DM9000A驱动调试(解决网卡无法接收数据问题)

本文介绍了DM9000A网络芯片驱动的调试过程,包括解决无法获取MAC地址的问题及TFTP下载数据异常的原因。通过修改代码实现自定义MAC地址,并详细分析了接收数据函数中出现重复数据包问题的解决方案。

DM9000A驱动调试

 

dm9000x.cdm9000x.h文件中包含了网络芯片的收发函数,但是该驱动是基于DM9000的,需要做更改才能适合于DM9000A

首先遇到的问题是DM9000A驱动无法获得MAC地址

Uboot在配置文件中有MAC地址的定义:

#define CONFIG_ETHADDR  08:00:3e:26:0a:5b

奇怪的是这里怎么无法获得呢?查看源代码发现获得MAC地址部分的代码如下:

for (i = 0; i < 6; i++)

 ((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);

原来Uboot要调用read_srom_word()函数从外面PHY中读取,反正芯片中已经集成了PHY,我们只需要设置PHYMAC地址就可以了,代码更改如下:

unsigned char env_enetaddr[6];

 char *tmp = getenv ("ethaddr");

 // 将环境变量中保存的mac地址转换成数字

for (i=0; i<6; i++) { 

  env_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;

  if (tmp)

   tmp = (*end) ? end+1 : end;

 }

 

// 保存mac地址

for (i = 0; i < 6; i++)

  ((u16 *) bd->bi_enetaddr)[i] = env_enetaddr[i];

这样DM9000A驱动就会使用我们配置的mac地址了。

接下来调试TFTP下载数据。

我在刚开始调试的时候发现使用TFTP总是不能正常下载数据,我以为是我设置的总线的访问时序上有问题,后来更改了读写访问延迟时间,已经放到了最大,但还是不能正常下载。打开网络调试开关,发现ARP获得了对方的MAC,但是到了开始传输数据的时候,主机发送下来的数据本机接受不到,然后主机发送第二次,本机才收到,然后返回确认,这样每发送一包数据就要有几秒钟的延迟,问题肯定出在网络接收处。

接下来我增加了调试tftp.c文件,发现接受到的数据和上次接受的数据的包号相同,当接受到同样的数据包的时候,网络的处理方法是丢弃,等待上位机机重新发送,难怪当时不返回,原来是给丢掉了!

这样就到了DM9000A的驱动部分代码。

DM9000A的接收数据函数:

eth_rx(void)

{

 u8 rxbyte, *rdptr = (u8 *) NetRxPackets[0];

 u16 RxStatus, RxLen = 0;

 u32 tmplen, i;

// DM9000A接收缓冲区中的数据格中格式是4字节的包头+真正的数据.

// 其中4字节包头分别位为: rxbyte, status, count_low, count_hight

// 说明如下:

// rxbyte: 0-没有接收到数据, 1-有新的数据包

// status: 状态

// count_low, count_hight: 接收到的数据长度

 /* Check packet ready or not */

 DM9000_ior(DM9000_MRCMDX);  // 设置读取SRAM数据, 内部地址不递增

 rxbyte = DM9000_inb(DM9000_DATA); // 读取查看是否有数据接收到

 if (rxbyte == 0)

  return 0;

 // rxbyte值必须是0或者1, 其它值不正确, 这里检测其它值的情况

 if (rxbyte > 1) {

  DM9000_iow(DM9000_RCR, 0x00); /* Stop Device */

  DM9000_iow(DM9000_ISR, 0x80); /* Stop INT request */

  DM9000_DBG("rx status check: %d/n", rxbyte);

 }

 DM9000_DBG("receiving packet/n");

 /* A packet ready now  & Get status/length */

 DM9000_outb(DM9000_MRCMD, DM9000_IO);

#ifdef CONFIG_DM9000_USE_16BIT

 RxStatus = DM9000_inw(DM9000_DATA); // 获得接收的状态

 RxLen = DM9000_inw(DM9000_DATA);  // 获得数据包长度

#endif

    // 接下来进行数据解析的处理…

 在初始化的时候,设置IMR寄存器的bit71RXSRAM0x0C00开始,当到达16K时,读取数据的地址重新返回到0x0C00位置。上面的代码在DM9000上工作的好好的,为什么到了DM9000A上就不能正常工作了呢?

 仔细看DM9000Adatasheet发现存在另外两个寄存器,位置在0xF40xF5,上面解释说当IMR寄存器的bit71时,内存数据地址将被设置成0x0C00,也就是说读取这两个寄存器能导致数据读取的地址指针复位,于是就在读取状态位之前重新设置一下地址指针,代码如下:

u16 temp;

 temp=DM9000_ior(DM9000_MRRH); // 读取这两个寄存器

 temp=DM9000_ior(DM9000_MRRL);

 加上以上三行代码后DM9000A工作正常了,看来就是这个原因。费了这么大的周折,原来是这里出的毛病!

 

 

有一个问题还是没有搞清楚:

 

 

 

 

DM9000Datasheet上的RXRAM说明如下:

 

也就是说接收完成一包数据后,下一包数据将接着上一包数据的结束地址保存,那么在读取的过程中就不需要重新对RX RAM的地址指针进行重新复位,就像一个大的FIFO一样读取,但为什么对于DM9000A

 

 

 

文章出处:DIY部落(http://www.diybl.com/course/6_system/linux/Linuxjs/200888/135101.html)

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值