历史上的今天
今天是:2024年11月10日(星期日)
2021年11月10日 | Linux2.6.32移植到MINI2440(4)移植+分析DM9000网卡驱动
2021-11-10 来源:eefocus
开发环境:
主机:fedora 14
虚拟机:vmware workstation 10
交叉编译工具:arm-linux-gcc 4.3.2
开发板:mini2440(2m nor ,64m sdram,256m nand)
内核版本:linux2.6.32.2
上一篇帖子的uImage可以起yaffs2文件系统,但是起不了nfs,我的yaffs2使用nfs打包来的,换一个内核可以起,bootargs也没有问题,可能是这里网卡没有移植造成的,移植结束之后再看能不能起,因为nfs对后面做驱动开发优势比较大,方便调试看现象,不需要每次都烧写进去,所以还是需要能够起nfs的。DM9000内核其实已经是支持了,我们需要根据mini2440的具体的硬件资源做添加和修改。
首先,明确一下mini2440上dm9000的硬件资源,dm9000是直接挂在s3c2440的bank4上面,连接了16条数据线,1条地址线,这条地址线判断是地址还是数据传输,然后通过16条数据线来传输,也就是复用。
一、添加头文件
在mach-mini2440.c中:
添加头文件如下:
#include 二、添加物理基地址宏定义 #define MACH_MINI2440_DM9K_BASE (S3C2410_CS4+0X300) 这个地址是怎么来的呢,这里S3C2410_CS4指的是BANK4的起始地址:0x20000000,后面加上0x300一开始我理解的是,就像我们烧写到sdram的时候虽然sdram挂在0x30000000上,我们烧写的时候还是会留点余地,烧写到0x30008000,这里的0x300和这个是一个意思,但是不超过128M,这样就到下一个BANK去了。 三、添加mini2440_dm9k_resource static struct resource mini2440_dm9k_resource[]={ [0] = { .start = MACH_MINI2440_DM9K_BASE, .end = MACH_MINI2440_DM9K_BASE+3, .flags = IORESOURCE_MEM }, [1] = { .start = MACH_MINI2440_DM9K_BASE_4, .end = MACH_MINI2440_DM9K_BASE+7, .flags = IORESOURCE_MEM }, [2] = { .start = IRQ_EINT7, .end = IRQ_EINT7, .flags = IORESOURCE_IRQ|IORESOURCE_IRQ_HIGHEDGE, } }; 这个函数是为了填充平台资源,以便和DM9000接口配合起来。 MACH_MINI2440_DM9K_BASE存放的是要发送的地址,MACH_MINI2440_DM9K_BASE+4存放的是要发送的数据,因为是地址和数据复用,所以要分开传送,两次,0代表地址,1代表数据。一个地址需要四个字节传送,所以每次end都要在start基础上+3,这样就是四个字节的大小。数组2则是跟中断有关的资源。 三、设置传送总线位宽 static struct dm9000_plat_data mini2440_dm9k_pdata = { .flags = (DM9000_PLATF_16BITONLY|DM9000_PLATF_NO_EEPROM), }; 四、添加设备注册函数 static struct platform_device mini2440_device_eth = { .name = "dm9000", .id = -1, .num_resources = ARRAY_SIZE(mini2440_dm9k_resource), .resource = mini2440_dm9k_resource, .dev = { .platform_data = &mini2440_dm9k_pdata, }, }; 五、添加平台设备函数 在mini2440_devices[]中: static struct platform_device*mini2440_devices[] __initdata = { &s3c_device_usb, &s3c_device_lcd, &s3c_device_wdt, &s3c_device_i2c0, &s3c_device_iis, &s3c_device_nand, &s3c_device_eth, }; 六、修改drivers/net/dm9000.c文件 添加头文件: #ifdefined(CONFIG_ARCH_S3C2410) #include #endif 修改dm9000_init函数: staticint __init dm9000_init(void) { #if defined(CONFIG_ARCH_S3C2410) unsigned intoldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON; unsigned intoldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4; *((volatile unsigned int*)S3C2410_BWSCON) = (oldval_bwscon&~(3<<16))|S3C2410_BWSCON_DW4_16|S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4; *((volatile unsigned int*)S3C2410_BANKCON4) = 0x1f7c; #endif printk(KERN_INFO "%s Ethernet Driver,V%sn", CARDNAME, DRV_VERSION); return platform_driver_register(&dm9000_driver); } 这里: unsigned int oldval_bwscon = *(volatile unsigned int *)S3C2410_BWSCON; unsigned intoldval_bankcon4 = *(volatile unsigned int *)S3C2410_BANKCON4; 是将两个寄存器的值保存,volatile是防止编译器因为优化省略掉它,要保证每次都去读他的值。 下面首先设置BWSCON,可以查看datasheet: 这里,oldval_bwscon&~(3<<16)是保留原来寄存器的值,但是对16,17位清零,然后|S3C2410_BWSCON_DW4_16|S3C2410_BWSCON_WS4|S3C2410_BWSCON_ST4,这里的三个宏定义如下,在arch/arm/mach-s3c2410/include/mach/regs-mem.h: /*bank 4 configurations */ #defineS3C2410_BWSCON_DW4_16 (1<<16) #defineS3C2410_BWSCON_WS4 (1<<18) #defineS3C2410_BWSCON_ST4 (1<<19) 所以再对照datasheet就可知,设置总线位宽为16位,使能WAIT,使用UB/LB。 在下面对S3C2410_BANKCON4赋值0x1f7c,这个查看datasheet,可以找到寄存器: 这里0x1f7c分解开来就是:0001 1111 0111 1100,可以自行对照datasheet查看其含义。这里应该是跟时序有关的设置,具体不清楚的可以去网上搜dm9000时序相关的帖子,这里知道其含义,不做深究了。 七、修改dm9000_probe函数 if (!is_valid_ether_addr(ndev->dev_addr)){ /*try reading from mac */ mac_src= "chip"; for(i = 0; i < 6; i++) ndev->dev_addr[i]= ior(db, i+DM9000_PAR); } memcpy(ndev->dev_addr," x08 x90 x90 x90 x90 x90",6); if(!is_valid_ether_addr(ndev->dev_addr)) dev_warn(db->dev,"%s: Invalid ethernet MAC address. Please " "set using ifconfign",ndev->name); 红色字体为添加部分,大概在1463行。这其实添加“软”mac地址,不添加的话,可能无法挂在我们的nfs,很重要的哦。 八、编译测试 #make menuconfig DeviceDrivers à Networkdevice support à Ethernet(10or 100Mbit) à <*>DM9000 support #make zImage 转换成uImage烧写到开发板,这里我从nand启动,然后起了yaffs2之后使用ifconfig没有出来东西,然后我修改bootargs,这里我的是: setenv bootargs console=ttySAC0root=/dev/nfs nfsroot=192.168.1.122:/opt/rootfsip=192.168.1.226:192.168.1.122:192.168.1.122:255.255.255.0:SMDK2440A.arm9.net:eth0:off 然后重新启动,这时候我的nfs就起来了,输出如下信息: eth0:link down IP-Config: Complete: device=eth0, addr=192.168.1.226, mask=255.255.255.0, gw=192.168.1.122, host=SMDK2440A, domain=, nis-domain=arm9.net, bootserver=192.168.1.122, rootserver=192.168.1.122, rootpath= Lookingup port of RPC 100003/2 on 192.168.1.122 eth0:link up, 100Mbps, full-duplex, lpa 0xDDE1 Lookingup port of RPC 100005/1 on 192.168.1.122 VFS:Mounted root (nfs filesystem) on device 0:14. Freeinginit memory: 132K Pleasepress Enter to activate this console. Processing/etc/profile... Done / # / # ls bin etc linuxrc proc sys usr dev lib mnt sbin tmp var 移植分析结束,如有不正确的地方,还请指出来,大家共同进步! 

史海拾趣
|
bios设置HWI问题,请求各位前辈给指导一下!刚学DSP痛苦啊 我用dsp/bios设置的HWI 选择的是HWI_INT5,选择External_Pin_5作为interrupt soure function为:UART_isr Use Dispatcher选为true 设置完并保存,编译后发现错误 不是说在bios中添加硬件中断,系统会自动识别吗? 为什么会出现下面错误: un ...… 查看全部问答> |
|
采用RC振荡的方法非常多,如文氏桥振荡等。这里介绍几种笔者常用的方法: 1.最简单的振荡器 最简单的振荡器 这种振荡器特点是:T≈(1.4~2.3)R*C 电源波动将使频率不稳定,适合小于100KHz的低频振荡情况。 2.加补偿电阻的振荡 加补偿电阻 ...… 查看全部问答> |
|
1、原先用spansion的norflash s29GL032操作一切正常,先改为ST的M29W320的flash,在用jtag烧写uboot时,一直擦除不成功,我用的是片擦除,系统时钟为125M,指令如下 //16bit erase *(volatile UINT16 *)(AM_START_AD ...… 查看全部问答> |
|
大家点个思路,有关基于S3C2440和WinCE如何使用串口及SD卡的问题 大家好,谢谢大家这么些天来一直很热心的回答我的问题,十分感谢! 现在我想实现这样的功能: 外面通过串口将数据传给S3C2440,这里S3C2440跑的是WinCE操作系统,在WinCE上应用程序将数据接收处理并将其存入SD卡,并画出数据拟合成的曲线。 这里 ...… 查看全部问答> |
|
wince下如何进行驱动调试,一定要用串口么??如果程序修改的话还要重新编译内核? 1.现在刚准备做wince的,我现在有些不明白如何进行调试,每次定制内核要用到几十分钟,我在调试硬件驱动的时候,为了考虑稳定性需要不断得进行修改代码,每次修改代码之后都要重新编译内核,太耗时了,请问有没有什么简单得方法呢??模拟调试是不行的,我的 ...… 查看全部问答> |
|
ST新库3.4.0中stm32f10x.h里面为啥又把bool型定义去掉了? 写库的人到底怎么想的,去掉类型定义,原来的程序会不兼容,有脑子吗?我已经出离愤怒了,版主告诉我他们怎么想的 ...… 查看全部问答> |
|
安装已经老声音长谈了,但我觉得有再说明一下的必要。因为好的开始是成功的一半,好多都是安装不好。对以后的学习造成了很大损失。甚至不愿再涉及该种芯片。 首选安装IAR V6.10 ,这个再光盘里。有所不同的是,这个是日系的,首先第一项是 ...… 查看全部问答> |
|
转自丁国勇的EMC博客刚才偶然看了本刊的两篇有关磁珠的专家博文,这两篇博文都是讲磁珠的。其中一篇是讲磁珠与电感的区别,另一篇讲磁珠其实就是一电阻特性。其实这样的说法都是不准确的。磁珠(Ferrite bead)的等效电路是一个DCR电阻串联一个电感 ...… 查看全部问答> |
|
#include #include #define uint unsigned int #define uchar unsigned char uchar temp,b; void delay(uint z); void main() { temp=0xfe; &nbs ...… 查看全部问答> |




