Bootloader在AT91RM9200系統(tǒng)中的實(shí)現(xiàn)
1.3 本嵌入式板的存儲(chǔ)空間情況
筆者開發(fā)的ARM板的與bootloader相關(guān)的關(guān)鍵存儲(chǔ)空間分布情況如下:
32M字節(jié)SDRAM: 0x2000_0000 – 0x21FF_FFFF
2M 字節(jié) Flash: 0x1000_0000 – 0x101F_FFFF
2 用GNU工具開發(fā)bootloader
GNU提供了免費(fèi)的編譯工具,可從網(wǎng)上下載。針對(duì)ARM平臺(tái)的交叉編譯工具有匯編器arm-linux-as, C編譯器arm-linux-gcc,連接器arm-linux-ld,以及二進(jìn)制轉(zhuǎn)換工具arm-linux-objcopy。 GNU的編譯器功能非常強(qiáng)大,共有上百個(gè)操作選項(xiàng),滿足開發(fā)者的各種需要。它的特點(diǎn)是開發(fā)成本低,無需昂貴的仿真器,不但可以開發(fā)操作系統(tǒng)下運(yùn)行的程序,也可以開發(fā)裸機(jī)應(yīng)用程序[3]。GNU工具都運(yùn)行在Linux下,開發(fā)者需要1臺(tái)運(yùn)行Linux的PC作為宿主機(jī),開發(fā)后下載到板子上。U-boot,vivi等都利用了這些工具。為開發(fā)者的開發(fā)提供了很好的范例。一般地,基于GNU工具的程序開發(fā)流程如下:(1)編寫C、C++或者匯編源程序;(2)用相關(guān)編譯器生成目標(biāo)文件;(3)編寫連接腳本;(4)用連接器生成最終文件(elf格式);(5)用二進(jìn)制轉(zhuǎn)換工具生成可下載的二進(jìn)制代碼。
編寫適用于本系統(tǒng)的Bootloader以完成最基本的引導(dǎo)操作系統(tǒng)的功能為目的。作為引導(dǎo)程序的基本功能應(yīng)該包括:(1)對(duì)硬件的初始化,如設(shè)置異常向量,設(shè)置CPU的速度、時(shí)鐘頻率和中斷控制寄存器,初始化內(nèi)存控制器,初始化堆棧等;(2)支持文件的下載,串口的Kermit協(xié)議下載或者支持tftp 協(xié)議的網(wǎng)口下載,后者實(shí)現(xiàn)相對(duì)復(fù)雜,但是速度快,可以根據(jù)情況選擇;(3)對(duì)Flash的操作;(4)最好支持下載和自舉兩種工作模式;(5)解壓內(nèi)核,配置參數(shù)等。其中功能(1)直接涉及硬件,實(shí)現(xiàn)時(shí)應(yīng)該使用GNU匯編。不同于ADS環(huán)境下的ARM匯編程序編寫,這種匯編語言有其特點(diǎn),支持預(yù)處理,可以使用#include>和C語言風(fēng)格的注釋,文件的擴(kuò)展名是大寫的S(編譯器以此區(qū)分是否預(yù)處理匯編程序),開發(fā)者可以參考GNU提供的資料,以及U-boot的源代碼。
3 U-boot的移植
3.1 源代碼分析
U-BOOT(Universe Bootloader),是Sourceforge網(wǎng)站的開放源代碼項(xiàng)目,支持PowerPC、ARM、MIPS和x86等多種體系結(jié)構(gòu),代碼便于移植[4]。本人開發(fā)中采用了U-Boot1.1.2的源代碼,GCC編譯器版本是2.95.3。開發(fā)者首先要了解代碼的結(jié)構(gòu)和功能。在此基礎(chǔ)上分析代碼的運(yùn)行順序和相互調(diào)用關(guān)系。
圖2 U-boot的執(zhí)行順序
U-Boot的運(yùn)行過程如圖2所示,程序從cpu/at91rm9200/start.S開始,start.S中用.globl _start定義了入口,之后設(shè)置了處理器的狀態(tài),初始化了中斷和內(nèi)存時(shí)序并且確定是否需要對(duì)整個(gè)U-Boot代碼重定位,跳轉(zhuǎn)到 star_armboot()運(yùn)行,這個(gè)函數(shù)在/lib_asm/board.c中定義,完成了一些初始化工作,之后便循環(huán)調(diào)用commmon /main.c中的main_loop()函數(shù)。開發(fā)時(shí)可以按這個(gè)次序閱讀代碼。在代碼的board目錄下,可以找到與自己的芯片相同的開發(fā)板對(duì)應(yīng)目錄,此處選擇的是目錄at91rm9200dk,移植時(shí)修改工作也多在此處。
3.2 移植要點(diǎn)
進(jìn)行移植主要關(guān)注并進(jìn)行修改的代碼文件有和相應(yīng)的修改要點(diǎn)如下:
(1) include/commom.h。代碼中用很多的條件編譯包含了一些頭文件,并且聲明了一系列的基本函數(shù),這個(gè)頭文件被很多文件包含。了解這個(gè)文件的內(nèi)容對(duì)理解、修改代碼很有幫助。
(2) include/configs/at91rm9200dk.h。這個(gè)文件中是針對(duì)本電路板的詳細(xì)設(shè)置信息,關(guān)鍵的設(shè)置有時(shí)鐘設(shè)置,終端選擇(GDBU、 USART0、USART1),SDRAM的起始地址PHYS_SDRAM和大小PHYS_SDRAM_SIZE,F(xiàn)lash存儲(chǔ)器的起始地址 PHYS_FLASH_1和大小PHYS_FLASH_SIZE,以及Flash中U-Boot的環(huán)境變量的存儲(chǔ)地址CFG_ENV_ADDR和大小 CFG_ENV_SIZE,以及U-Boot的起始地址CFG_U_BOOT_BASE和大小CFG_U_BOOT_SIZE。其他的參數(shù)可以根據(jù)開發(fā)者的需要進(jìn)行修改。以上的參數(shù)要根據(jù)實(shí)際情況修改。
根據(jù)開發(fā)經(jīng)驗(yàn),容易忽略的是FLASH中環(huán)境變量的存儲(chǔ)地址CFG_ENV_ADDR和大小CFG_ENV_SIZE的設(shè)置。U-boot中的 saveenv命令執(zhí)行時(shí)會(huì)將setenv命令設(shè)置的環(huán)境變量存儲(chǔ)在Flash,要求起始地址是Flash的一個(gè)段(section)的邊界,項(xiàng)目中根據(jù) AM29LV160DB芯片的手冊(cè)以及電路原理圖上Flash的地址線的連接對(duì)本文件做以下修改:
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0xe000)
#define CFG_ENV_SIZE 0x2000 /* 0x8000 */
修改為:
#define CFG_ENV_ADDR (PHYS_FLASH_1 + 0x8000)
#define CFG_ENV_SIZE 0x8000 /*0x8000 */
Flash存儲(chǔ)器的地址分配情況可以參見圖1。
(3) board/at91rm9200dk/config.mk。這里面將TEXT_BASE設(shè)置為0x21f00000,與本文第1部分中提到的Boot程序的DST參數(shù)設(shè)置一致。
(4) board/at91rm9200dk/flash.c。由于Flash芯片選用的與源代碼所針對(duì)的Flash芯片不同,首先要在include /flash.h中加入下面的宏:#define AMD_ID_LV160DB 0x22492249,這是AM29LV160DB芯片的設(shè)備ID號(hào),為了在flash_identification()函數(shù)中正確地識(shí)別。另外在本文件中還要加入定義
OrgDef OrgAMDLV160DB[] ={
{ 1, 16*1024 },
/* 1 * 16 kBytes sectors */
{ 2, 8*1024 },
/* 2 * 8 kBytes sectors */
{ 1, 32*1024 },
/* 1 * 32 kBytes sectors */
{ 31, 64*1024 },
/* 31 * 64 kBytes sectors */
};
評(píng)論