在mini2440上移植DM9000E网卡的参考步骤如下:
一、看电路图
在mini2440开发板上移植好Linux-2.6.29.1内核和根文件系统的基础上,进行网卡DM9000E的移植,因为手里面有韦东山写的《嵌入式Linux应用开发完全手册》一书,在书中找到了DM9000网卡移植部分,对照该书与友善光盘里面的原理图,移植之前先从看原理图开始。看了DM9000E与S3C2440的电路图发现:
1、DM9000E挂接到S3C2440总线
S3C2440通过总线来访问DM9000E。mini2440访问DM9000E的物理地址的基址是BANK4,用到一条地址线ADDR2,对应DM9000E的CMD引脚,,因为DM9000E的地址信号和数据信号复用,CMD引脚决定传输的是地址信号还是数据信号,于是地址线ADDR2的引脚状态决定了DM9000E与S3C2440传输的是地址信号还是数据信号。
2、总线位宽16,用到nWAIT信号
3、DM9000E收到完整的数据包,通过中断引脚通知S3C2440来接收数据包,与S3C2440相连的中断引脚为EINT7。
二、网卡驱动程序修改
修改内核中网卡驱动程序时需要先结合所使用的内核,先查看当前内核是否支持该网卡,如果不支持需要查找支持该网卡的驱动程序进行修改。我用的是Linux-2.6.29.1内核,该内核已经对DM9000E具有很好的支持了,这在内核的Documentation/networking/dm9000.txt中有对内核中dm9000驱动程序详细地说明,其中如下部分说明Linux-2.6.29.1内核对DM9000E网卡的友好支持。
一些低版本的内核(比如linux-2.6.13等)对DM9000E不支持,可以用其它内核版本的dm9000.c驱动程序添加到内核中,进行修改和配置。由于这里使用的内核已经对DM9000E网卡具有很好的支持,只需简单的配置和修改即可。
1、修改DM9000平台设备
修改/arch/arm/plat-s3c24xx/common-smdk.c文件
(1)、添加要包含的头文件
#if defined(CONFIG_DM9000) ||
defined(CONFIG_DM9000_MODULE)
#include
#endif
(2)、添加DM9000的平台设备结构
#if defined(CONFIG_DM9000) ||
defined(CONFIG_DM9000_MODULE)
/*DM9000*/
static struct resource
s3c_dm9k_resource[]={
[0] = {
.start = S3C2410_CS4, //ADDR2 = 0
.end = S3C2410_CS4 + 3,
.flags = IORESOURCE_MEM,
},
[1] = {
.start = S3C2410_CS4 + 4, //ADDR2 = 1
.end = S3C2410_CS4 + 4 + 3,
.flags = IORESOURCE_MEM,
},
[2] = {
.start = IRQ_EINT7,
.end = IRQ_EINT7,
.flags = IORESOURCE_IRQ,
}
};
static struct dm9000_plat_data s3c_dm9k_platdata =
{
.flags = DM9000_PLATF_16BITONLY,
};
static struct platform_device s3c_device_dm9k =
{
.name = "dm9000",
.id = 0,
.num_resources =
ARRAY_SIZE(s3c_dm9k_resource),
.resource = s3c_dm9k_resource,
.dev = {
.platform_data = &s3c_dm9k_platdata,
}
};
#endif
(3)、将DM9000平台设备加入内核设备列表中
/* devices we initialise */
static struct platform_device __initdata *smdk_devs[] =
{
&s3c_device_nand,
&smdk_led4,
&smdk_led5,
&smdk_led6,
&smdk_led7,
#if defined(CONFIG_DM9000) ||
defined(CONFIG_DM9000_MODULE)
&s3c_device_dm9k,
#endif
};
2、修改drivers/net/dm9000.c
dm9000.c中包含dm9000_probe函数,该函数完成DM9000设备的枚举,dm9000_probe函数的介绍在《嵌入式Linux应用开发完全手册》一书中详细介绍。
(1)、添加必要的头文件
#if defined(CONFIG_ARCH_S3C2410)
#include
#endif
在《嵌入式Linux应用开发完全手册》一书中上面的#include是#include ,这使得我编译通不过,被我改成#include后编译成功,这是不同版本内核文件的程序所在文件的差别造成。
(2)、在dm9000_probe中设置存储器使BANK4可用,设置默认MAC地址(也可以在根文件系统启动脚本设置),添加的代码如下:
/*
* Search DM9000 board, allocate space and register
it
*/
static int __devinit
dm9000_probe(struct platform_device *pdev)
{
…
#if defined(CONFIG_ARCH_S3C2410)
unsigned int oldval_bwscon; //用来保存BWSCON寄存器的值
unsigned int oldval_bankcon4; //用来保存S3C2410_BANKCON4寄存器的值
#endif
…
#if defined (CONFIG_ARCH_S3C2410)
//设置BANK4:总线宽度为16,使能nWAIT
oldval_bwscon = *((volatile unsigned int
*)S3C2410_BWSCON);
*((volatile unsigned int *)S3C2410_BWSCON) =
(oldval_bwscon & ~(3<<16)) /
| S3C2410_BWSCON_DW4_16 | S3C2410_BWSCON_WS4 |
S3C2410_BWSCON_ST4;
//设置BANK4的时间参数
oldval_bankcon4 = *((volatile unsigned int
*)S3C2410_BANKCON4);
*((volatile unsigned int *)S3C2410_BANKCON4) =
0x1f7c;
#endif
…
if
(!is_valid_ether_addr(ndev->dev_addr))
dev_warn(db->dev, "%s: Invalid ethernet MAC address.
Please "
"set using ifconfig/n", ndev->name);
#if defined(CONFIG_ARCH_S3C2410)
printk("Now use the default MAC
address:08:90:90:90:90:90/n");
ndev->dev_addr[0] = 0x08;
ndev->dev_addr[1] = 0x90;
ndev->dev_addr[2] = 0x90;
ndev->dev_addr[3] = 0x90;
ndev->dev_addr[4] = 0x90;
ndev->dev_addr[5] = 0x90;
#endif
…
out:
printk("%s:not found
(%d)./n",CARDNAME,ret);
#if defined(CONFIG_ARCH_S3C2410)
*((volatile unsigned int *)S3C2410_BWSCON) =
oldval_bwscon;
*((volatile unsigned int *)S3C2410_BANKCON4) =
oldval_bankcon4;
#endif
(3)、指定注册中断时的触发方式
dm9000_open(struct net_device *dev)
{
…
irqflags |= IRQF_SHARED;
#if defined (CONFIG_ARCH_S3C2410)
if(request_irq(dev->irq,&dm9000_interrupt,IRQF_SHARED|IRQF_TRIGGER_RISING,dev->name,dev))
#else
if(request_irq(dev->irq,&dm9000_interrupt,IRQF_SHARED,dev->name,dev))
#endif
//if (request_irq(dev->irq, &dm9000_interrupt,
irqflags, dev->name, dev))
return -EAGAIN;
…
}
三、在内核中增加对网卡DM9000的配置
在内核目录下执行“make
menuconfig”命令进行如下的配置:
Device Drivers--->
[*]Network device support--->
[*]Ethernet(10 or 100Mbit)--->
<*>DM9000 support
[*]Networking support--->
Networking options--->
<*>TCP/IP networking
<*>IP:kernel leel autoconfiguration
//增加对nfs的支持
File systems--->
[*]Networking File Systems--->
<*>NFS client support
[*]NFS client support for NFS version 3
[*]NFS client support for the NFSv3 ACL protocol
extension
[*]Boot file system on NFS
[*]NFS server support
四、修改根文件系统启动脚本rcS
在根文件etc/init.d/rcS文件中添加如下:
echo "network interface"
/sbin/ifconfig lo 127.0.0.1
/sbin/ifconfig eth0 192.168.1.230 up
route add default gw 192.168.1.1
五、测试和修改
至此,将修改过的内核和根文件系统下载到mini2440开发板,启动时出现如下信息:
----------munt all----------------
network interface
dm9000 dm9000.0: WARNING: no IRQ resource flags
set.
eth0: link up, 10Mbps, half-duplex, lpa
0x0021
***********************************************
****************Studying
ARM*********************
Kernel version:linux-2.6.29.1
Student:Feng dong rui
Date:2009.07.15
***********************************************
Please press Enter to activate this console.
[MrFeng]#
1、测试
Please press Enter to activate this console.
[MrFeng]#ifconfig -a
eth0 Link encap:Ethernet HWaddr 10:23:45:67:89:AB
inet addr:192.168.1.230 Bcast:192.168.1.255
Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500
Metric:1
RX packets:1506 errors:0 dropped:0 overruns:0
frame:0
TX packets:0 errors:0 dropped:0 overruns:0
carrier:0
collisions:0 txqueuelen:1000
RX bytes:101460 (99.0 KiB) TX bytes:0 (0.0
B)
Interrupt:51 Base address:0x8000
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:6 errors:0 dropped:0 overruns:0
frame:0
TX packets:6 errors:0 dropped:0 overruns:0
carrier:0
collisions:0 txqueuelen:0
RX bytes:504 (504.0 B) TX bytes:504 (504.0
B)
[MrFeng]#ping 127.0.0.1
PING 127.0.0.1
(127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: seq="0" ttl="64" time="1".004
ms
64 bytes from 127.0.0.1: seq="1" ttl="64" time="0".518
ms
64 bytes from 127.0.0.1: seq="2" ttl="64" time="0".436
ms
^C
--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet
loss
round-trip min/avg/max = 0.436/0.652/1.004
ms
[MrFeng]#ping 192.168.1.103
PING 192.168.1.103
(192.168.1.103): 56 data bytes
64 bytes from 192.168.1.103: seq="0" ttl="64"
time="2".098 ms
64 bytes from 192.168.1.103: seq="1" ttl="64"
time="1".342 ms
64 bytes from 192.168.1.103: seq="2" ttl="64"
time="0".823 ms
^C
--- 192.168.1.103 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet
loss
round-trip min/avg/max = 0.823/1.421/2.098
ms
//挂载网络文件系统
[MrFeng]#mount -t nfs -o nolock 192.168.1.103:/opt/nfs
/mnt
[MrFeng]#ls /mnt
pic.jpg
[MrFeng]#umount /mnt
[MrFeng]#ls /mnt
[MrFeng]#
注:在挂载网络文件系统时先要在Linux系统下设置共享目录才能在从开发板挂载该目录,这里已经在虚拟机下Redhat9.0系统中的/opt下设置了共享目录nfs,虚拟机的ip为192.168.1.103,故通过mount -t nfs -o
nolock 192.168.1.103:/opt/nfs /mnt命令挂载。
2、曾经出现的问题
(1)、ping不同局域网内其它主机,ping自己也有时会出现如下问题:
[ ] (s3c_irq_demux_extint4t7+0x0/0xa8) from [
] (asm_do_IRQ+0x
44/0x5c)
r4:c03c2350
[ ] (asm_do_IRQ+0x0/0x5c) from [ ]
(__irq_svc+0x24/0xa0)
Exception stack(0xc2e2bd98 to 0xc2e2bde0)
bd80: 00000000 fb000000
bda0: 00000001 00000000 c03c2a18 00000033 40000013
00000080 00000033 00000000
bdc0: c39bfc80 c2e2be10 c2e2bdbc c2e2bde0 c007320c
c0072748 60000013 ffffffff
r7:00000080 r6:00000010 r5:f4000000 r4:ffffffff
[ ] (setup_irq+0x0/0x248) from [ ]
(request_irq+0xb0/0xcc)
[ ] (request_irq+0x0/0xcc) from [ ]
(dm9000_open+0x16c/0x23c)
[ ] (dm9000_open+0x0/0x23c) from [ ]
(dev_open+0xa8/0x10c)
[ ] (dev_open+0x0/0x10c) from [ ]
(dev_change_flags+0x98/0x164
)
r5:00000000 r4:c382b800
[ ] (dev_change_flags+0x0/0x164) from [
] (devinet_ioctl+0x2f0
/0x708)
r7:bed9ba88 r6:c39fdf00 r5:00000000 r4:ffffff9d
[ ] (devinet_ioctl+0x0/0x708) from [
] (inet_ioctl+0xc0/0xf4)
[ ] (inet_ioctl+0x0/0xf4) from [ ]
(sock_ioctl+0x1e4/0x244)
[ ] (sock_ioctl+0x0/0x244) from [ ]
(vfs_ioctl+0x3c/0x84)
r7:00000003 r6:00008914 r5:ffffffe7 r4:c2d1a420
[ ] (vfs_ioctl+0x0/0x84) from [ ]
(do_vfs_ioctl+0x284/0x2a4)
r6:00000000 r5:bed9ba88 r4:c2d1a420
[ ] (do_vfs_ioctl+0x0/0x2a4) from [
] (sys_ioctl+0x40/0x5c)
r7:00000036 r6:00008914 r5:fffffff7 r4:c2d1a420
[ ] (sys_ioctl+0x0/0x5c) from [ ]
(ret_fast_syscall+0x0/0x2c)
r6:00000000 r5:00159dec r4:00159d5c
出现这个问题的原因是我没将中断的触发方式按照默认的,没有改成上面修改的。
(2)、挂载不了网络文件系统
可能的原因:检查内核的配置中是否选中对NFS的支持,Linux主机是否能连通局域网并设置了共享目录,硬件的链接是否良好。还有就是Linux主机的防火墙是否关闭,nfs服务是否已经开启。
六、参考资料
在学习的过程中,参考了韦东山写的《嵌入式Linux应用开发完全手册》一书,该书我觉得虽然没有把很多东西讲得很详细,嵌入式Linux的书也不可能在一本书上讲得详细,但我每想做什么就不自觉的翻阅它,对我来说非常具有参考价值。另外就是网上的一些热心网友的博客、帖子上的内容给了我很多参考,结合“百家之长”解决问题,网上的资料很多,不一一列举。
以上为复制。
今天步骤
1.按照韦东山写的《嵌入式Linux应用开发完全手册》,并把miniarm dm9000.c #if defined (CONFIG_ARCH_S3C2410)
#endif 宏里的直接复制到 linux 2.6.34 dm9000.c中。开始图省事,把dm9000.c dm9000.h,直接替换,并把include/linux/netdevice.h 也替换,并不成功。还是按照韦东山自己修改,成功。
2.修改文件系统 /etc/init.d/rcS
3.mount 成功
4.试hello。ko驱动。