移植環(huán)境
1,主機環(huán)境:VMare下CentOS 5.5 ,1G內(nèi)存。
2,集成開發(fā)環(huán)境:Elipse IDE
3,編譯編譯環(huán)境:arm-linux-gcc v4.4.3,arm-none-eabi-gcc v4.5.1。
4,開發(fā)板:mini2440,2M nor flash,128M nand flash。
5,u-boot版本:u-boot-2009.08
u-boot-2009.08版本已經(jīng)對CS8900、RTL8019和DM9000X等網(wǎng)卡有比較完善的代碼支持(代碼在drivers/net/目錄下),而且在S3C24XX系列中默認對CS8900網(wǎng)卡進行配置使用。而mini2440開發(fā)板使用的則是DM9000網(wǎng)卡芯片,所以只需在開發(fā)板上添加對DM9000的支持即可。還有一點,以前的 U-boot 對于網(wǎng)絡(luò)延時部分有問題,需要修改許多地方。但是現(xiàn)在的U-boot 網(wǎng)絡(luò)
部分已經(jīng)基本不需要怎么修改了,只有在DM9000 的驅(qū)動和NFS 的TIMEOUT 參數(shù)上需要稍微修改一下。
4.1,DM9000驅(qū)動代碼修改
【1】修改static int dm9000_init函數(shù)中部分代碼,如果不修改這一部分,在使用網(wǎng)卡的時候會報“could not establish link”的錯誤。
打開/drivers/net/dm9000x.c,定位到377行,修改如下:
/* Activate DM9000 */
/* RX enable */
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
DM9000_iow(DM9000_IMR, IMR_PAR);
#if 0 //default to link MII interface
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 1650) {
//printf("could not establish link\n");
//return 0;
break;
}
}
#endif
【2】對于NFS,增加了延時,否則會出現(xiàn)“*** ERROR: Cannot mount”的錯誤。
打開/net/nfs.c,定位到36行,修改如下:
#if defined(CONFIG_CMD_NET) && defined(CONFIG_CMD_NFS)
#define HASHES_PER_LINE 65 /* Number of "loading" hashes per line */
#define NFS_RETRY_COUNT 30
#define NFS_TIMEOUT (CONFIG_SYS_HZ/1000*2000UL) //2000UL
【3】添加網(wǎng)卡芯片(DM9000)的初始化函數(shù)
打開board/samsung/mini2440/mini2440.c,定位到194行附近,文件末尾處,修改如下:
int dram_init (void)
{
gd->bd->bi_dram[0].start = PHYS_SDRAM_1;
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
extern int dm9000_initialize(bd_t *bis);//implicit declaration of function 'dm9000_initialize'
#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
return dm9000_initialize(bis);
}
#endif
【4】添加串口 Xmodem 傳輸協(xié)議(可不修改)
對于使用串口傳輸數(shù)據(jù)到內(nèi)存的操作,有可能會用到Xmodem協(xié)議。但是原本的kermit協(xié)議傳輸就挺好用的,速度也比較快,所以可添加此功能。
打開/common/cmd_load.c,定位到37行,修改如下:
#if defined(CONFIG_CMD_LOADB)
#if defined(ENABLE_CMD_LOADB_X)
static ulong load_serial_xmodem (ulong offset);
#endif
static ulong load_serial_ymodem (ulong offset);
#endif
然后再定位到480行附近,修改如下:
if (load_baudrate != current_baudrate) {
printf ("## Switch baudrate to %d bps and press ENTER ...\n",
load_baudrate);
udelay(50000);
gd->baudrate = load_baudrate;
serial_setbrg ();
udelay(50000);
for (;;) {
if (getc() == '\r')
break;
}
}
#if defined(ENABLE_CMD_LOADB_X)
if (strcmp(argv[0],"loadx")==0) {
printf ("## Ready for binary (xmodem) download "
"to 0x%08lX at %d bps...\n",
offset,
load_baudrate);
addr = load_serial_xmodem (offset);
} else if (strcmp(argv[0],"loady")==0) {
#else
if (strcmp(argv[0],"loady")==0) {
#endif
printf ("## Ready for binary (ymodem) download "
"to 0x%08lX at %d bps...\n",
offset,
load_baudrate);
addr = load_serial_ymodem (offset);
再定位到998行附近,修改如下:
static int getcxmodem(void) {
if (tstc())
return (getc());
return -1;
}
#if defined(ENABLE_CMD_LOADB_X)
static ulong load_serial_xmodem (ulong offset)
{
int size;
char buf[32];
int err;
int res;
connection_info_t info;
char xmodemBuf[1024];
ulong store_addr = ~0;
ulong addr = 0;
size = 0;
info.mode = xyzModem_xmodem;
res = xyzModem_stream_open (&info, &err);
if (!res) {
while ((res =
xyzModem_stream_read (xmodemBuf, 1024, &err)) > 0) {
store_addr = addr + offset;
size += res;
addr += res;
#ifndef CFG_NO_FLASH
if (addr2info (store_addr)) {
int rc;
rc = flash_write ((char *) xmodemBuf,
store_addr, res);
if (rc != 0) {
flash_perror (rc);
return (~0);
}
} else
#endif
{
memcpy ((char *) (store_addr), xmodemBuf,
res);
}
}
} else {
printf ("%s\n", xyzModem_error (err));
}
xyzModem_stream_close (&err);
xyzModem_stream_terminate (false, &getcxmodem);
flush_cache (offset, size);
printf ("## Total Size = 0x%08x = %d Bytes\n", size, size);
sprintf (buf, "%X", size);
setenv ("filesize", buf);
return offset;
}
#endif
static ulong load_serial_ymodem (ulong offset)
再定位到1169行,修改如下:
#if defined(CONFIG_CMD_LOADB)
U_BOOT_CMD(
loadb, 3, 0, do_load_serial_bin,
"load binary file over serial line (kermit mode)",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'"
);
#if defined(ENABLE_CMD_LOADB_X)
U_BOOT_CMD(
loadx, 3, 0, do_load_serial_bin,
"load binary file over serial line (xmodem mode)",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'"
);
#endif
U_BOOT_CMD(
loady, 3, 0, do_load_serial_bin,
"load binary file over serial line (ymodem mode)",
"[ off ] [ baud ]\n"
" - load binary file over serial line"
" with offset 'off' and baudrate 'baud'"
);
【5】修改配置文件,在mini2440.h中加入相關(guān)定義
打開/include/configs/mini2440.h,定位到60行附近,修改如下:
/*
* Hardware drivers
*/
#if 0
#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
#endif
#define CONFIG_NET_MULTI 1
#define CONFIG_DRIVER_DM9000 1
#define CONFIG_DM9000_BASE 0x20000300 //網(wǎng)卡片選地址
#define DM9000_IO CONFIG_DM9000_BASE
#define DM9000_DATA (CONFIG_DM9000_BASE+4) //網(wǎng)卡數(shù)據(jù)地址
#define CONFIG_DM9000_NO_SROM 1
//#define CONFIG_DM9000_USE_16BIT
#undef CONFIG_DM9000_DEBUG
注意:
u-boot-2009.08 可以自動檢測DM9000網(wǎng)卡的位數(shù),根據(jù)開發(fā)板原理圖可知網(wǎng)卡的數(shù)據(jù)位為16位,并且網(wǎng)卡位
于CPU的BANK4上,所以只需在 board/samsung/mini2440/lowlevel_init.S中設(shè)置 #define B4_BWSCON (DW16) 即
可,不需要此處的 #define CONFIG_DM9000_USE_16BIT 1
給u-boot加上ping命令,用來測試網(wǎng)絡(luò)通不通
/*
* Command line configuration.
*/
#include <config_cmd_default.h>
#define CONFIG_CMD_CACHE
#define CONFIG_CMD_DATE
#define CONFIG_CMD_ELF
#define CONFIG_CMD_NAND
#define CONFIG_CMD_JFFS2 /* JFFS2 Support*/
#define CONFIG_CMD_PING /*ping command support*/
恢復被注釋掉的網(wǎng)卡MAC地址和修改你合適的開發(fā)板IP地址以及內(nèi)核啟動參數(shù):
#define CONFIG_BOOTDELAY 3
#define CONFIG_ETHADDR 08:00:3e:26:0a:5b
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 10.1.0.129
#define CONFIG_SERVERIP 10.1.0.128
#define CONFIG_GATEWAYIP 10.1.0.1
#define CONFIG_OVERWRITE_ETHADDR_ONCE
/*#define CONFIG_BOOTFILE "elinos-lart" */
定位到139行附近,加入使能串口傳輸數(shù)據(jù)到內(nèi)存的操作:
#define ENABLE_CMD_LOADB_X 1 //使能串口傳輸數(shù)據(jù)到內(nèi)存的操作
#if defined(CONFIG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
4.2,重新編譯u-boot,下載到Nand中從Nand啟動,查看啟動信息和環(huán)境變量并使用ping命令測試網(wǎng)卡,操作如下:
Enter your selection: a
USB host is connected. Waiting a download.
Now, Downloading [ADDRESS:30000000h,TOTAL:154934]
RECEIVED FILE SIZE: 154934 (151KB/S, 1S)
Downloaded file at 0x30000000, size = 154924 bytes
Write to flash ok: skipped size = 0x0, size = 0x25d2c
... ...
nand 方式上電重啟后:
U-Boot 2009.08 ( 5鏈?09 2011 - 15:01:04)
DRAM: 64 MB
Flash: 2 MB
NAND: 128 MiB
In: serial
Out: serial
Err: serial
Net: dm9000
[u-boot@MINI2440]#
顯示下環(huán)境變量:
[u-boot@MINI2440]# printenv
bootdelay=3
baudrate=115200
netmask=255.255.255.0
stdin=serial
stdout=serial
stderr=serial
ipaddr=10.1.129
serverip=10.1.0.128
ethact=dm9000
Environment size: 141/131068 bytes
ping測試:
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at 100M full duplex mode
*** ERROR: `ethaddr' not set
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at 100M full duplex mode
ping failed; host 10.1.0.128 is not alive
需要設(shè)定IP地址和MAC地址
[u-boot@MINI2440]# setenv ipaddr 10.1.0.129
[u-boot@MINI2440]# setenv serverip 10.1.0.128
[u-boot@MINI2440]# setenv setenv ethaddr 12:34:56:78:9A:BC
[u-boot@MINI2440]# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 -- 0% complete.
Writing to Nand... done
[u-boot@MINI2440]#
然后再進行ping測試:
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
ping failed; host 10.1.0.128 is not alive
[u-boot@MINI2440]#
可以看到,啟動信息里面顯示了Net:dm9000,printenv查看的環(huán)境變量也和include/configs/mini2440.h中設(shè)置的一致。但是現(xiàn)在有個問題就是ping不能通過。
經(jīng)過一段時間在網(wǎng)上搜索,原來有很多人都碰到了這種情況。出現(xiàn)問題的地方可能是DM9000網(wǎng)卡驅(qū)動中關(guān)閉網(wǎng)卡的地方,如是就試著修改代碼如下:
打開drivers/net/dm9000x.c ,定位到456行附近,屏蔽掉dm9000_halt函數(shù)中的內(nèi)容:
/*
Stop the interface.
The interface is stopped when it is brought.
*/
static void dm9000_halt(struct eth_device *netdev)
{
#if 0
DM9000_DBG("%s\n", __func__);
/* 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 */
#endif
}
重新編譯下載,nand啟動,運行結(jié)果:
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at unknown: 0 mode
*** ERROR: `ethaddr' not set
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 00:00:00:00:00:00
operating at unknown: 0 mode
ping failed; host 10.1.0.128 is not alive
[u-boot@MINI2440]# setenv gatewayip 10.1.0.1
[u-boot@MINI2440]# setenv ethaddr 12:34:56:78:9a:bc //MAC地址,隨便設(shè)
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 0 mode
Using dm9000 device
host 10.1.0.128 is alive
[u-boot@MINI2440]# saveenv
Saving Environment to NAND...
Erasing Nand...
Erasing at 0x4000000000002 -- 0% complete.
Writing to Nand... done
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 0 mode
Using dm9000 device
host 10.1.0.128 is alive
[u-boot@MINI2440]#
結(jié)果,只是第一次ping不通,以后都是可以ping通的(據(jù)網(wǎng)友們說這是正常的)。
4.3,tftp功能測試
首先需要將友善官方移植好的有關(guān)mini2440的內(nèi)核文件zImage_T35復制到linux 宿主機的/tftpboot目錄下,因為u-boot默認的此目錄,然后執(zhí)行:
[u-boot@MINI2440]# tftp 0x30008000 zImage_T35
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 0 mode
Using dm9000 device
TFTP from server 10.1.0.128; our IP address is 10.1.0.129
Filename 'zImage_T35'.
Load address: 0x30008000
Loading: T ################################################T #################
#############T T ######################T ##############################
T T
########
done
Bytes transferred = 2022348 (1edbcc hex)
[u-boot@MINI2440]#
至此DM9000網(wǎng)卡驅(qū)動移植成功。但是還發(fā)現(xiàn)一個問題:"這里之前還是"operating at 100M full duplex mode",而現(xiàn)在怎么是"operating at unknown: 0 mode"?原來是dm9000的phy_read(int reg)函數(shù)延時出了問題,現(xiàn)操作如下:
打開/drivers/net/dm9000x.c,定位到595行附近,修改如下:
/*
Read a word from phyxcer
*/
static u16
phy_read(int reg)
{
u16 val;
/* Fill the phyxcer register into REG_0C */
DM9000_iow(DM9000_EPAR, DM9000_PHY | reg);
DM9000_iow(DM9000_EPCR, 0xc); /* Issue phyxcer read command */
udelay(1000); //udelay(100); /* Wait read complete */
DM9000_iow(DM9000_EPCR, 0x0); /* Clear phyxcer read command */
val = (DM9000_ior(DM9000_EPDRH) << 8) | DM9000_ior(DM9000_EPDRL);
/* The read data keeps on REG_0D & REG_0E */
DM9000_DBG("phy_read(0x%x): 0x%x\n", reg, val);
return val;
}
重新編譯下載后:
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at unknown: 15 mode
Using dm9000 device
ping failed; host 10.1.0.128 is not alive
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
host 10.1.0.128 is alive
[u-boot@MINI2440]#
可以看到"operating at 100M full duplex mode"這樣的信息了
上面還有一個問題,就是問什么第一次ping不通呢?經(jīng)過嘗試,操作如下:
打開/drivers/net/dm9000x.c,定位到377行,修改如下:
/* Activate DM9000 */
/* RX enable */
DM9000_iow(DM9000_RCR, RCR_DIS_LONG | RCR_DIS_CRC | RCR_RXEN);
/* Enable TX/RX interrupt mask */
DM9000_iow(DM9000_IMR, IMR_PAR);
#if 1 //internet delay loop
i = 0;
while (!(phy_read(1) & 0x20)) { /* autonegation complete bit */
udelay(1000);
i++;
if (i == 3000) {
printf("could not establish link\n");
return 0;
//break;
}
}
#endif
修改后重新編譯下載:
[u-boot@MINI2440]# ping 10.1.0.128
dm9000 i/o: 0x20000300, id: 0x90000a46
DM9000: running in 16 bit mode
MAC: 12:34:56:78:9a:bc
operating at 100M full duplex mode
Using dm9000 device
host 10.1.0.128 is alive
[u-boot@MINI2440]#
OK! 第一次ping不通的問題解決了!
接下來將進入u-boot的第五階段,為u-boot-2009.08增加yaffs2文件系統(tǒng)。