嵌入式Linux之我行——u-boot-2009.08在2440上的移植詳解(四)

嵌入式Linux之我行,主要講述和總結了本人在學習嵌入式linux中的每個步驟。一爲總結經驗,二希望能給想入門嵌入式Linux的朋友提供方便。如有錯誤之處,謝請指正。

一、移植環境

二、移植步驟

上接u-boot-2009.08在2440上的移植詳解(三)

在這一篇中,我們首先讓開發板對CS8900或者DM9000X網卡的支持,然後再分析實現u-boot怎樣來引導Linux內核啓動。因爲測試u-boot引導內核我們要用到網絡下載功能。

7)u-boot對CS8900或者DM9000X網卡的支持。
u-boot-2009.08版本已經對CS8900和DM9000X網卡有比較完善的代碼支持(代碼在drivers/net/目錄下),而且在S3C24XX系列中默認對CS8900網卡進行配置使用。只是在個別地方要根據開發板的具體網卡片選進行設置,就可以對S3C24XX系列中CS8900網卡的支持使用。代碼如下:

#gedit include/configs/my2440.h

/*
 * Hardware drivers
 */

#define CONFIG_DRIVER_CS8900  1        /* we have a CS8900 on-board */
#define CS8900_BASE           0x19000300 //注意:對不同的開發板就是要修改這個片選地址參數,這個參數值就看開發板上網卡的片選引腳是接到ARM芯片存儲控制器的哪個Bank上
#define CS8900_BUS16          1        /* the Linux driver does accesses as shorts */

現在修改對我們開發板上DM9000X網卡的支持。
首先,我們看看drivers/net/目錄下有關DM9000的代碼,發現dm9000x.h中對CONFIG_DRIVER_DM9000宏的依賴,dm9000x.c中對CONFIG_DM9000_BASE宏、DM9000_IO宏、DM9000_DATA等宏的依賴,所以我們修改代碼如下:

#gedit include/configs/my2440.h

/* * Hardware drivers */  屏蔽掉u-boot默認對CS8900網卡的支持
//#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 */

 

//添加u-boot對DM9000X網卡的支持

#define CONFIG_DRIVER_DM9000    1 
#define CONFIG_NET_MULTI        1
#define CONFIG_DM9000_NO_SROM   1
#define CONFIG_DM9000_BASE      0x20000300  //網卡片選地址
#define DM9000_IO               CONFIG_DM9000_BASE
#define DM9000_DATA             (CONFIG_DM9000_BASE + 4)   //網卡數據地址

//#define CONFIG_DM9000_USE_16BIT 1

注意:
u-boot-2009.08 可以自動檢測DM9000網卡的位數,根據開發板原理圖可知網卡的數據位爲16位,並且網卡位於CPU的BANK4上,所以只需在 board/samsung/my2440/lowlevel_init.S中設置 #define B4_BWSCON (DW16) 即可,不需要此處的 #define CONFIG_DM9000_USE_16BIT 1

 

//給u-boot加上ping命令,用來測試網絡通不通

#define CONFIG_CMD_PING 

 

//恢復被註釋掉的網卡MAC地址和修改你合適的開發板IP地址

#define CONFIG_ETHADDR   08:00:3e:26:0a:5b  //開發板MAC地址
#define CONFIG_NETMASK   255.255.255.0
#define CONFIG_IPADDR    192.168.1.105      //開發板IP地址

#define CONFIG_SERVERIP  192.168.1.103      //Linux主機IP地址

添加板載DM9000網卡初始化代碼,如下:

#gedit board/samsung/my2440/my2440.c

#include <net.h>
#include <netdev.h>

 

#ifdef CONFIG_DRIVER_DM9000
int board_eth_init(bd_t *bis)
{
    return dm9000_initialize(bis);
}
#endif

修改MD9000網卡驅動代碼,如下:

#gedit drivers/net/dm9000x.c

#if//屏蔽掉dm9000_init函數中的這一部分,不然使用網卡的時候會報“could not establish link”的錯誤
    i = 0;
    while (!(phy_read(1) & 0x20)) {    /* autonegation complete bit */
        udelay(1000);
        i++;
        if (i == 10000) {
            printf("could not establish link ");
            return 0;
        }
    }
#endif


然後重新編譯u-boot,下載到Nand中從Nand啓動,查看啓動信息和環境變量並使用ping命令測試網卡,操作如下:
可以看到,啓動信息裏面顯示了Net:dm9000,printenv查看的環境變量也和include/configs/my2440.h中設置的一致。但是現在有個問題就是ping不能通過。
 
經過一段時間在網上搜索,原來有很多人都碰到了這種情況。出現問題的地方可能是DM9000網卡驅動中關閉網卡的地方,如是就試着修改代碼如下:

#gedit drivers/net/dm9000x.c  //屏蔽掉dm9000_halt函數中的內容

/*
  Stop the interface.
  The interface is stopped when it is brought.
*/

static void dm9000_halt(struct eth_device *netdev)
{
    
//DM9000_DBG("%sn", __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 */
}

 
結果,只是第一次ping不通,以後都是可以ping通的(據網友們說這是正常的),如下圖:
 
好了,現在只剩下一個問題了,就是使用tftp進行下載。關於tftp服務器在Linux中的安裝和配置,這裏我就不講了,在網上搜一下很多的。然而,在tftp下載時又遇到了問題,總是出現傳送不完整又重新傳送的現象,不斷的循環,如下圖:
 
困惑好久的tftp問題現在終於搞定啦,心情真是爽啊!!首先分析上面圖中的現象,在下載過程中斷斷續續就說明是可以下載的,只是由於某種原因使網絡出現超時從而重新下載,那我想出現這種情況的可能性有兩種:1、u-boot中對網絡的延時設置;2、就是我的物理網絡結構。首先針對第一種,我修改了net/net.c中對網絡延時的設置,結果還是不行。接着就試試第二種情況,因爲之前我的網絡是通過路由器來管理的,主機和開發板也是通過路由器來連接的,所以現在我就改用一條交叉網線直接把主機和開發板連接起來,一試,果然可以啦,哈哈哈哈....。至此,網絡部分的移植總算完成了。
 
 
8)實現u-boot引導Linux內核啓動。
 
在前面幾節中,我們講了u-boot對Nor Flash和Nand Flash的啓動支持,那現在我們就再來探討一下u-boot怎樣來引導Linux內核的啓動。
 
①、機器碼的確定
通常,在u-boot和kernel中都會有一個機器碼(即:MACH_TYPE),只有這兩個機器碼一致時才能引導內核,否則就會出現如下mach的錯誤信息:
 
首先,確定u-boot中的MACH_TYPE。在u-boot的include/asm-arm/mach-types.h文件中針對不同的CPU定義了非常多的MACH_TYPE,可以找到下面這個定義:

#define MACH_TYPE_SMDK2440 1008  //針對2440的MACH_TYPE碼的值定義爲1008

 
那麼我們就修改u-boot的MACH_TYPE代碼引用部分,確定u-boot的MACH_TYPE。如下:

#gedit board/samsung/my2440/my2440.c   //修改board_init函數

/* arch number of SMDK2410-Board */
//gd->bd->bi_arch_number = MACH_TYPE_SMDK2410;
改爲:
gd->bd->bi_arch_number = MACH_TYPE_SMDK2440;

 
其次,確定kernel中的MACH_TYPE。在kernel的arch/arm/tools/mach-types文件中也針對不同的CPU定義了非常多的MACH_TYPE,也可以找到下面這個定義:

smdk2440  MACH_SMDK2440   SMDK2440   1008

 
那麼我們就修改kernel的MACH_TYPE代碼引用部分,確定kernel的MACH_TYPE。如下:

#gedit arch/arm/mach-s3c2440/mach-smdk2440.c   //修改文件最後面

//MACHINE_START(S3C2440, "SMDK2440")
改爲:
MACHINE_START(SMDK2440, "SMDK2440")

 

#gedit arch/arm/kernel/head.S  //在ENTRY(stext)下添加如下代碼(紅色部分)

ENTRY(stext)

    mov    r0, #0
    mov    r1, #0x3f0   //上面的MACH_TYPE值1008換成十六進制就是0x3f0
    ldr    r2, =0x30000100
 
   
msr cpsr_c, #PSR_F_BIT | PSR_I_BIT | SVC_MODE

    .......

 
分別重新編譯u-boot和kernel。u-boot下載後,記得要saveenv;kernel用tftp下載到內存後使用go命令來測試引導內核,結果可以引導了,如下:
 
準備能被u-boot直接引導的內核uImage
通常,kernel的啓動需要u-boot提供一些參數信息,比如ramdisk在RAM中的地址。經過編譯後的u-boot在根目錄下的tools目錄中,會有個叫做mkimage的工具,他可以給zImage添加一個header,也就是說使得通常我們編譯的內核zImage添加一個數據頭信息部分,我們把添加頭後的image通常叫uImage,uImage是可以被u-boot直接引導的內核鏡像。
 
mkimage工具的使用介紹如下:

使用: 中括號括起來的是可選的

mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image

選項:
-A:set architecture to 'arch'       //用於指定CPU類型,比如ARM
-O:set operating system to 'os'     //用於指定操作系統,比如Linux
-T:set image type to 'type'         //用於指定image類型,比如Kernel
-C:set compression type 'comp'      //指定壓縮類型
-a:set load address to 'addr' (hex) //指定image的載入地址
-e:set entry point to 'ep' (hex)    //內核的入口地址,一般爲image的載入地址+0x40(信息頭的大小)
-n:set image name to 'name'         //image在頭結構中的命名
-d:use image data from 'datafile'   //無頭信息的image文件名
-x:set XIP (execute in place)       //設置執行位置

 
先將u-boot下的tools中的mkimage複製到主機的/usr/local/bin目錄下,這樣就可以在主機的任何目錄下使用該工具了。現在我們進入kernel生成目錄(一般是arch/arm/boot目錄),然後執行如下命令,就會在該目錄下生成一個uImage.img的鏡像文件,把他複製到tftp目錄下,這就是我們所說的uImage。

mkimage -n 'linux-2.6.30.4' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage uImage.img

 
③、Nand Flash的分區。我們查看內核在arch/arm/plat-s3c24xx/common-smdk.c中的分區情況如下

         起始地址      結束地址

uboot : 0x00000000    0x00030000
param : 0x00030000    0x00040000 //注意這個環境變量的地址範圍要與上一節補充內容中配置的CONFIG_ENV_OFFSET一致
kernel: 0x00050000    0x00200000
root  : 0x00250000    0x03dac000

 
 
④、設置修改u-boot的啓動參數,在u-boot命令行下輸入:

//設置啓動參數,意思是將nand中0x50000-0x00200000(和kernel分區一致)的內容讀到內存0x31000000中,然後用bootm命令來執行

set bootcmd 'nand read 0x31000000 0x50000 0x00200000;bootm 0x31000000'

saveenv  //保存設置

 
⑤、把uImage.img用tftp下載到內存中,然後再固化到Nand Flash中,操作和執行圖如下:

tftp 0x30000000 uImage.img  //將uImage.img下載到內存0x30000000處

nand erase 0x50000 0x200000 //擦除nand的0x50000-0x200000的內容

nand write 0x30000000 0x50000 0x200000 //將內存0x30000000處的內容寫入到nand的0x50000處

 
 
最後,我們重新啓動開發板,可以看到,內核被u-boot成功引導起來了,如圖:
 
      文章出處:http://hbhuanggang.cublog.cn
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章