最近在将u-boot1.3.4移植到三星s5pc100 SOC平台发现u-boot启动之后无法ping通主机,也不能用tftp下载内核。硬件平台用的网卡芯片是dm9000aep,这是一款全集成,性价比高的快速以太网MAC控制器,支持8-bit和16-bit数据宽度,带有一个通用处理器接口,EEPROM接口,10M/100M自适应,带有16KB的SRAM(13KB作为接受FIFO,3KB作为发送FIFO)。Dm9000a在嵌入式平台中应用非常广。
因为在开发过程中我们需要经常修改重新编译Linux内核,所以每次改完之后都重新烧写内核到nandflash里面很麻烦。所以一定要解决u-boot对dm9000a网卡的支持问题。
我们首先需要确定硬件上有没有问题。鉴于Linux内核启动之后可以通过nfs挂在根文件系统,并且工作正常,所以可以确定内核对dm9000a的支持是没问题的,也就是说硬件上没有问题。接下来将注意力集中到软件上。
我首先怀疑是u-boot下对dm9000a的驱动有问题。找到驱动源代码:driver/net/dm9000x.c。 在代码一开始的注释中说“Fixed the driver to work with DM9000A”。看了之后很疑惑,既然源码作者都说他的驱动已经支持了DM9000A,那为什么网卡在u-boot下还不能工作?带着半信半疑的态度我进去查看源代码。首先最重要的网卡初始化的代码,在函数eth_init()中,这里面主要是设置网卡的工作模式,数据总线宽度,设置MAC地址并使能网卡等工作。为了确认这段代码是否正确,我又查看了Linux内核中DM9000A的驱动代码dm9000.c,发现两者在关键部分的设置都是一样的,只不过内核里面采用中断的工作模式,而在u-boot中采用轮询的工作模式。如果初始化代码没有问题的话,我继续查看关键的接收以及发送函数,即eth_send()和eth_rx(),发现这两部分也和内核里面是一样的。
这下我就更加困惑了,似乎驱动代码是没有问题的,但是问题出在什么地方呢?为了深入的分析原因,我打开了DM9000a的调试接口宏:define CONFIG_DM9000_DEBUG。然后在超级终端ping我的主机,ping的时候会调用eth_init()激活网卡,终端打印出下面的初始化信息:
Dm90000 i/o : 0x88000300, id : 0x90000a46
Dm9000 : running in 16 bit mode
MAC : 11:22:33:44:55:66
Operating at 100M full duplex mode
看来初始化是没有问题的,可以读出id号这说明s5pc100和dm9000a数据交互肯定没有问题。但是ping还是会失败。之后打印的信息如下所示:
Transmit done
Receiving packet
Rx status: 0x0101 rx len: 24158
Rx fifo error
Rx length too big