U-boot在S3C2440上的移植詳解
U-boot在S3C2440上的移植詳解
一、移植環境
· 主機:VMWare--Fedora 9
· 開發板:Mini2440--64MBNand,Kernel:2.6.30.4
· 編譯器:arm-linux-gcc-4.3.2.tgz
· u-boot:u-boot-2009.08.tar.bz2
二、移植步驟
本次移植的功能特點包括:
·
· 支援從Nor/NandFlash啟動
· 支援CS8900或者DM9000網絡卡
· 支援Yaffs檔案系統
· 支援USB下載(還未實現)
1.瞭解u-boot主要的目錄結構和啟動流程,如下圖。
u-boot的stage1程式碼通常放在cpu/xxxx/start.S檔案中,他用匯編語言寫成;
u-boot的stage2
各個部分的流程圖如下:
2. 建立自己的開發板專案並測試編譯。
目前u-boot對很多CPU直接支援,可以檢視board目錄的一些子目錄,如:board/samsung/目錄下就是對三星一些ARM處理器的支援,有smdk2400、smdk2410和smdk6400,但沒有2440,所以我們就在這裡建立自己的開發板專案。
1)因2440和2410的資源差不多,主頻和外設有點差別,所以我們就在board/samsung/下建立自己開發板的專案,取名叫my2440。
#tar -jxvf u-boot-2009.08.tar.bz2 // #cd u-boot-2009.08/board/samsung/ //進入目錄 #mkdir my2440 //建立my2440資料夾 |
2)因2440和2410的資源差不多,所以就以2410專案的程式碼作為模板,以後再修改
#cp -rf smdk2410/* my2440/ //將2410下所有的程式碼複製到2440下 #cd my2440 //進入my2440目錄 #mv smdk2410.c my2440.c //將my2440下的smdk2410.c改名為my2440.c #cd ../../../ //回到u-boot根目錄 |
COBJS := my2440.o flash.o //因在my2440下我們將smdk2410.c改名為my2440.c |
3)修改u-boot根目錄下的Makefile檔案。查詢到smdk2410_config的地方,在他下面按照smdk2410_config的格式建立my2440_config的編譯選項,另外還要指定交叉編譯器
#gedit Makefile |
CROSS_COMPILE ?= arm-linux- //指定交叉編譯器為arm-linux-gcc smdk2410_config : unconfig //2410編譯選項格式 @$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 samsung s3c24x0 my2440_config : unconfig //2440編譯選項格式 @$(MKCONFIG) $(@:_config=) arm arm920t my2440 samsung s3c24x0 *說明:arm :CPU的架構(ARCH) arm920t:CPU的型別 my2440 :對應在board目錄下建立新的開發板專案的目錄 samsung:新開發板專案目錄的上級目錄,如直接在board下建立新的開發板專案的目錄,則這裡就為NULL s3c24x0:CPU型號 *注意:編譯選項格式的第二行要用Tab鍵開始,否則編譯會出錯 |
4)測試編譯新建的my2440開發板專案
#make my2440_config //如果出現Configuring for my2440 board...則表示設定正確 #make //編譯後在根目錄下會出現u-boot.bin檔案,則u-boot移植的第一步就算完成了 |
到此為止,u-boot對自己的my2440開發板還沒有任何用處,以上的移植只是搭建了一個my2440開發板u-boot的框架,要使其功能實現,還要根據my2440開發板的具體資源情況來對u-boot原始碼進行修改。
3. 根據u-boot啟動流程圖的步驟來分析或者修改新增u-boot原始碼,使之適合my2440開發板(注:修改或新增的地方都用紅色表示)。
1)my2440開發板u-boot的stage1入口點分析。一般在嵌入式系統軟體開發中,在所有原始碼檔案編譯完成之後,連結器要讀取一個連結分配檔案,在該檔案中定義了程式的入口點,程式碼段、資料段等分配情況等。那麼我們的my2440開發板u-boot的這個連結檔案就是cpu/arm920t/u-boot.lds,開啟該檔案部分程式碼如下:
知道了程式的入口點是_start,那麼我們就開啟my2440開發板u-boot第一個要執行的程式cpu/arm920t/start.S(即u-boot的stage1部分),查詢到_start的位置如下:
從這個彙編程式碼可以看到程式又跳轉到start_code處開始執行,那麼再查詢到start_code處的程式碼如下:
/* |
由此可以看到,start_code處才是u-boot啟動程式碼的真正開始處。以上就是u-boot的stage1入口的過程。
2)my2440開發板u-boot的stage1階段的硬體裝置初始化。由於在u-boot啟動程式碼處有兩行是AT91RM9200DK的LED初始程式碼,但我們my2440上的LED資源與該開發板的不一致,所以我們要刪除或遮蔽該處程式碼,再加上my2440的LED驅動程式碼(注:新增my2440 LED功能只是用於表示u-boot執行的狀態,給除錯帶來方便,可將該段程式碼放到任何你想除錯的地方),程式碼如下:
/*bl coloured_LED_init //這兩行是AT91RM9200DK開發板的LED初始化,註釋掉 bl red_LED_on*/ #if defined(CONFIG_S3C2440) //區別與其他開發板 //根據mini2440原理圖可知LED分別由S3C2440的PB5、6、7、8口來控制,以下是PB埠暫存器基地址(查2440的DataSheet得知) //以下對暫存器的操作參照S3C2440的DataSheet進行操作 //此段程式碼使u-boot啟動後,點亮開發板上的LED1,LED2、LED3、LED4不亮 |
在include/configs/my2440.h標頭檔案中新增CONFIG_S3C2440巨集
3)在u-boot中新增對S3C2440一些暫存器的支援、新增中斷禁止部分和時鐘設定部分。由於2410和2440的暫存器及地址大部分是一致的,所以這裡就直接在2410的基礎上再加上對2440的支援即可,程式碼如下:
S3C2440的時鐘部分除了在start.S中新增外,還要分別在board/samsung/my2440/my2440.c和cpu/arm920t/s3c24x0/speed.c中修改或新增部分程式碼,如下:
#gedit board/samsung/my2440/my2440.c //設定主頻和USB時鐘頻率引數與start.S中的一致 |
#define FCLK_SPEED 2 //設定預設等於2,即下面紅色程式碼部分有效 |
#gedit cpu/arm920t/start.S |
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) ||
defined(CONFIG_S3C2440) ldr r0, =INTSUBMSK # if defined(CONFIG_S3C2440) //新增s3c2440的時鐘部分# endif #define MPLLCON 0x4C000004 //系統主頻配置暫存器基地址 #define UPLLCON 0x4C000008 //USB時鐘頻率配置暫存器基地址 ldr r0, =CLKDIVN //設定分頻係數FCLK:HCLK:PCLK = 1:4:8 ldr r0, =MPLLCON //設定系統主頻為405MHz ldr r1, =0x7F021 //這個值參考晶片手冊“PLL VALUE SELECTION TABLE”部分 str r1, [r0] ldr r0, =UPLLCON //設定USB時鐘頻率為48MHz ldr r1, =0x38022 //這個值參考晶片手冊“PLL VALUE SELECTION TABLE”部分 str r1, [r0] # else //其他開發板的時鐘部分,這裡就不用管了,我們現在是做2440的 /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN |
#gedit cpu/arm920t/s3c24x0/speed.c //根據設定的分頻係數FCLK:HCLK:PCLK = 1:4:8修改獲取時鐘頻率的函式 |
static ulong get_PLLCLK(int pllreg) |
好了!修改完畢後我們再重新編譯u-boot,然後再下載到RAM中執行測試。結果終端有輸出資訊並且出現類似Shell的命令列,這說明這一部分移植完成。示意圖如下:
#gedit include/configs/my2440.h |
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */ |
現在編譯u-boot,在根目錄下會生成一個u-boot.bin檔案。然後我們利用mini2440原有的supervivi把u-boot.bin下載到RAM中執行測試(注意:我們使用supervivi進行下載時已經對CPU、RAM進行了初始化,所以我們在u-boot中要遮蔽掉對CPU、RAM的初始化),如下:
/*#ifndef CONFIG_SKIP_LOWLEVEL_INIT //在start.S檔案中遮蔽u-boot對CPU、RAM的初始化bl cpu_init_crit #make my2440_config #make |
下載執行後可以看到開發板上的LED燈第一了亮了,其他三個熄滅,測試結果符合上面的要求。終端執行結果如下:
#gedit cpu/arm920t/start.S |
.globl _start |
#gedit cpu/arm920t/u-boot.lds |
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm") |
4)準備進入u-boot的第二階段(在u-boot中新增對我們開發板上Nor Flash的支援)。通常,在嵌入式bootloader中,有兩種方式來引導啟動核心:從Nor Flash啟動和從Nand Flash啟動。u-boot中預設是從Nor Flash啟動,再從上一節這個執行結果圖中看,還發現幾個問題:第一,我開發板的Nor Flash是2M的,而這裡顯示的是512kB;第二,出現Warning - bad CRC, using default environment的警告資訊。不是u-boot預設是從Nor Flash啟動的嗎?為什麼會有這些錯誤資訊呢?這是因為我們還沒有新增對我們自己的Nor Flash的支援,u-boot預設的是其他型號的Nor Flash,而我們的Nor Flash的型號是SST39VF1601。另外怎樣將命令列提示符前面的SMDK2410變成我自己定義的呢?
下面我們一一來解決這些問題,讓u-boot完全對我們Nor Flash的支援。首先我們修改標頭檔案程式碼如下:
#gedit include/configs/my2440.h //修改命令列前的名字和Nor Flash引數部分的定義 |
#define CONFIG_SYS_PROMPT "[MY2440]#" //將命令列前的名字改成[MY2440] /*----------------------------------------------------------------------- |
然後新增對我們mini2440開發板上2M的Nor Flash(型號為SST39VF1601)的支援。在u-boot中對Nor Flash的操作分別有初始化、擦除和寫入,所以我們主要修改與硬體密切相關的三個函式flash_init、flash_erase、write_hword,修改程式碼如下:
#gedit board/samsung/my2440/flash.c |
//修改定義部分如下: //#define MAIN_SECT_SIZE 0x10000 //修改flash_init函式如下: //修改flash_print_info函式如下: case (AMD_MANUFACT & FLASH_VENDMASK): //修改flash_erase函式如下://if ((info->flash_id & FLASH_VENDMASK) != |