utu2440 vxWorks DM9000A驱动移植


1.从网上下载一个DM9000A的BSP,查看源代码分析网卡初始化流程,具体修改代码。

2.根据原理图确定DM9000的基地址,utu2440使用的是CS3片选,首先确定基地址为0x18000000,对网

 

卡操作的地址为0x18000000+0x300(经测试不加0x300偏移也行,网上说是为了兼容ISA),IOBASE即

 

为0x18000000,IODATA为0x18000000+0x04。首先保证操作的地址是正确的,然后修改DM9000_IN_ADDR

 

、DM9000_IN_ADDR、DM9000_OUT_ADDR、DM9000_IN_BYTE、DM9000_OUT_BYTE、DM9000_IN_WORD、

 

DM9000_OUT_WORD、DM9000_OUT_CHAR、DM9000_IN_CHAR这些宏定义,因为DM9000是地址控制复用了,

 

所以写命令时先写控制信号,再写数据信号。

 

 1  #define  DM9000_IN_CHAR(addr,data)\
 2 
 3  { \
 4 
 5      ( * ( volatile  UCHAR   * )(DM9000_IOADDR)  =  addr); \
 6 
 7      (data  =   * ( volatile  UCHAR   * )(DM9000_IODATA)); \
 8 
 9  }
10 
11   
12 
13  #define  DM9000_OUT_CHAR(addr,value)\
14 
15  { \
16 
17      ( * ( volatile  UCHAR   * )(DM9000_IOADDR)  =  addr); \
18 
19      ( * ( volatile  UCHAR   * )(DM9000_IODATA)  =  value); \
20 
21  }
22 

 

 

查看原理图得知dm9000中断接在了2440的EINT9上。

 

3.修改网卡名,要和DEFAULT_BOOT_LINE中使用的启动设备一致,否则提示WDB: Agent configuration 

 

failed.无法启动网络设备。

#define DEFAULT_BOOT_LINE \

    "dmf(0,0) host:vxWorks h=192.168.1.221 e=192.168.1.221:ffffff00 tn=mxd",dmf为网卡名

 

 

4.修改configNet.c让系统自动加载自己的网络设备,仿照已有的在END_TBL_ENTRY endDevTbl []中加

 

 

1  #ifdef INCLUDE_DM9000_END
2 
3      {  0 ,DM9000_LOAD_FUNC_0,DM9000_LOAD_STRING_0,  0  , NULL, FALSE},
4 
5  #endif
6 

 


主要这两个参数:

<1>DM9000_LOAD_FUNC_0为dm9000驱动加载入口函数,XXXLoad()。

<2>DM9000_LOAD_STRING_0为网卡配置参数,在Prease解析函数中用到,主要为了intEnable和

 

intConnect使用的,告诉vxWorks将相应的中断挂接起来。

 

5.检查网卡配置函数dm9000Config()确认将网卡正确初始化了,主要参考DM9000 DataSheet。修改

 

dm9000Start()函数,原来的start中调用了一个cpuForDM9000Init函数将EINT7初始化并使能EINT7,

 

仿照他的改写成EINT9的初始化并使能。将intEnable(4)改成intEnable(5),EINT8-23共享一个位。

函数最后使能网卡使其接受发送中断DM9000_OUT_CHAR( 0xff, DM9000_REGFF ),修改宏定义

 

DM9000_REGFF 0x83为0x81使得这里只使能接受中断。

 

6.将ISR全部注释,只点灯。

 

7.测试发现每次ping过去shell会成“死”的状态,并且ISR里面点的灯并未点亮。将中断使能语句屏

 

蔽,检查其他寄存器设置,发现都没问题。检查网卡的状态寄存器,有中断时相应位都正确置位,中

 

断管脚经测量电压为3.24高电平状态,判断出芯片是正常接收中断的。

 

8.改测试网卡发送,使用了sendto系统调用,编写简单的UDP广播发送函数,发现第一个数据包可以正

 

常送出,连着以后的都会打印tx full,检查错误信息来源为dmfe_start_xmit函数,由于CPU向

 

DM9000E发送数据的速度较快时,一个缓冲区会忙不过来,就会出现“tx full”,然后网卡工作不正

 

常,无法继续进行通信。

测试UDP发送正常。

 

 1       if  (dev -> tx_pkt_cnt  ==   0
 2 
 3      {    
 4 
 5     
 6 
 7     dev -> tx_pkt_cnt  ++ ;
 8 
 9     
10 
11     DM9000_OUT_CHAR(  0xfc , skb -> len  &   0xff  );
12 
13     DM9000_OUT_CHAR(  0xfd , (skb -> len  >>   8 &   0xff  );
14 
15     
16 
17     DM9000_OUT_CHAR(  0x2 0x01  );        
18 
19      }
20 
21       else
22 
23      {
24 
25          dev -> queue_pkt_len  =  skb -> len;
26 
27          dev -> tx_pkt_cnt  ++ ;
28 
29      }
30 

 

 

9.到此说明网卡能正常工作,再调试中断接收,中间自己写了EINT0、1(对应KEY 0、1)的中断连接

 

到isr,能正常进入isr,检查中断寄存器查看是否在网卡工作期间EINT9对应为被改变了或者占用了,

 

启动后:

 

 1  INTMSK  0x4A000008   =   0xee7ff9bd
 2 
 3  INTMOD  0x4A000004   =   0x00000000
 4 
 5  EINTMASK  0x560000A4   =   0x00fffff0
 6 
 7  EINTPEND  0x560000A8   =   0x00000000
 8 
 9  SRCPND  0x4A000000   =   0x0000000d
10 

 


都很正常,在shell下将EINT9相关寄存器置位,出现死的情况,isr无反应。最后,检查了BSP里面

 

intEnable的实现,中断控制程序位于s3cIntrCtl.c,每次有中断发生系统都会调用里面的

 

s3c2410xIntLvlVecChk函数,由于前面测试的都是只有一级的中断,所以对于只有一个控制位的外部

 

中断是处理正确的,而EINT9是有两个控制位的,因此要检查s3c2410xIntLvlVecChk的实现,每次有中

 

断都会自动去清除相应位,s3c2410x_INT_REG_WRITE(S3C2410X_SRCPND, (1<<tempUINT32)); 

 

s3c2410x_INT_REG_WRITE(S3C2410X_INTPEND, (1<<tempUINT32));而对于有两个屏蔽位的EINT9并没有

 

清除或屏蔽相关中断,造成不停的中断死的状态。在里面添加:

if((1<<tempUINT32)&(1<<INT_LVL_EXTINT8_23))

{

rEINTMASK = 0x00fffff0;

}

判断有EINT8_23中断时先屏蔽二级的,在INTMSK、INTPND和SRCPND寄存器里面,外部中断EINT8_23分

 

别只对应一个控制位,然后在EINTMASK、EINTPND再对具体是那一个外部中断进行处理。中断接收测试

 

成功,在中断退出前还得打开rEINTMASK,否则只能进一次。为了保险在中断进入后intDisabel(5),

 

在最后清除中断和intEnable(5)(打开INTMSK)。

 

10.ping测试:

Pinging 192.168.1.221 with 32 bytes of data:

 

Reply from 192.168.1.221: bytes=32 time=3ms TTL=64

Reply from 192.168.1.221: bytes=32 time=1ms TTL=64

Reply from 192.168.1.221: bytes=32 time=1ms TTL=64

Reply from 192.168.1.221: bytes=32 time=1ms TTL=64

 

Ping statistics for 192.168.1.221:

    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),

Approximate round trip times in milli-seconds:

    Minimum = 1ms, Maximum = 3ms, Average = 1ms

你可能感兴趣的:(驱动)