天天看點

uboot移植大全

BOOT LOADER(引導裝載器),是用于初始化目标闆硬體,給嵌入式作業系統提供闆上硬體資源資訊,并進一步裝載、引導嵌入式作業系統運作的固件。在嵌入式系統開發過程中,很多情況都會涉及底層BOOT LOADER的移植問題,即使在有些已有BOOT LOADER的參考開發闆上也存在這種可能。概括來說,如下情況會考慮進行BOOT LOADER的移植工作:

A. 在自主設計的目标闆上,用于引導嵌入式作業系統及其應用;

B. 在廠家未提供BOOT LOADER源碼的參考闆上,遇有如下情形之一:

a. 在實際應用中需要添加或修改一些功能;

b. 為了給自行設計主機闆移植BOOT LOADER提供參考,先在參考闆上進行移植以積累經驗;

另外,從嵌入式系統實際開發角度講,嵌入式作業系統的引導、配置甚至應用程式的運作狀況都和BOOT LOADER有一定的關聯,可以說,掌握BOOT LOADER移植是順利進行嵌入式系統開發的重要利器。

與常見的嵌入式作業系統闆級支援包BSP相比,BOOT LOADER與底層硬體更為相關,即每個不同配置的目标闆基本都有不同的BOOT LOADER。因為BOOT LOADER往往更依據量體裁衣、定身制作的原則,以滿足要求的最小化代碼存放在啟動ROM或FLASH中。

誠然,自行編寫BOOT LOADER未嘗不可,但從可利用的資源和實際項目開發考慮,采用移植已有的BOOT LOADER源碼來解決這一問題更符合大多數項目開發的要求。

1 U-Boot簡介

U- Boot,全稱Universal Boot Loader,是遵循GPL條款的開放源碼項目。從FADSROM、8xxROM、PPCBOOT逐漸發展演化而來。其源碼目錄、編譯形式與Linux核心很相似,事實上,不少U-Boot源碼就是相應的Linux核心源程式的簡化,尤其是一些裝置的驅動程式,這從U-Boot源碼的注釋中能展現這一點。但是U-Boot不僅僅支援嵌入式Linux系統的引導,目前,它還支援NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS嵌入式作業系統。其目前要支援的目标作業系統是OpenBSD, NetBSD, FreeBSD,4.4BSD, Linux, SVR4, Esix, Solaris, Irix, SCO, Dell, NCR, VxWorks, LynxOS, pSOS, QNX, RTEMS, ARTOS。這是U-Boot中Universal的一層含義,另外一層含義則是U-Boot除了支援PowerPC系列的處理器外,還能支援MIPS、 x86、ARM、NIOS、XScale等諸多常用系列的處理器。這兩個特點正是U-Boot項目的開發目标,即支援盡可能多的嵌入式處理器和嵌入式作業系統。就目前來看,U-Boot對PowerPC系列處理器支援最為豐富,對Linux的支援最完善。其它系列的處理器和作業系統基本是在2002年11 月PPCBOOT改名為U-Boot後逐漸擴充的。從PPCBOOT向U-Boot的順利過渡,很大程度上歸功于U-Boot的維護人德國DENX軟體工程中心Wolfgang Denk[以下簡稱W.D]本人精湛專業水準和持着不懈的努力。目前,U-Boot項目正在他的領軍之下,衆多有志于開放源碼BOOT LOADER移植工作的嵌入式開發人員正如火如荼地将各個不同系列嵌入式處理器的移植工作不斷展開和深入,以支援更多的嵌入式作業系統的裝載與引導。

選擇U-Boot的理由:

① 開放源碼;

② 支援多種嵌入式作業系統核心,如Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS;

③ 支援多個處理器系列,如PowerPC、ARM、x86、MIPS、XScale;

④ 較高的可靠性和穩定性;

④ 較高的可靠性和穩定性;

⑤ 高度靈活的功能設定,适合U-Boot調試、作業系統不同引導要求、産品釋出等;

⑥ 豐富的裝置驅動源碼,如序列槽、以太網、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、鍵盤等;

⑦ 較為豐富的開發調試文檔與強大的網絡技術支援;

2 U-Boot主要目錄結構

- board 目标闆相關檔案,主要包含SDRAM、FLASH驅動;

- common 獨立于處理器體系結構的通用代碼,如記憶體大小探測與故障檢測;

- cpu 與處理器相關的檔案。如mpc8xx子目錄下含序列槽、網口、LCD驅動及中斷初始化等檔案;

- driver 通用裝置驅動,如CFI FLASH驅動(目前對INTEL FLASH支援較好)

- doc U-Boot的說明文檔;

- examples可在U-Boot下運作的示例程式;如hello_world.c,timer.c;

- include U-Boot頭檔案;尤其configs子目錄下與目标闆相關的配置頭檔案是移植過程中經常要修改的檔案;

- lib_xxx 處理器體系相關的檔案,如lib_ppc, lib_arm目錄分别包含與PowerPC、ARM體系結構相關的檔案;

- net 與網絡功能相關的檔案目錄,如bootp,nfs,tftp;

- post 上電自檢檔案目錄。尚有待于進一步完善;

- rtc RTC驅動程式;

- tools 用于建立U-Boot S-RECORD和BIN鏡像檔案的工具; 

3 U-Boot支援的主要功能

U-Boot可支援的主要功能清單

系統引導 支援NFS挂載、RAMDISK(壓縮或非壓縮)形式的根檔案系統

支援NFS挂載、從FLASH中引導壓縮或非壓縮系統核心;

基本輔助功能 強大的作業系統接口功能;可靈活設定、傳遞多個關鍵參數給作業系統,适合系統在不同開發階段的調試要求與産品釋出,尤對Linux支援最為強勁;

支援目标闆環境參數多種存儲方式,如FLASH、NVRAM、EEPROM;

CRC32校驗,可校驗FLASH中核心、RAMDISK鏡像檔案是否完好;

裝置驅動 序列槽、SDRAM、FLASH、以太網、LCD、NVRAM、EEPROM、鍵盤、USB、PCMCIA、PCI、RTC等驅動支援;

上電自檢功能 SDRAM、FLASH大小自動檢測;SDRAM故障檢測;CPU型号;

特殊功能 XIP核心引導;

4 U-Boot移植過程

① 獲得釋出的最新版本U-Boot源碼,與Linux核心源碼類似,也是 bzip2的壓縮格式。可從U-Boot的官方網站 http://sourceforge.net/projects/U-Boot上獲得;

② 閱讀相關文檔,主要是U-Boot源碼根目錄下的README文檔和U-Boot官方網站的DULG(The DENX U-Boot and Linux Guide)文檔 http://www.denx.de/twiki/bin/view/DULG/Manual。尤其是DULG文檔,從如何安裝建立交叉開發環境和解決U-Boot移植中常見問題都一一給出詳盡的說明;

③ 訂閱U-Boot使用者郵件清單 http://lists.sourceforge.net/lists/listinfo/u-boot-users。在移植U-Boot過程中遇有問題,在參考相關文檔和搜尋U-Boot-User郵件檔案庫 http://sourceforge.net/mailarchive/forum.php?forum_id=12898仍不能解決的情況下,第一時間送出所遇到的這些問題,衆多熱心的U-Boot開發人員會樂于迅速排查問題,而且很有可能,W.D本人會直接參與指導;

④ 在建立的開發環境下進行移植工作。絕大多數的開發環境是交叉開發環境。在這方面,DENX 和MontaVista均提供了完整的開發工具集;

⑤ 在目标闆與開發主機間接入硬體調試器。這是進行U-Boot移植應當具備且非常關鍵的調試工具。因為在整個U-Boot的移植工作中,尤其是初始階段,硬體調試器是我們了解目标闆真實運作狀态的唯一途徑。在這方面,W.D本人和衆多嵌入式開發人員傾向于使用BDI2000。一方面,其價格不如ICE調試器昂貴,同時其可靠性高,功能強大,完全能勝任移植和調試U-Boot。另外,網上也有不少關于BDI2000調試方面的參考文檔。

⑥ 如果在參考開發闆上移植U-Boot,可能需要移除目标闆上已有的BOOT LOADER。可以根據闆上BOOT LOADER的說明文檔,先着手解決在移除目前BOOT LOADER的情況下,如何進行恢複。以便今後在需要場合能重新裝入原先的BOOT LOADER。

5 U-Boot移植方法

目前,對于U-Boot的移植方法,大緻分為兩種。一種是先用BDI2000建立目标闆初始運作環境,将U-Boot鏡像檔案u-boot.bin下載下傳到目标闆RAM中的指定位置,然後,用BDI2000進行跟蹤調試。其好處是不用将U-Boot鏡像檔案燒寫到FLASH中去。但弊端在于對移植開發人員的移植調試技能要求較高,BDI2000的配置檔案較為複雜。另外一種方法是用BDI2000先将 U-Boot鏡像檔案燒寫到FLASH中去,然後利用GDB和BDI2000進行調試。這種方法所用BDI2000的配置檔案較為簡單,調試過程與U- Boot移植後運作過程相吻合,即U-Boot先從FLASH中運作,再重載至RAM中相應位置,并從那裡正式投入運作。唯一感到有些麻煩的就是需要不斷燒寫FLASH。但考慮到FLASH正常擦寫次數基本為10萬次左右,作為移植U-Boot,不會占用太多的次數,應該不會為FLASH燒寫有什麼擔憂。同時,W. D本人也極力推薦使用後一種方法。筆者建議,除非U-Boot移植資深人士或有強有力的技術支援,建議采用第二種移植方法。

6 U-Boot移植主要修改的檔案

從移植U-Boot最小要求-U-Boot能正常啟動的角度出發,主要考慮修改如下檔案:

① <目标闆>.h頭檔案,如include/configs/RPXlite.h。可以是U-Boot源碼中已有的目标闆頭檔案,也可以是新命名的配置頭檔案;大多數的寄存器參數都是在這一檔案中設定完成的;

② <目标闆>.c檔案,如board/RPXlite/RPXlite.c。它是SDRAM的驅動程式,主要完成SDRAM的UPM表設定,上電初始化。

③ FLASH的驅動程式,如board/RPXlite/flash.c,或common/cfi_flash.c。可在參考已有FLASH驅動的基礎上,結合目标闆FLASH資料手冊,進行适當修改; 

④ 序列槽驅動,如修改cpu/mpc8xx/serial.c序列槽收發器晶片使能部分。

7 U-Boot移植要點

① BDI2000的配置檔案。如果采用第二種移植方法,即先燒入FLASH的方法,配置項隻需很少幾個,就可以進行U-Boot的燒寫與調試了。對PPC 8xx系列的主機闆,可參考DULG文檔中TQM8xx的配置檔案進行相應的修改。下面,筆者以美國Embedded Planet公司的RPXlite DW闆為例,給出在嵌入式Linux交叉開發環境下的BDI2000參考配置檔案以作參考:

; bdiGDB configuration file for RPXlite DW or LITE_DW

; --------------------------------------------

[INIT]

; init core register

WSPR 149 0x2002000F ;DER : set debug enable register

; WSPR 149 0x2006000F ;DER : enable SYSIE for BDI flash program

WSPR 638 0xFA200000 ;IMMR : internal memory at 0xFA200000

WM32 0xFA200004 0xFFFFFF89 ;SYPCR

[TARGET]

CPUCLOCK 40000000 ;the CPU clock rate after processing the init list

BDIMODE AGENT ;the BDI working mode (LOADONLY | AGENT)

BREAKMODE HARD ;SOFT or HARD, HARD uses PPC hardware breakpoints

[HOST]

IP 173.60.120.5

FILE uImage.litedw 

FORMAT BIN

LOAD MANUAL ;load code MANUAL or AUTO after reset

DEBUGPORT 2001

START 0x0100

[FLASH]

CHIPTYPE AM29BX8 ;;Flash type (AM29F | AM29BX8 | AM29BX16 | I28BX8 | I28BX16)

CHIPSIZE 0x400000 ;;The size of one flash chip in bytes

BUSWIDTH 32 ;The width of the flash memory bus in bits (8 | 16 | 32)

WORKSPACE 0xFA202000 ; RAM buffer for fast flash programming

FILE u-boot.bin ;The file to program

FORMAT BIN 0x00000000

ERASE 0x00000000 BLOCK

ERASE 0x00008000 BLOCK

ERASE 0x00010000 BLOCK

ERASE 0x00018000 BLOCK

[REGS]

DMM1 0xFA200000

FILE reg823.def

② U-Boot移植參考闆。這是進行U-Boot移植首先要明确的。可以根據目标闆上CPU、FLASH、SDRAM的情況,以盡可能相一緻為原則,先找出一個與所移植目标闆為同一個或同一系列處理器的U-Boot支援闆為移植參考闆。如RPXlite DW闆可選擇U-Boot源碼中RPXlite闆作為U-Boot移植參考闆。對U-Boot移植新手,建議依照循序漸進的原則,目标闆檔案名暫時先用移植參考闆的名稱,在逐漸熟悉U-Boot移植基礎上,再考慮給目标闆重新命名。在實際移植過程中,可用Linux指令查找移植參考闆的特定代碼,如 grep –r RPXlite ./ 可确定出在U-Boot中與RPXlite闆有關的代碼,依此對照目标闆實際進行屏蔽或修改。同時應不局限于移植參考闆中的代碼,要廣泛借鑒U-Boot 中已有的代碼更好地實作一些具體的功能。

③ U-Boot燒寫位址。不同目标闆,對U-Boot在FLASH中存放位址要求不盡相同。事實上,這是由處理器中斷複位向量來決定的,與主機闆硬體相關,對 MPC8xx主機闆來講,就是由硬體配置字(HRCW)決定的。也就是說,U-Boot燒寫具體位置是由硬體決定的,而不是程式設計來選擇的。程式中相應U -Boot起始位址必須與硬體所确定的硬體複位向量相吻合;如RPXlite DW闆的中斷複位向量設定為0x00000100。是以, U-Boot 的BIN鏡像檔案必須燒寫到FLASH的起始位置。事實上,大多數的PPC系列的處理器中斷複位向量是0x00000100和0xfff00100。這也是一般所說的高位啟動和低位啟動的BOOT LOADER所在位置。可通過修改U-Boot源碼<目标闆>.h頭檔案中CFG_MONITOR_BASE 和board/<目标闆>/config.mk中的TEXT_BASE的設定來與硬體配置相對應。

④ CPU寄存器參數設定。根據處理器系列、類型不同,寄存器名稱與作用有一定差别。必須根據目标闆的實際,進行合理配置。一個較為可行和有效的方法,就是借鑒參考移植闆的配置,再根據目标闆實際,進行合理修改。這是一個較費功夫和考驗耐力的過程,需要仔細對照處理器各寄存器定義、參考設定、目标闆實際作出選擇并不斷測試。MPC8xx處理器較為關鍵的寄存器設定為SIUMCR、PLPRCR、SCCR、BRx、ORx。

⑤ 序列槽調試。能從序列槽輸出資訊,即使是亂碼,也可以說U-Boot移植取得了實質性突破。依據筆者調試經曆,序列槽是否有輸出,除了與序列槽驅動相關外,還與 FLASH相關的寄存器設定有關。因為U-Boot是從FLASH中被引導啟動的,如果FLASH設定不正确,U-Boot代碼讀取和執行就會出現一些問題。是以,還需要就FLASH的相關寄存器設定進行一些參數調試。同時,要注意序列槽收發晶片相關引腳工作波形。依據筆者調試情況,如果序列槽無輸出或出現亂碼,一種可能就是該晶片損壞或工作不正常。

⑥ 與啟動 FLASH相關的寄存器BR0、OR0的參數設定。應根據目标闆FLASH的資料手冊與BR0和OR0的相關位含義進行合理設定。這不僅關系到FLASH能否正常工作,而且與序列槽調試有直接的關聯。

⑦ 關于CPLD電路。目标闆上是否有CPLD電路絲毫不會影響U-Boot的移植與嵌入式作業系統的正常運作。事實上,CPLD電路是一個集中将闆上電路的一些邏輯關系可程式設計設定的一種實作方法。其本身所起的作用就是實作一些目标闆所需的脈沖信号和電路邏輯,其功能完全可以用一些邏輯電路與CPU口線來實作。

⑧ SDRAM的驅動。序列槽能輸出以後,U-Boot移植是否順利基本取決于SDRAM的驅動是否正确。與序列槽調試相比,這部分工作更為核心,難度更大。 MPC8xx目标闆SDRAM驅動涉及三部分。一是相關寄存器的設定;二是UPM表;三是SDRAM上電初始化過程。任何一部分有問題,都會影響U- Boot、嵌入式作業系統甚至應用程式的穩定、可靠運作。是以說,SDRAM的驅動不僅關系到U-Boot本身能否正常運作,而且還與後續部分相關,是相當關鍵的部分。

⑨ 補充功能的添加。在獲得一個能工作的U-Boot後,就可以根據目标闆和實際開發需要,添加一些其它功能支援。如以太網、LCD、NVRAM等。與序列槽和 SDRAM調試相比,在已有基礎之上,這些功能添加還是較為容易的。大多隻是在參考現有源碼的基礎上,進行一些修改和配置。

另外,如果在自主設計的主機闆上移植U-Boot,那麼除了考慮上述軟體因素以外,還需要排查目标闆硬體可能存在的問題。如原理設計、PCB布線、元件好壞。在移植過程中,敏銳判斷出故障态是硬體還是軟體問題,往往是關系到項目進度甚至移植成敗的關鍵,相應難度會增加許多。

完成一個目标闆的移植工作後,可考慮将移植結果以更新檔的形式發送到U-Boot使用者郵件清單,尤其是一些參考闆的移植結果。這是使用GPL代碼并遵循GPL 條款的展現。可在閱讀README相關更新檔說明的基礎上,添加适當的注釋,将自己列入光榮榜(CREDITS)。如果願意承擔所移植闆的後續更新工作,可以考慮加入維護人員(MAINTAINERS)開發隊伍行列。

誠然,在實際的U-Boot移植中無法避免地會遇到一些難以預料的問題,甚至出現倒退,尤其U-Boot移植新手,更會平添諸多難度。但筆者相信,在逐漸熟悉U-Boot移植方法、過程中,随着自身經驗的不斷積累,加之有衆多熱衷于開放源碼人士的鼎立相助,堅冰終會消融

armlinux的bootloader啟動代碼分析

Author : balancesli

mail : [email protected]

前階段做了一次基于at91rm9200引導部分的技術分析,主要采用了u-boot,這裡隻面向使用at91rm9200闆子的

的朋友做個簡單的推敲,希望起到抛磚引玉的作用.

關鍵詞 : 

u-boot: 一個開源的面向多個目标平台(ppc, mips, arm, x86)的bootloader.

at91rm9200 : Atmel 公司生産的基于arm9核的Soc處理器.

以下先給出at91rm9200引導流程圖

Boot program Flow Diagram 

Device Setup

|

|

Boot SPI DataFlash Boot --> Download from DataFlash --> run

|

TWI EEPROM Boot --> Download from EEPROM --> run

|

|

Parallel Boot --> Download from 8-bit Device --> 

| Xmodem protocol 

| |---DBGU Serial Download ---------------------> run

|____|

| DFU protocol

|-----USB download -----------------------> run 

在這裡我主要介紹通過片内引導和片外引導, 片内引導主要采用序列槽下載下傳并引導u-boot,并完成程式被燒寫到Flash上, 

然後就可以通過跳線的方式從片外引導執行已經燒寫到片外Flash上的引導程式(bootloader).

這裡要提及的是at91rm9200内部本身有128k的片内rom,其固化了一個bootloader和uploader, 用來支援程式的

下載下傳和引導,而且其内部固化的程式提供了很多内部服務接口(Internel Service)供我們來使用,例如Xmodem,Tempo

DataFlash, CRC, Sine服務接口,這樣我們就可以利用它所提供的Service interface API完成程式的下載下傳。

這裡主要介紹Xmodem接口服務。

at91rm9200内部固化的代碼在設計上采用了面向對象的設計方法,如下:

typedef struct _AT91S_Service 

{

char data;

char (*MainMethod)();

char (*ChildMethod)();

}AT91S_Service, *AT91PS_Service;

char AT91F_MainMethod()

{

}

char AT91F_ChildMethod()

{

}

AT91PS_Service AT91F_OpenDevice(AT91PS_Service pService)

{

pService->data = 0;

pService->MainMethod = AT91F_MainMethod;

pService->ChildMethod = AT91F_ChildMethod;

}

//使用方法如下

AT91S_Service service;

AT91PS_Service pService = AT91F_OpenDevice(&service);

pService->AT91F_MainMethmod();

.....

通過如上代碼片斷可以看出它采用了類似面向對象的設計方法。

其實如果各位朋友接觸過的話或者看過這本書的話,應該很容易便接受它。

下面以Xmodem服務為例子介紹:

at91rm9200内部提供的服務包含了幾個服務對象, 這些對象在片内啟動xmodem協定Host端和Targe端通訊時會用到.

typedef struct _AT91S_RomBoot 

{

const unsigned int version;

// Peripheral descriptors

const AT91S_MEMCDesc MEMC_DESC;

const AT91S_STDesc SYSTIMER_DESC;

const AT91S_Pio2Desc PIOA_DESC;

const AT91S_Pio2Desc PIOB_DESC;

const AT91S_USART2Desc DBGU_DESC;

const AT91S_USART2Desc USART0_DESC;

const AT91S_USART2Desc USART1_DESC;

const AT91S_USART2Desc USART2_DESC;

const AT91S_USART2Desc USART3_DESC;

const AT91S_TWIDesc TWI_DESC;

const AT91S_SPIDesc SPI_DESC;

// Objects entry

const AT91PF_OpenPipe OpenPipe;

const AT91PF_OpenSBuffer OpenSBuffer;

const AT91PF_OpenSvcUdp OpenSvcUdp;

const AT91PF_OpenSvcXmodem OpenSvcXmodem;

const AT91PF_OpenCtlTempo OpenCtlTempo;

const AT91PF_OpenDfuDesc OpenDfuDesc;

const AT91PF_OpenUsbDesc OpenUsbDesc;

const AT91PF_OpenSvcDataFlash OpenSvcDataFlash;

const AT91PF_SVC_CRC16 CRC16;

const AT91PF_SVC_CRCCCITT CRCCCITT;

const AT91PF_SVC_CRCHDLC CRCHDLC;

const AT91PF_SVC_CRC32 CRC32;

// Array

const AT91PS_SVC_CRC_BIT_REV Bit_Reverse_Array;

const AT91PS_SINE_TAB SineTab;

const AT91PF_Sinus Sine;

} AT91S_RomBoot;

//AT91S_Pipe

typedef struct _AT91S_Pipe

{

// A pipe is linked with a peripheral and a buffer

AT91PS_SvcComm pSvcComm;

AT91PS_Buffer pBuffer;

// Callback functions with their arguments

void (*WriteCallback) (AT91S_PipeStatus, void *);

void (*ReadCallback) (AT91S_PipeStatus, void *);

void *pPrivateReadData;

void *pPrivateWriteData;

// Pipe methods

AT91S_PipeStatus (*Write) (

struct _AT91S_Pipe *pPipe,

char const * pData,

unsigned int size,

void (*callback) (AT91S_PipeStatus, void *),

void *privateData

);

AT91S_PipeStatus (*Read) (

struct _AT91S_Pipe *pPipe,

char *pData,

unsigned int size,

void (*callback) (AT91S_PipeStatus, void *),

void *privateData

);

AT91S_PipeStatus (*AbortWrite)(struct _AT91S_Pipe *pPipe);

AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);

AT91S_PipeStatus (*AbortRead)(struct _AT91S_Pipe *pPipe);

AT91S_PipeStatus (*Reset)(struct _AT91S_Pipe *pPipe);

char (*IsWritten)(struct _AT91S_Pipe *pPipe, char const *pVoid);

char (*IsReceived) (struct _AT91S_Pipe *pPipe, char const *pVoid);

} AT91S_Pipe;

//AT91S_Buff

typedef struct _AT91S_SBuffer

{

AT91S_Buffer parent;

char *pRdBuffer;

char const *pWrBuffer;

unsigned int szRdBuffer;

unsigned int szWrBuffer;

unsigned int stRdBuffer;

unsigned int stWrBuffer;

} AT91S_SBuffer;

// AT91S_SvcTempo

typedef struct _AT91S_SvcTempo

{

// Methods:

AT91S_TempoStatus (*Start) (

struct _AT91S_SvcTempo *pSvc,

unsigned int timeout,

unsigned int reload,

void (*callback) (AT91S_TempoStatus, void *),

void *pData);

AT91S_TempoStatus (*Stop) (struct _AT91S_SvcTempo *pSvc);

struct _AT91S_SvcTempo *pPreviousTempo;

struct _AT91S_SvcTempo *pNextTempo;

// Data

unsigned int TickTempo; /

pAT91 = AT91C_ROM_BOOT_ADDRESS;//這裡取得内部ROM服務的入口位址

pAT91->OpenCtlTempo(&ctlTempo, (void *) &(pAT91->SYSTIMER_DESC));

ctlTempo.CtlTempoStart((void *) &(pAT91->SYSTIMER_DESC));

pXmBuffer = pAT91->OpenSBuffer(&sXmBuffer);

pSvcXmodem = pAT91->OpenSvcXmodem(&svcXmodem, (AT91PS_USART)AT91C_BASE_DBGU, &ctlTempo);

pAT91->OpenPipe(&xmodemPipe, pSvcXmodem, pXmBuffer);

xmodemPipe.Read(&xmodemPipe, (char *)AT91C_UBOOT_BASE_ADDRESS, AT91C_UBOOT_MAXSIZE, 

AT91F_XmodemProtocol, 0); 

while(XmodemComplete !=1);

//上面部分主要針對at91rm9200片内啟動時我們可以使用的片内接口服務介紹,玩H9200的朋友可以參考一下便知道緣由。

下面主要介紹at91rm9200片外啟動時所使用的bootloader-->u-boot.

一. bootloader 

BootLoader(引導裝載程式)是嵌入式系統軟體開發的非常重要的環節,它把作業系統和硬體平台銜接在一起,

是跟硬體體系密切相關的。

1.1 典型的嵌入式系統軟體部分Image memory layout : bootloader , bootloader param, kernel, rootfs.

1.2 引導模式 : 1. bootstrap或download

2. autoboot

1.3 u-boot簡介 :

u-boot是由Wolfgang Denk開發,它支援(mips, ppc, arm, x86)等目标體系,

可以在http://sourceforge.net 上下載下傳獲得源碼,

1.4 u-boot源代碼目錄結構

board:開發闆相關的源碼,不同的闆子對應一個子目錄,内部放着主機闆相關代碼。

at91rm9200dk/at91rm9200.c, config.mk, Makefile, flash.c ,u-boot.lds等都和具體開發闆的硬體和位址配置設定有關。

common:與體系結構無關的代碼檔案,實作了u-boot所有指令,

其中内置了一個shell腳本解釋器(hush.c, a prototype Bourne shell grammar parser), busybox中也使用了它.

cpu:與cpu相關代碼檔案,其中的所有子目錄都是以u-boot所支援的cpu命名.

at91rm9200/at45.c, at91rm9200_ether.c, cpu.c, interrupts.c serial.c, start.S, config.mk, Makefile等.

其中cpu.c負責初始化CPU、設定指令Cache和資料Cache等;

interrupt.c負責設定系統的各種中斷和異常,比如快速中斷、開關中斷、時鐘中斷、軟體中斷、

預取中止和未定義指令等;

start.S負責u-boot啟動時執行的第一個檔案,它主要是設定系統堆棧和工作方式,為跳轉到C程式入口點.

disk:裝置分區處理代碼。

doc:u-boot相關文檔。

drivers:u-boot所支援的裝置驅動代碼, 網卡、支援CFI的Flash、序列槽和USB總線等。

fs: u-boot所支援支援檔案系統通路存取代碼, 如jffs2.

include:u-boot head檔案,主要是與各種硬體平台相關的頭檔案,

如include/asm-arm/arch-at91rm9200/, include/asm-arm/proc-armv

net:與網絡有關的代碼,BOOTP協定、TFTP協定、RARP協定代碼實作.

lib_arm:與arm體系相關的代碼。(這裡我們主要面向的是ARM體系,是以該目錄是我們主要研究對象)

tools:編譯後會生成mkimage工具,用來對生成的raw bin檔案加入u-boot特定的image_header.

1.5 u-boot的功能介紹

 u-boot支援SCC/FEC以太網、OOTP/TFTP引導、IP和MAC的功能.

讀寫Flash、DOC、IDE、IIC、EEROM、RTC

支援串行口kermit和S-record下載下傳代碼, 并直接從序列槽下載下傳并執行。

在我們生成的核心鏡像時,要做如下處理.

1. arm-linux-objcopy -O binary -R.note -R.comment -S vmlinux linux.bin 

2. gzip -9 linux.bin

3. mkimage -A arm -O linux -T kernel -C gzip -a 0xc0008000 -e 0xc0008000 -n 

"Linux-2.4.19-rmk7” -d linux.bin.gz uImage

即在Linux核心鏡像vmLinux前添加了一個特殊的頭,這個頭在include/image.h中定義,

typedef struct image_header 

{

uint32_t ih_magic;

uint32_t ih_hcrc;

uint32_t ih_time;

uint32_t ih_size;

uint32_t ih_load;

uint32_t ih_ep;

uint32_t ih_dcrc;

uint8_t ih_os;

uint8_t ih_arch;

uint8_t ih_type;

uint8_t ih_comp;

uint8_t ih_name[IH_NMLEN];

} image_header_t;

當u-boot引導時會對這個檔案頭進行CRC校驗,如果正确,才會跳到核心執行.

如果u-boot啟動以後會出現

u-boot>

敲入help, 會出現大量的指令提示,Monitor command

go - start application at address 'addr'

run - run commands in an environment variable

bootm - boot application image from memory

bootp - boot image via network using BootP/TFTP protocol

tftpboot- boot image via network using TFTP protocol

and env variables "ipaddr" and "serverip"

(and eventually "gatewayip")

rarpboot- boot image via network using RARP/TFTP protocol

diskboot- boot from IDE devicebootd - boot default, i.e., run 'bootcmd'

loads - load S-Record file over serial line

loadb - load binary file over serial line (kermit mode)

md - memory display

mm - memory modify (auto-incrementing)

nm - memory modify (constant address)

mw - memory write (fill) 

cp - memory copy

cmp - memory compare

crc32 - checksum calculation

imd - i2c memory display

imm - i2c memory modify (auto-incrementing)

inm - i2c memory modify (constant address)

imw - i2c memory write (fill)

icrc32 - i2c checksum calculation

iprobe - probe to discover valid I2C chip addresses

iloop - infinite loop on address range

isdram - print SDRAM configuration information

sspi - SPI utility commands

base - print or set address offset

printenv- print environment variables

setenv - set environment variables

saveenv - save environment variables to persistent storage

protect - enable or disable FLASH write protection

erase - erase FLASH memory

flinfo - print FLASH memory information

bdinfo - print Board Info structure

iminfo - print header information for application image

coninfo - print console devices and informations

ide - IDE sub-system

loop - infinite loop on address range

mtest - simple RAM test

icache - enable or disable instruction cache

dcache - enable or disable data cache

reset - Perform RESET of the CPU

echo - echo args to console

version - print monitor version

help - print online help

? - alias for 'help'

u-boot支援大量的指令可用, 這裡就不作介紹,大家有興趣可以看看u-boot 的README文檔

3.3 對u-boot-1.0.0的修改和移植

1.6 關于u-boot的移植如下,由于u-boot的軟體設計體系非常清晰,它的移植工作并不複雜,

相信各位的代碼閱讀功力不錯的話,參照如下就可以完成。

If the system board that you have is not listed, then you will need

to port U-Boot to your hardware platform. To do this, follow these

steps:

1. Add a new configuration option for your board to the toplevel

"Makefile" and to the "MAKEALL" script, using the existing

entries as examples. Note that here and at many other places

boards and other names are listed in alphabetical sort order. Please

keep this order.

2. Create a new directory to hold your board specific code. Add any

files you need. In your board directory, you will need at least

the "Makefile", a ".c", "flash.c" and "u-boot.lds".

3. Create a new configuration file "include/configs/.h" for

your board

4. If you're porting U-Boot to a new CPU, then also create a new

directory to hold your CPU specific code. Add any files you need.

5. Run "make _config" with your new name.

6. Type "make", and you should get a working "u-boot.srec" file

7. Debug and solve any problems that might arise.

[Of course, this last step is much harder than it sounds.]

為了使u-boot-1.0.0支援新的開發闆,一種簡便的做法是在u-boot已經支援的開發闆中參考選擇一種較接近闆的進行修改,

幸運的是在u-boot-1.0.0中已經有了at91rm9200的支援。

1.7 與at91rm9200相關的u-boot代碼

在include/configs/at91rm9200dk.h 它包括開發闆的CPU、系統時鐘、RAM、Flash系統及其它相關的配置資訊。

在include/asm-arm/AT91RM9200.h, 該檔案描述了H9200寄存器的結構及若幹宏定義。

具體内容要參考相關處理器手冊。

在cpu/at91rm9200/目錄下别為cpu.c、interrupts.c和serial.c等檔案.

在board/at91rm9200dk/目錄下分别為flash.c、at91rm9200dk.c, config.mk, Makefile,u-boot.lds

flash.c : u-boot讀、寫和删除Flash裝置的源代碼檔案。由于不同開發闆中Flash存儲器的種類各不相同,

是以,修改flash.c時需參考相應的Flash晶片手冊。它包括如下幾個函數:

unsigned long flash_init (void ),Flash初始化;

void flash_print_info (flash_info_t *info),列印Flash資訊;

int flash_erase (flash_info_t *info, int s_first, int s_last),Flash擦除;

volatile static int write_dword (flash_info_t *info, ulong dest, ulong data),Flash寫入;

int write_buff (flash_info_t *info, uchar *src, ulong addr, ulong cnt),從記憶體複制資料。

u-boot.lds :linker scripte, 設定u-boot中各個目标檔案的連接配接位址.

網口裝置控制程式

  在drivers/目錄中網口裝置控制程式cs8900, bcm570x等, 還可以添加其他網卡驅動

int eth_init (bd_t *bd) : 初始化網絡裝置;

void eth_halt (void) : 關閉網絡裝置;

int eth_send (volatile void *packet,int len) : 發送資料包;

int eth_rx (void) : 接收資料包。

Makefile

  在u-boot-1.0.0/Makefile中 

at91rm9200dk_config : unconfig

./mkconfig $(@:_config=) arm at91rm9200 at91rm9200dk

1.8 編譯u-boot

  make at91rm9200_config

Configuring for at91rm9200 board...

make all

生成三個檔案:u-boot.bin, u-boot, u-boot.srec

u-boot.bin is a raw binary image

u-boot is an image in ELF binary format

u-boot.srec is in Motorola S-Record format (objcopy -O srec -R.note -R.comment -S [inputfile] [outfile]

以上工作完成我們可以通過序列槽将u-boot.bin下載下傳到主機闆的SDRAM中,它會自動執行, 并出現uboot>

這裡我們可以通過序列槽把boot.bin, u-boot.bin.gz下載下傳到主機闆,再用u-boot的提供的寫flash功能分别

把boot.bin, u-boot.bin.gz寫入到flash中,完成以上工作後,對主機闆跳線選擇片外啟動,

闆子複位後會自動啟動u-boot.

二.loader.bin, boot.bin, u-boot.bin代碼執行流分析.

以上三個檔案時at91rm9200啟動所需要的三個bin,他們的實作代碼并不難。

如果是你是采用at91rm9200的評估版,應該能得到其源碼。

2.1 loader.bin 執行流程,這個檔案主要在片内啟動從序列槽下載下傳代碼時會用到

loader/entry.S init cpu

b main ---> crt0.S

--> copydata --> clearbss --> b boot

main.c --> boot -->

pAT91 = AT91C_ROM_BOOT_ADDRESS;

--> pAT91->OpenSBuffer

--> pAT91->OpenSvcXmodem

---> AT91F_AIC_ConfigureIt

AT91F_AIC_EnableIt

AT91F_DBGU_Printk("XMODEM: Download U-BOOT ");

Jump.S

// Jump to Uboot BaseAddr exec

Jump((unsigned int)AT91C_UBOOT_BASE_ADDRESS) 

2.2 boot.bin執行流程 該檔案會在從片内啟動時被下載下傳到闆子上,以後還會被燒寫到片外Flash中,以便在片外啟動時

用它來引導并解壓u-boot.gz,并跳轉到u-boot來執行。

boot/entry.S

b main --> crt0.S --> copydata --> clearbss --> b boot

T91F_DBGU_Printk(" ");

AT91F_DBGU_Printk("************************************** ");

AT91F_DBGU_Printk("** Welcome to at91rm9200 ** ");

AT91F_DBGU_Printk("************************************** ");

boot/misc.s

----> decompress_image(SRC,DST,LEN) --> gunzip 

//jump to ubootBaseAddr exec 這裡跳轉到解壓u-boot.gz的位址處直接開始執行u-boot

asm("mov pc,%0" : : "r" (DST));

2.3 uboot.bin執行流程

u-boot/cpu/at91rm9200/start.S 

start --->reset 

---> copyex ---> cpu_init_crit 

---> --> start_armboot

u-boot/lib_arm/board.c

init_fnc_t *init_sequence[] = {

cpu_init,

board_init,

interrupt_init,

env_init,

init_baudrate,

serial_init,

console_init_f,

display_banner,

dram_init,

display_dram_config,

checkboard,

NULL,

};

---> start_armboot ---> call init_sequence

---> flash_init --> display_flash_config 

---> nand_init ---> AT91F_DataflashInit 

---> dataflash_print_info --> env_relocate

---> drv_vfd_init --> devices_init --> jumptable_init

---> console_init_r --> misc_init_r --> enable_interrupts

---> cs8900_get_enetaddr --> board_post_init --> 

u-boot/common/main.c

for (;;) 

{

main_loop () --> u_boot_hush_start --> readline

--> abortboot 

-->printf("Hit any key to stop autoboot: %2d ", bootdelay);

}

以上是at91rm9200啟動并進入u-boot的執行流分析。後面u-boot還會将uImage解壓到特定的位置并開始執行核心代碼。

三. 綜述

總之, 不同廠商的出的Soc片子在啟動方式大都提供片内和片外啟動兩種方式,一般都是在片内固化一段小程式

友善于程式開發而已,在其DataSheet文檔中有詳盡的描述。若是對at92rm9200有興趣或玩過的朋友,可以與我共同探讨互相學習。

下一篇: cups移植

繼續閱讀