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是地址控制复用了,
所以写命令时先写控制信号,再写数据信号。
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 []中加
入
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发送正常。
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对应为被改变了或者占用了,
启动后:
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