原文:http://blog.csdn.net/ll_0520/article/details/6046169
/*在第二次移植基础上添加DM9000网卡支持*/
/*2010.11.30--2010.11.30*/
/*交叉编绎工具:cross-3.3.2.tar.bz2*/
/*默认当前目录为:u-boot-1.1.4*/
1. vi include/configs/fl2440.h
(1)注释56行(#define CONFIG_DRIVER_CS8900 1),57行(#define CS8900_BASE 0x19000300),58行(#define CS8900_BUS16 1)
(2)添加:
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x20000000 /*网卡片选地址*/
#define DM9000_IO CONFIG_DM9000_BASE /*传输I0数据的地址,即DM9000的CMD引脚为低电平的地址*/
#define DM9000_DATA (CONFIG_DM9000_BASE+4) /*传输DATA数据的地址,即DM9000的CMD引脚为高电平时的地址*/
#define CONFIG_DM9000_USE_16BIT 1 /*网卡数据传输位数*/
(3)84行(CFG_CMD_NAND | /)后添加;
CFG_CMD_PING | /
(4)去掉注释/*#define CONFIG_ETHADDR 08:00:3e:26:0a:5b */
(开发板MAC地址)
修改CONFIG_IPADDR(开发板IP地址)和CONFIG_SERVERIP(主机IP地址)
2. 确认board/fl2440/lowlevel_init.S中宏B4_BWSCON定义为(DW16)
3. 网卡的MAC地址与你设置的不一样,解决办法:(vi drivers/dm9000x.c)
/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
......
/* Set Node address */
/* for (i = 0; i < 6; i++)
((u16 *) bd->bi_enetaddr)[i] = read_srom_word(i);
*/
//tekkamanninja
char *tmp = getenv ("ethaddr");
char *end;
for (i=0; i<6; i++) {
bd->bi_enetaddr[i] = tmp ? simple_strtoul(tmp, &end, 16) : 0;
if (tmp)
tmp = (*end) ? end+1 : end;
}
//tekkamanninja
printf("MAC: %02x:%02x:%02x:%02x:%02x:%02x/n", bd->bi_enetaddr[0],
bd->bi_enetaddr[1], bd->bi_enetaddr[2], bd->bi_enetaddr[3],
bd->bi_enetaddr[4], bd->bi_enetaddr[5]);
......
红色的字符是要做的修改:功能是屏蔽原有获取MAC地址的语句,替换成从U-Boot的参数区读取数据并存到bd->bi_enetaddr[i]中。
4. 会有“could not establish link” 的提示,而且在显示MAC地址后很久后才响应,解决办法: (vi drivers/dm9000x.c)
/* Initilize dm9000 board
*/
int
eth_init(bd_t * bd)
{
......
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* RX enable */
DM9000_iow(DM9000_IMR, IMR_PAR); /* Enable TX/RX interrupt mask
*/
#if 0
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 10000) {
printf("could not establish link/n");
return 0;
}
printf(" link=%d/n",i);
}
/* see what we've got */
lnk = phy_read(17) >> 12;
printf("operating at ");
switch (lnk) {
case 1:
printf("10M half duplex ");
break;
case 2:
printf("10M full duplex ");
break;
case 4:
printf("100M half duplex ");
break;
case 8:
printf("100M full duplex ");
break;
default:
printf("unknown: %d ", lnk);
break;
}
printf("mode/n");
#endif
return 0;
}
红色的字符是要做的修改:功能是屏蔽无用的语句。其实被屏蔽的语句是MII接口用的,放在这显然是错误的,无端的浪费了10秒钟。
5. 此时还是PING不通,解决办法:注释掉eth_halt函数的内容.
vi drivers/dm9000x.c
void eth_halt(void)
{
// DM9000_DBG("eth_halt/n");
/* RESET devie */
// phy_write(0, 0x8000); /* PHY RESET */
// DM9000_iow(DM9000_GPR, 0x01); /* Power-Down PHY */
// DM9000_iow(DM9000_IMR, 0x80); /* Disable all interrupt */
// DM9000_iow(DM9000_RCR, 0x00); /* Disable RX */
}
6.现在每回上电开发板第一次PING时还是PING不通,但从第二次开始就能PING通了
,因为当使用PING命令时才会掉用网卡初始化函数int eth_init(bd_t * bd),为了
第一次就能PING通可以先初始化下网卡:
vi lib_arm/board.c
(1)文件头添加:
#ifdef CONFIG_DRIVER_DM9000
extern int eth_init(bd_t * bd);
#endif
(2)void start_armboot (void)函数中for循环上面添加:
#ifdef CONFIG_DRIVER_DM9000
eth_init(gd->bd);
#endif
(由于uboot1.1.4没有ICMP协议,所以主机PING开发板是PING不通的)
相关链接:
uboot-2009.08 添加 DM9000X网卡的支持
http://blog.chinaunix.net/u3/117680/showart_2294336.html
移植U-Boot.1.2.0到友善之臂SBC2440V4(补:DM9000网卡移植)
http://blog.chinaunix.net/u2/67519/showart_640986.html
U-BOOT DM9000驱动完全注释
http://blog.chinaunix.net/u3/114978/showart.php?id=2262658
/*2010.12.15*/
搞了好几天就是不能通过网口下内核,明明ping主机都是通的,但是ping不通VM上的ubuntu,不过用sniffit抓包ubuntu确实收到开发板发来的ICMP包了,并且也回复了ICMP包,今天才发现原来FL2440用的网卡是DM9000AE,而uboot1.1.4的网卡驱动是DM9000的,这两之间还是有些区别的,晕死啊......
再网上找到的解决办法是:
无奈参考Linux内核中代码,发现Linux的dm9000在rx函数中添加do while循环,于是按照Linux内核源码在u-boot中也添加do while循环。
do{
/* Check packet ready or not */
DM9000_ior(DM9000_MRCMDX); /* Dummy read */
rxbyte = DM9000_inb(DM9000_DATA); /* Got most updated data */
if (rxbyte == 0)
return 0;
/* Status check: this byte must be 0 or 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);
/* */
RxStatus = DM9000_inw(DM9000_DATA);
RxLen = DM9000_inw(DM9000_DATA);
/* */
DM9000_DBG("rx status: 0x%04x rx len: %d/n", RxStatus, RxLen);
/* Move data from DM9000 */
/* Read received packet from RX SRAM */
tmplen = (RxLen + 1) / 2;
for (i = 0; i < tmplen; i++)
{
((u16 *) rdptr)[i] = DM9000_inw(DM9000_DATA);
//printf("%d ",((u16 *) rdptr)[i]);
}
/* */
if ((RxStatus & 0xbf00) || (RxLen < 0x40)
|| (RxLen > DM9000_PKT_MAX)) {
if (RxStatus & 0x100) {
printf("rx fifo error/n");
}
if (RxStatus & 0x200) {
printf("rx crc error/n");
}
if (RxStatus & 0x8000) {
printf("rx length error/n");
}
if (RxLen > DM9000_PKT_MAX) {
printf("rx length too big/n");
dm9000_reset();
}
} else {
/* Pass to upper layer */
DM9000_DBG("passing packet to upper layer/n");
NetReceive(NetRxPackets[0], RxLen);
//return RxLen;
}
}
while (rxbyte == DM9000_PKT_RDY);
//return 0;
return RxLen;
测试结果:
大部分时候都可以ping通了,因为有调试信息,tftp速度十几k。
网上还有个建议在tx函数前加入以上内容清空dm9000ae寄存器
DM9000_ior(DM9000_MRRH);
DM9000_ior(DM9000_MRRL);
我放在do的前面,貌似也有一定作用
参考链接:
[6410][u-boot]移植dm9000ae驱动
http://www.360doc.com/content/10/0223/15/496343_16556017.shtml
dm9000ae 在u-boot上的移植小结