1. 程式人生 > >ARM-Linux嵌入式系統啟動流程

ARM-Linux嵌入式系統啟動流程

        作為一個嵌入式新手,閱讀資料之後做一下筆記還是很有必要的,下面從四個階段來描述嵌入式系統的大致啟動流程。如下圖所示:

圖片引用自OMAPpedia的WIKI

其他相關參考資料:

TI官方WIKI的boot sequence

       由此可見啟動流程分為四個步驟,分別是ROM Code -> x-loader -> U-BOOT -> kernel ,下面從四個階段來進行分析。

1、第一階段啟動ROM-Code

        每一個晶片都會有一個片內ROM,在出廠時廠家在其中固化好了一段程式碼,不可更改,這段程式碼執行第一階段的啟動任務。當晶片上電後,這段ROM-Code會讀取啟動引腳配置(boot configuration pins),然後根據引腳配置情況來決定以哪種方式下載接下來的外部啟動程式碼(指的就是x-loader),下載的方式可以是NAND, UART,或者SD/MMC卡。

        比如BBB板子上,如果上電時沒有按住boot按鍵,那麼ROM-Code從板子上的eMMC中的第一啟動分割槽(boot partition)下載x-loader(就是通常板子上電後,電腦上彈出的大概70MB的碟符中的MLO檔案);如果上電時按住了boot按鍵,那麼ROM-Code從板子上的SD卡的第一啟動分割槽(boot partition)下載x-loader(編譯u-boot後得到的MLO檔案,製作SD卡時這個檔案連同u-boot.img一起放在第一分割槽,事實上SD卡分割槽以及檔案的情況和eMMC中是一樣的)。

那麼ROM-Code具體完成了哪些任務呢?

step1:初始化最小執行系統,包括時鐘初始化、片內

SRAM初始化以及一些晶片級外設的初始化。

step2:讀取系統啟動引腳配置後,按相應的啟動裝置列表的順序,依次訪問這些裝置直到下載x-loader到SRAM成功。

step3:x-loader被下載到片內SRAM後,CPU控制權移交x-loader,ROM-Code任務結束。

Note:在step2中假若啟動裝置列表順序是1、serial(UART3) , 2、SD card(MMC1), 3、NAND flash(eMMC),那麼,

        首先ROM-Code將傳送一個ID到串列埠(串列埠3),此時主機在一定時間內響應了這個ID,那麼ROM-Code將把接下來收到的資料(MLO)寫入片內SRAM,寫完後CPU控制權移交MLO。如果一定時間內主機沒有進行響應,

        接著ROM-Code將在MMC1控制器上尋找SD卡,如果找到一個SD卡,那麼讀取第一啟動分割槽(boot partition),接著掃描該分割槽根目錄,在根目錄下尋找名為MLO的檔案,並將這個檔案下載到片內SRAM,再把控制權移交MLO。事實上MLO檔案包含了x-loader二進位制檔案以及一些頭部資訊,這些資訊指示了MLO檔案應該下載在片內SRAM的哪個起始地址以及檔案大小。如果ROM-Code沒有找到SD卡,

        最後ROM-Code將NAND flash的第一個分割槽尋找MLO檔案,如果發現第一個分割槽損壞或者空白分割槽,那麼嘗試第二個分割槽(最多嘗試4個分割槽),找到MLO檔案同樣將其下載到片內SRAM,在移交控制權。(對於eMMC將會進行相同的操作)。

2、第二階段啟動x-loader

         x-loader事實上是u-boot的一個簡化分支而來,其原始碼目錄結構和u-boot比較相似。接上步驟,他運行於片內SRAM中承擔著下載第三階段啟動程式碼u-boot.img到系統片外的主要記憶體SDRAM的任務。

         下面是一段x-loader主頁的原文應用,介紹x-loader的作用和原因。

       X-loader is a small first stage boot loader derived from the u-boot base code to be loaded into the internal static ram by the OMAP ROM code. Because the internal static ram is very small (64k-32k), x-loader is stripped down to the essentials and is used to initialize memory and enough of the peripheral devices to access and load the second stage loader (UBoot) into main memory.

          由於片內SRAM空間太小,所以u-boot無法在其中執行,而NAND flash也不支援XIP(eXecute In Place),所以只能將u-boot搬至片外主存SDRAM中執行,所以最後應該是x-loader、u-boot被燒寫在NAND flash中(即MLO、u-boot.img被燒寫在SD卡或者eMMC的第一啟動分割槽中),上電後ROM-Code將體積較小的x-loader搬至片內SRAM中執行,而執行在SRAM中的x-loader又初始化片外SDRAM,並將NAND Flash中的u-boot下載至SDRAM,控制權移交u-boot。 

相關參考資料:

X-loader主頁以及程式碼庫,支援OMAP3、BeagleBoard、BeagleBoard XM、zoom3、OMAP4、PandaBoard等。

從beagleboard.org找到的x-loader工程程式碼庫,這個x-loader程式碼獨立於u-boot,對原始碼進行整理後,編譯的二進位制檔案支援所有的啟動方式,這個程式碼庫由Steve Sakoman託管在gitorious上。網頁中同時告訴你如何根據板子、CPU型別配置來x-loader,推薦了TI的一些工具用來生成目標檔案、燒寫檔案。

對X-loader進行了原始碼方面的分析,特別細緻

另外,一般從DENX下載的UBOOT原始碼編譯後能同時得到MLO和u-boot.img。

那麼X-loader具體完成了哪些任務呢?

step1:配置複用引腳、初始化時鐘頻率、初始化片外SDRAM儲存器

step2:CPU、板級外設初始化、串列埠控制檯初始化

step3:讀取啟動裝置,將u-boot讀取到SDRAM中,控制權移交u-boot,並不再返回。

Note:在step3中,x-loader從何處讀取u-boot.img?一般來說,MLO和u-boot.img都會放在同一個分割槽中或者以相同的方式獲取,所以如果x-loader是從串列埠獲得的,那麼x-loader執行時,也會從串列埠等待主機發送u-boot.img檔案。

 3、第三階段啟動任務u-boot

          和功能強大的u-boot相類似的BootLoader還有Blob,他們任務是通過各種方式將核心下載至SDRAM,並傳遞一些核心啟動引數。所以介紹的相關資料也將u-boot的啟動任務分成兩個階段stage1和stage2進行講解。stage1主要完成基本硬體裝置的初始化和為載入stage2部分的程式碼準備RAM空間,stage2則是為引導核心準備環境。另外,u-boot還可以工作在啟動載入模式和下載模式,在啟動載入模式下,是u-boot正常的工作模式,即正常的把核心載入到核心中,而在下載模式下,一般是u-boot要更新nand flash上的核心映像,或者是第一次燒寫核心映像到flash。其實u-boot的功能和STM32處理器的IAP程式功能極為相似。

其他相關參考資料:

對於不瞭解bootloader概念的入門絕好資料!!!

u-boot原始碼分析

Linux Core U-boot User's Guide,TI出的一篇基於BBB等一些平臺的講解內容涉及裝置樹、MLO和u-boot編譯、環境變數等的絕好的資料,必看!!!

關於u-boot

那麼u-boot到底完成了那些任務呢?

stage1

step1:硬體裝置初始化。

step2:為載入Bootloader的stage2準備RAM空間。

step3:拷貝Bootloader的stage2到RAM空間中。

step4:設定好堆疊。

step5:跳轉到stage2的C入口點。

stage2

step1:初始化本階段要用到的硬體裝置。

step2:檢測系統記憶體對映。

step3:將kernel映像和根檔案系統映像從flash上讀到RAM空間中。

step4:為核心設定啟動引數。

step5:呼叫核心。

4、啟動核心kernel

            核心是一個作業系統功能發揮的根本,從核心原始碼的目錄結構上看,可以知道核心大致分為五個模組,分別是記憶體管理、程序排程、虛擬檔案系統、網路介面、程序間通訊。

相關參考資料

獲取核心原始碼的標準

英蓓特提供的Angstrom原始碼

另外,TI-SDK的包裡面也有核心原始碼,TI的資料只能用海量兩個字來形容!

核心架構分析

Linux核心啟動分析,分析非常透徹,包括原碼分析

從作業系統的啟動角度來看,核心的啟動過程分為三個階段。

step1:核心的自解壓過程。

step2:主要工作是設定ARM處理器的工作模式、使能MMU、設定一級頁表等。

step3:主要為C程式碼,包括核心初始化的全部工作。

5、載入根檔案系統

        根檔案系統首先是一種檔案系統,該檔案系統不僅具有普通檔案系統的儲存資料檔案的功能,但是相對於普通的檔案系統,它的特殊之處在於,它是核心啟動時所掛載(mount)的第一個檔案系統,核心程式碼的映像檔案儲存在根檔案系統中,系統引導啟動程式會在根檔案系統掛載之後從中把一些初始化指令碼(如rcS,inittab)和服務載入到記憶體中去執行。我們要明白檔案系統和核心是完全獨立的兩個部分。在嵌入式中移植的核心下載到開發板上,是沒有辦法真正的啟動Linux作業系統的,會出現無法載入檔案系統的錯誤。

        那麼根檔案系統在系統啟動中到底是什麼時候掛載的呢?先將/dev/ram0掛載,而後執行/linuxrc.等其執行完後。切換根目錄,再掛載具體的根檔案系統.根檔案系統執行完之後,也就是到了Start_kernel()函式的最後,執行init的程序,也就第一個使用者程序。對系統進行各種初始化的操作。

        根檔案系統之所以在前面加一個”根“,說明它是載入其它檔案系統的”根“,既然是根的話,那麼如果沒有這個根,其它的檔案系統也就沒有辦法進行載入的。它包含系統引導和使其他檔案系統得以掛載(mount)所必要的檔案。根檔案系統包括Linux啟動時所必須的目錄和關鍵性的檔案,例如Linux啟動時都需要有init目錄下的相關檔案,在 Linux掛載分割槽時Linux一定會找/etc/fstab這個掛載檔案等,根檔案系統中還包括了許多的應用程式bin目錄等,任何包括這些Linux 系統啟動所必須的檔案都可以成為根檔案系統。

根檔案系統至少包括以下目錄:

/etc/儲存重要的配置檔案。

/bin/儲存常用且開機時必須用到的執行檔案。

/sbin/儲存著開機過程中所需的系統執行檔案。

/lib/儲存/bin/及/sbin/的執行檔案所需的連結庫,以及Linux的核心模組。

/dev/儲存裝置檔案。

注:五大目錄必須儲存在根檔案系統上,缺一不可。

以只讀的方式掛載根檔案系統,之所以採用只讀的方式掛載根檔案系統是因為:此時Linux核心仍在啟動階段,還不是很穩定,如果採用可讀可寫的方式掛載根檔案系統,萬一Linux不小心宕機了,一來可能破壞根檔案系統上的資料,再者Linux下次開機時得花上很長的時間來檢查並修復根檔案系統。

    掛載根檔案系統的而目的有兩個:一是安裝適當的核心模組,以便驅動某些硬體裝置或啟用某些功能;二是啟動儲存於檔案系統中的init服務,以便讓init服務接手後續的啟動工作。

相關參考資料

Linux核心啟動及根檔案系統載入過程