您的位置:首页 > 其它

第一次移植uboot(3)(添加DM9000网卡支持)

2010-11-30 19:40 423 查看
/*在第二次移植基础上添加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上的移植小结

http://weibing.blogbus.com/logs/12146712.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: