說到這個地方,有幾個術語可能需要搞清楚:
BootROM, Bootloader各是什么東西:
BootROM是固化在SOC內部(在片內的一小塊norflash上,容量很小,只讀)的一段代碼,是芯片設計時候的一個重點環節
如果這塊代碼有問題,那芯片流片指定是廢了!一旦流片,無人能更改!
說了BootROM是什么之后,我們來思考一下,為什么需要BootROM?
先想一下,51單片機有bootrom嗎,沒有,51單片機上電立即從0x0000000的地方開始讀取代碼執行,本身代碼就在norflash上,CPU直接跳轉過去執行就行了。STM32有bootrom嗎,好像也沒有,理由和51一樣。那么為什么手機soc就有BootRom呢?因為一個重大的區別,手機的代碼量太大了,手機的固件動輒幾百MB,甚至幾個G, (新買的手機,光系統本身鏡像甚至就會占一個GB以上的內存),固件的size遠遠大於內部norflash的容量(這個norflash又小又貴),這就導致:
---->1.固件根本無法放到norflash中,norflash本身也是只讀的,根本無法燒寫
---------> 2. 固件一般是燒寫到SD卡,或者emmc,spiflash中
-------------> 3. 無法上電后直接被CPU取指令,他們是需要被搬運到DDR中才能被CPU取出來執行
----------------> 4. 需要先初始化DDR, 而不同廠家DDR的初始化代碼是不同的,也是需要代碼來做的
因此可以看到,3和4存在死鎖,如果初始化DDR的代碼在要搬運到DDR的鏡像中, 那么因為沒有地方能初始化DDR, 這就導致系統永遠也啟不來。這就是bootloader存在的意義。
bootloader和我們的系統鏡像是分開的,它是一小段短小精煉的代碼,可以由我們自由編輯,編譯,然后燒寫到flash中,或者sd中。更關鍵的是,借助bootloader, 我們就可以像發射火箭一樣,實現多級啟動
首先是第一級:bootrom, 上電后根據bootmode的pin選擇啟動方式,然后自動將spiflash/emmc/usb中的指定size的固件(bootloader的全部或者一部分)搬運到片內sram中(容量有限,所以bootloader可能無法全部加載到此處),然后跳轉執行
然后是第二級:bootloader 相對來說靈活性就很高了,比如在初始化DDR之后,可以先加載M0, M7的固件,然后再加載linux kernel. bootloader中還可以做一些安全相關的工作,比如設置內存某些區域的安全非安全讀寫屬性等
最后是第三級:kernel 加載好之后,進入linux的啟動環節
流程大致如下:
上面提到了第一步,上電的時候,soc會根據bootmode 選擇不同的啟動方式;比如某個引腳組合,就會從USB啟動,某個組合會從emmc啟動;如果選擇了USB啟動,這里就會涉及到另一個有趣的問題,那就是USB燒錄。當bootmode 選擇為從USB啟動后,bootrom 會嘗試從usb接收固件,也就是bootloader, 在我司的產品中,bootloader是lk. 其實這里就是一個usb文件傳輸的過程。
我們看一下燒錄腳本的細節:
.\bin\libusbex.exe .\bin\bootarea.img.eng.clr # 這是第一行,這里就是通過libusb將帶有fastboot 功能的lk (bootarea.img.eng.clr) 傳輸到設備中, 注意這個是非加密的版本,加密版本的lk名字是bootarea.img.pro.enc, 傳輸成功后,就可以在PC端用fastboot (host) 和 設備端的fastboot (device)通信了.
.\bin\fastboot.exe erase blackbox
.\bin\fastboot.exe flash normal .\image\normal.img
.\bin\fastboot.exe flash system .\image\system.img
.\bin\fastboot.exe reboot
也可以看到fastboot的主要作用就是燒錄,擦除分區,啟動等;fastboot 運行時是一個host段的fastboot 和 傳送到設備端的 lk里的fastboot交互的過程,也就是說是由host段先發起fastboot 命令,然后設備端進行響應的過程。而如果不從usb啟動,不執行我們的燒錄腳本,就不會走到fastboot里,也就是說正常啟動的lk , 是啟動了aboot來執行啟動的相關操作,而燒錄用的lk是啟動了fastboot 來執行燒錄相關的指令。
這里還涉及到加密的lk, 這個是干啥的呢,就是加密固件要用對應的加密的lk來加載,非加密要用非加密的lk來加載。