<2012 12 09> [原創]Bootloader(U-boot)學習研究心得


  我認為學習和應用u-boot對於剛接觸的人來說最大的困難在於其功能比較全,文件(.S .c .h makefile文件)非常多,結構也比較復雜,難以理清各方面的關系。熟悉了一段時間之后,發現還是有很多的規律可以總結的。

一、首先要理解bootloader的作用,以及U-boot具體可以實現什么樣的一些功能。

二、弄清U-boot的啟動流程,這時候需要跟着整個程序走一遍,先不管實現這個流程的代碼文件與文件結構。

三、熟悉整個U-boot的文件結構,重點是理解那些“移植到不同開發板上需要修改的”文件,以及它們之間的關系。重點這些文件是怎樣與實際的硬件(開發板)對應和統一起來的。

四、進一步細化第二步和第三步,這是一個來回穿插的考查,考查在具體的實現整個程序流程和功能中,這些文件的結構與層次關系是怎樣實施的。

五、動手針對一個開發板進行移植實驗,可以參考別人的移植記錄,但是通過自己的動手實驗,會更加熟悉U-boot,並提高解決實際問題(排錯)的能力。

U-boot下載地址: ftp://ftp.denx.de/pub/u-boot/  

 

說到底,bootloader是一段裸機程序,是直接與硬件打交道的。① 它在系統上電后開始執行(PC系統中在bootloader之前有個BIOS固件,嵌入式系統中一般沒有),其最終目的是“初始化硬件設備,准備好軟件環境,最后調用操作系統內核”。② 為了方便進行底層開發(比如調試內核等),bootloader增加了很多功能,主要有UART、網絡、USB、讀寫Flash(Nor or Nand)、解壓縮、LCD支持等等。這樣的bootloader具有比較強大的功能,除了不能進行多任務調度,已經類似一個小型操作系統了,被稱為“Monitor”。U-boot就是這樣一種bootloader,全功能體積高達數百Kbytes,如果不需要這些開發調試功能,發布產品時它能配置到很小的體積。

那我們也知道其實OS(如linux)的Kernel其實也是一段裸機程序,也是直接掌管硬件的,不過這個程序極其復雜,許許多多的計算機專家和黑客為其耗費心血,如果三四百K的U-boot已經比較復雜,那么一個典型功能的linux Kernel編譯后竟然能高達萬Kbytes,光從代碼量來看,linux的復雜度已經是U-boot的百倍。而其實遠不止。

雖然kernel很complex,但終究不過是一段裸機代碼,Bootloader進行所謂的“kernel引導”,其過程不過是從bootloader里的一句跳轉代碼,跳轉到kernel代碼處(執行kernel中的第一個函數),所謂傳遞參數也不過是bootloader和kernel約定一個內存地點存放。在這個過程中,bootloader和kernel雖然都處於同一個內存里,但是它們除了“引導”與“傳遞有限的參數”這樣的關系,並無其它關系,完全是兩個獨立的程序。之所以在kernel之前用一個bootloader來引導(為什么開機不能直接執行kernel,所有事情都交給kernel做?),其思想類似於一個板級支持包:kernel假定執行的時候已經具備了一個基本的硬件運行條件,這個環境的初始化(最底層的一些硬件初始化、硬件信息設定)需要bootloader來完成,也許這樣kernel的設計才能保持一定的一致性。

U-boot為了能支持很多不同的體系結構、SoC、電路板,設計了一種代碼文件的組織結構(包括makefile文件),這種設計很大程度上借鑒了linux kernel,很多硬件驅動代碼也直接從linux kernel中搬遷過去,因為linux kernel也是一種移植性非常好的程序。“在通用代碼與系統特定代碼之間,不惜代價,保持一條明確的分界線”,這是可移植程序設計的不變箴言。

 

U-boot的啟動流程分析,上一篇轉載的博文敘述的很全面,也比較有條理。

---->《U-boot研究與移植心得》   http://www.cnblogs.com/andrew-wang/archive/2012/12/06/2806238.html

總的主線就是: 初始化硬件--->加載內核到內存--->設置好各項參數--->跳轉到內核。其他命令都是開發調試時使用的。

 

U-boot的代碼文件組織架構是比較重要的一項,首先是要知道U-boot的代碼結構經歷過什么樣的“歷史變遷”。博主的這篇《U-boot版本與移植概況》有些這方面的知識(http://www.cnblogs.com/andrew-wang/archive/2012/11/04/2753971.html)。無論怎樣變化,代碼的組織架構的目標都是要使U-boot的結構更清晰、移植性更好,而其實每次的變化都是微小的進步。以版本2010.09的U-boot為例:

復制代碼
├── api 存放uboot提供的API函數
├── arch 與體系結構相關的代碼,uboot的重頭戲  +++
├── board 根據不同開發板定制的代碼,代碼也不少  +++
├── common 通用的代碼,涵蓋各個方面,已命令行處理為主
├── disk 磁盤分區相關代碼
├── doc 文檔,一堆README開頭的文件
├── drivers 驅動,很豐富,每種類型的設備驅動占用一個子目錄  +++
├── examples 示例程序
├── fs 文件系統,支持嵌入式開發板常見的文件系統
├── include 頭文件,已通用的頭文件為主  +++
├── lib 通用庫文件
├── nand_spl NAND存儲器相關代碼
├── net 網絡相關代碼,小型的協議棧
├── onenand_ipl
├── post 加電自檢程序
└── tools 輔助程序,用於編譯和檢查uboot目標文件
復制代碼

可以將這些代碼分為4類

1、平台相關(arch)、或開發板相關(board)(系統特定代碼)
2、通用的函數(include common)
3、通用驅動(disk  drivers  fs  nand_spl  onenand_ipl  net  post)
4、工具、實例、文檔(api  doc  examples  tools)

 除了引導kernel的主線之外,U-boot的支持的各種硬件操作驅動實現,有一定的層次性:為了實現“通用的函數”,首先要調用“通用驅動”,這些通用驅動如果有引用“平台相關”的宏或者外部函數,就需要調用到這些系統特定代碼。其層次是"  2 <--> 3 <--> 1  " 。

一般來說,移植U-boot主要就是修改“1”項中的代碼,以及在include/configs/XXX.h中打開需要的功能以及定義一些常量,具體的實現就是在arch和board子目錄,來看一下這兩個子目錄的組織:

復制代碼
|--arch\
|--config.mk ===>配置腳本   |--arm\     |--cpu\ 子目錄對應一種處理器的不同產品型號或者系列;       |--arm920t\         |--a320\         |...         |--s3c24x0\           |--interrupts.c           |--speed.c           |--timer.c           |--usb.c           |--usb_ohci.c           |--usb_ohci.h         |--Makefile         |--cpu.c         |--interrupts.c         |--start.S <==整個bootloader入口點         |--u-boot.lds <==鏈接腳本         |--Makefile    |--include\ 子目錄是處理器用到的頭文件;        |--asm\          |--arch-a320\          |...          |--arch_s3c24x0\             |--memory.h             |--s3c2400.h             |--s3c2410.h             |--s3c24x0_cpu.h             |--s3c24x0.h          |...          |--proc-armv\(公用)          |--atomic.h          |--bitops.h          |--byteorder.h          |--cache.h          |--... (等共24個.h公用頭文件)    |--lib\ 目錄對應用到處理器公用的代碼;       |--board.c       |--config.mk
      |--... (等共16個文件) |--board\   |--ppmc7xx\   |...   |--samsung\       |--goni\       |--smdk2400\       |--smdk2410\           |--smdk2410.c           |--flash.c           |--lowlevel_init.S           |--config.mk           |--Makefile           |--nand_read.c           |--nand_read_save.c   |...

 復制代碼

我們知道ARM是ARM公司設計的一種體系結構,這個公司專門設計IP core出售給半導體廠商加上一些外圍部件生產SoC,這些IP Core有很多代的產品,如v4、v5、v6、v7,還根據有沒有thumb指令集(t)、DSP加強(e)、java硬件加速(j)等進一步細分。而每一代IP core都有不少半導體廠家生產SoC,如qualcomm、Samsung、TI等,因此ARM平台的組織最為復雜。

打開arch,其中所有的子目錄代表一種體系結構11種;選取其中的ARM類,里面包含cpu、include、lib三個子目錄,其中lib是這個體系結構的公用代碼;include下面只有一個子目錄asm,其中包含的是不同的SoC對應的頭文件及一些公用頭文件;cpu中是ARM體系結構中不同代際的IP core,每種IP core中都有一些子目錄代表不同廠商的SoC以及公用代碼。(其他體系結構的platform沒這么復雜)。

board則是基於某種SoC設計的電路板,2010.09的版本支持有近290種board。一般選擇相似的board進行U-boot的移植。當然board里面的代碼都是跟特定的board有關的。因此,要分arch、IP-core、SoC、Board 4個層次來理解U-boot在ARM系統上的移植性,而其他體系結構有可能只有2-3層。以基於S3C2440開發板為例,這種層次關系像下圖:

要完全理解U-boot的代碼,需要熟悉平台硬件及其匯編、熟悉C語言、熟悉編譯原理。由於U-boot的編譯是基於linux和Gcc的,因此還需要對linux的技術文化有一定的理解,比如其makefile體系架構,前文的博主推薦看《從庖丁解牛說uboot如何編譯》《詳細分析make uboot 最后的編譯鏈接的具體執行過程》這兩篇(看官去Google~)。博主的《U-boot架構分析與移植重點》其中對編譯鏈接過程有個主線的介紹(主要參考了韋東山的書)---> http://www.cnblogs.com/andrew-wang/archive/2012/11/04/2753972.html  。U-boot文件雖多,結構雖復雜,但搞清楚了主線,就比較好理解了。

 

 四、

具體的移植過程,從下載原版U-boot、linux kernel、busybox、FSmaker、gcc,到最后用它們組件一個完整的嵌入式系統,參考下面的博文,它們主要轉載自yanghao和趙春江兩位的博客(都標明了source)(另外也推薦mobilefzb的博客,其中關於TQ2440的移植博文也很好 http://nervfzb.blog.163.com/ ),我也都在FL2440開發板上實驗過,原文可能有問題的地方做了補充注釋,有些地方稍作修改以便理解,有些是原創的:

FL2440開發板的U-boot-2010.09版本移植(一)建立特定開發板的U-boot框架

FL2440開發板的U-boot-2010.09版本移植(二)片上系統SoC初始化移植

FL2440開發板的U-boot-2010.09版本移植(三) 如何利用JLINK燒寫U-boot到NAND Flash中

FL2440開發板的U-boot-2010.09版本移植(四)Nor Flash啟動支持

FL2440開發板的U-boot-2010.09版本移植(五)支持DM9000網卡和板級相關LED等配置

FL2440開發板的U-boot-2010.09版本移植(六)uboot架構中NAND Flash驅動修改

FL2440開發板的U-boot-2010.09版本移植(七)NAND Flash啟動支持

FL2440開發板的U-boot-2010.09版本移植(八)LCD的支持

FL2440開發板的U-boot-2010.09版本移植 ____ U-boot中常用參數設定及常用宏(u-boot環境變量、USB、內核引導)

FL2440開發板的U-boot-2010.09版本移植(九)NAND Flash啟動支持的一種新型方法,利用U-Boot自帶nand_spl/nand_boot.c

FL2440開發板的U-boot-2010.09版本移植(十)支持燒寫YAFFS2文件系統

FL2440開發板的U-boot-2010.09版本移植(十一)U-boot引導內核設置、編譯linux內核、編譯文件系統、加載...

 以下原創:

使用JTAG接口進行裸板開發

在U-boot上用tftp進行文件傳輸需要注意的地方

J-link & AXD仿真調試ARM開發板 “halt不住” 的問題的解決

U-boot研究與移植心得

U-boot(1)版本與移植概況

U-boot(2)U-boot架構分析與移植重點

 

最后,希望這篇博文能幫助到U-boot的初學者。^_^

                                              By Andrew 2012.12.10


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM