在新研NXX板上使用了若干片C6414,其中有两片用EMIFB接口连接DM9000芯片扩展出网口,上层采用LwIP协议栈。因此需要移植LwIP协议栈和DM9000的驱动。手头有老板上验证过的代码,但是在CCS3.3环境下开发。
采用的开发环境仍然是CCS5.4,需要做的主要工作有:
1. 建立基础工程,并将整个Lwip源码拷贝到工程目录,然后删除一些不需要的文件,包括IPV6和SLIP等
2. 在工程包含路径中添加Lwip目录下的include和include/ipv4
3. 将cc.h和main.c中包含的工程名相关cfg.h修改名称
4. 由于更改了general.h的bool类型定义,将true和false修改为TRUE和FALSE
5. NPU上的DM9000连接CMD的是A15,而非原来的A2,代码中对应做修改
6. NPU上的DM9000的INT连接到GP7,而非原来的GP5,代码中对应做修改
做完这些修改后编译通过,开始测试。测试过程遇到了许多的问题。
首先读VID和PID,结果读出值为全1。分析代码没有发现问题,于是祭出示波器。测量CMD、CS、IOR等信号,发现CS和IOR正常,但CMD没有信号。从代码中找与CMD相关的代码,最终发现CMD是通过一个地址触发的,地址值计算错误。更正后PID和VID都读取正常。
然后插上网线用底层驱动发送一个自组的ARP包,在与之直连的PC机上用WireShark抓包,结果抓不到。发现网口上的灯不亮,说明底层硬件协商有问题。仔细读手册发现本板上采用的DM9000芯片升级为DM9000C,寄存器与原DM9000有差异,如ISR寄存器的bit7是IO模式位,代码中为bit6,对照文档做了一些修改。同时上网查找到Linux下的驱动,仿照初始化过程做了修改。最后初始化完成灯亮。
再次进行ARP包的收发,发现DM9000收到的数据间隔丢失一字节,而Wireshark抓包线上的数据正常。因此问题出在DM9000到CPU的过程。DM9000有一个EECS输入引脚,当拉高时,内部存储器位宽为8bit,拉低时为16bit,怀疑是这项设置不正常。在板上焊为低,飞线将其拉高后测试,发现初始化即错误,读出的ID变为全1。
这时的怀疑点集中在新旧芯片的寄存器不一致上,花费了很长时间逐一对比和尝试配置寄存器,仍未能解决问题。
最后终于想到,是不是EMIF的配置有问题呢?查询手册发现默认为8bit,而老版本的代码中没有找到对EMIF有配置。询问原开发人员得知老版CCS3.3中会自动生成配置代码,在某文件夹下。将这段代码拷贝过来添加到启动过程中,则收发数据均无误。
接下来开始PING试验,直连机可以ping通本板。但是一段时间后DSP复位,原因不明。
把LwIP模块移除,长期运行未发现复位现象,因此初步定位为LwIP内的问题。开启LwIP的调试打印,未找到明显迹象。单独去掉接收中断和接收处理函数,不再重启;单独去掉发送函数和发送中断,依旧重启。因此问题定位在接收方向。
重点看接收方向的几个函数。在接收中断中抛出信号量,某进程ethernetif_input等待信号量后调用low_level_input接收一帧数据,交给上层处理,处理完成后如果还有新数据,接收再处理,如果没有,则挂起继续等待中断。
在这里做了多次修改删减调试,如只做信号量操作,不去真正读取数据等,均无果。最后在梳理LwIP的初始化流程时发现创建该进程时,只分配了256字节的栈,显然太小。将其改大到1024字节,再次长期运行,不再出现问题。
之前遇到过一些栈过小引发的问题。在有操作系统时某些情况下SYS/BIOS的调试模块会明显打印出stack overflow等信息。还有一次协助别人调试算法时,栈太小导致每次从某个函数返回时系统就崩溃。这些现象都比较明确,容易定位。但像这次一样,问题发生时悄无声息,之后的莫名时间里又突然出现,这种现象才最是头疼。只能在编码时间慎之又慎,避免给自己和后人挖坑。