不同嵌入式系統啓動過程分析(小型單片機以51爲例,大型單片機以ARM-A系列爲例)

啓動即是芯片上電覆位要運行的程序,啓動作爲一個模塊獨立於操作系統而在,因爲操作系統需要通過啓動這個模塊來加載和引導的。所以啓動的英文術語是boot loader。我對boot loader的定義包括兩部分:1.加載os 2. 爲了讓os能夠正常運行所要做的硬件和軟件初始化工作。

我們常常看到boot loader這個詞語用於arm引導linux,X86引導windows等等。可見一般意義上,能用上boot loader都是一些計算能力強並外掛SDRAM的SOC方案。

那我們咱們去理解單片機這種內存資源有限型的嵌入式系統的啓動呢?就以51爲例。

(小型)51單片機啓動流程

           51體系SOC一般都是內置K字節級別的nor flash用於運行代碼,並內置一塊K級別較小的ram用於數據讀寫。很明顯這種系統跑不了linux這種高大上的系統,那51的啓動都幹嘛呢?我們從程序開發流程說起:

           1)編寫程序,編譯,鏈接成可執行文件。一般在keil集成環境中。

           2)keil的二進制工具(類似gcc的objcopy)中的可執行文件,抽取code和data數據,生成帶有加載地址的.HEX格式文件。記住是加載地址,而不是運行地址。

           3)燒寫.HEX文件數據到nor flash,其根據的是文件中的加載地址。一般來說,代碼段的加載地址和運行地址是一樣的,這樣才能在nor flash中跑起來。但是data是要放在內置ram區域才能可讀寫的,可是ram掉電會消失啊。所以data是先加載到nor flash的。即data的運行地址在ram區域,而加載地址在flash區域。

           4)上電覆位後,啓動代碼會進行硬件初始化,例如時鐘,看門狗,串口等等

           5)準備好棧,然後把data從加載的地方copy到ram的運行區域(鏈接地址)

           6)初始化好bss,然後就jump到主程序開始跑啦。

          簡單的嵌入式系統一般沒有os,就是上面的流程。這種系統的代碼量一般比較小,全部放到內置的nor flash中,沒有外掛的nand flash或者card。它可以支持讀寫卡,但是代碼只放到內置的nor flash,而沒有放到外置的卡中。

          事實上51也可以像arm那樣引導操作系統的,當然操作系統不僅對內存有要求,對CPU計算能力也有要求,所以51是不能勝任跑linux的。但是51也能引導並跑簡單的操作系統的,例如UCOS等等,只要ram足夠大就可以。所以基於51的SOC系統也可以跑Linux那樣的系統,代碼是放在外置的nand flash或者card中,那啓動就要成爲一個獨立的模塊和U啓動COS、應用程序放在外置的nand中,上電的時候先通過irom來加載啓動的代碼到iram中,然後跑啓動代碼,並在啓動代碼中引導os。

TIPS

對於單片機的程序執行時codedata的存放與讀取,理解如下:對單片機編程後,程序的代碼段,data段,bss段,rodata段等都存放在Flash中。當單片機上電後,初始化彙編代碼將data段,bss段,複製到RAM中,並建立好堆棧,開始調用code段程序的main函數。以後,便有了程序存儲器,和數據存儲器之分,運行時從Flash(即指令存儲器,代碼存儲器)中讀取指令,從RAM中讀取與寫入數據。RAM存在的意義就在於速度更快。

(大型)ARM啓動流程

這裏只是ARM爲例做說明,其實是一類內存資源比較豐富的嵌入式系統啓動流程。以下將使用ARM + Linux的架構說明。

內存資源寬裕型操作系統一般都外掛SDRAM,並且CPU的計算能力都比較強,例如基於cortex A、MIPS 74k等核心的SOC。

  圖1,對於資源緊缺型系統,內置flash和ram。上電之前就已經通過燒寫工具將代碼寫到內置flash(nor flash),而iram用於data讀寫。

圖2是資源寬裕型系統,其代碼都放在外置存儲介質中,如nand,sd卡等,包括引導OS的啓動代碼、OS、根文件系統和用戶數據。上電後的運行過程是:

       1)irom中有第一階段的啓動代碼,一般稱爲boot loader 0(BL0),其作用是爲了引導nand flash中的啓動代碼到IRAM中,而nand flash中的啓動代碼是爲了引導OS代碼,稱爲BL1。BL0上電運行,這時SDRAM尚未初始化,所以其需要將BL1搬到IRAM中運行。BL0的代碼量比較小,主要是固化nand flash和card的讀驅動代碼,因爲其要支持不同的啓動介質。

            由於受成本約束,IRAM也不可能很大,那BL0搬BL1的大小一般是固定的,一定要小於IRAM大小;而引導OS的啓動代碼往往超過IRAM大小,所以引導OS的啓動代碼又再分爲兩部分,一般分是由BL0搬到IRAM,即BL1;剩下的一部分稱爲BL2。UBOOT就是這樣。

       2)BL0引導BL1到IRAM後,把控制權交給BL1。BL1初始化好SDRAM,接着將BL2搬到SDRAM。

       3)BL1將控制權交給BL2,BL2接着引導OS,最後把控制權交給OS。

 

事實上,爲了支持不同的啓動模式,如上電覆位,看門狗中斷,睡眠喚醒等等,在2)中,BL1會將自身BL1和BL2一起搬到SDRAM。可見BL1可能運行在IRAM中,也有可能運行在SDRAM中,一份代碼只有一個鏈接地址,怎麼可以在兩個不同的虛擬地址上運行呢?答案就是BL1一定是位置無關的,GCC編譯選項是-fPIC (Position-Independent Code)。

總結自微信公衆號嵌入式企鵝圈

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章