1、概述
在嵌入式操作系統中,BootLoader是在操作系統內核運行之前運行的一段代碼。
他的作用就是為操作系統內核準備好運行環境,比如初始化必要的設備硬件,建立內存映射圖等。
bootloader不一定只有一個,有些操作系統有兩級的bootloader,第一級bootloader和第二級bootloader分別完成不同的功能。
二級bootloader功能如下:
1)提供OTA升級運行環境
OTA的差分及壓縮升級功能,需要一個與OS及APP隔離的運行環境,用於差分恢復運行區版本。該運行環境可以在一級bootloader中實現,但是一級bootloader通常是芯片或者模組廠商提供,而且很多芯片及模組廠商未提供bootloader的源碼,無法保證可以在所有的一級bootlaoder中實現。
2)充分利用內存空間
在二級bootloader運行時,OS還未啟動,二級bootloader可以使用全部的內存空間,用於差分解壓算法等比較耗內存的操作。OS啟動後,將整個系統內存重新初始化,也可以使用全部內存空間,二級bootloader使用了多少內存對OS無影響。這樣可以達到內存的充分利用。
3)版本自動回滾
可以提供版本回滾功能,版本升級後,如果啟動失敗,可以通過二級bootloader自動回滾到升級前可正常運行的版本。
4)設備本地升級。
可以支持設備在不直接聯網的場景下,通過本地升級功能,作為子設備升級。
2、二級bootloader總體框架
2.1、物理部署
如上圖所示,二級bootloader介於一級bootloader與OS之間,與一級bootloader及OS共用FLASH空間,運行時獨享系統RAM空間。
2.2、二級bootloader對外功能
1)UART驅動、FLASH驅動級Watchdog驅動,需要獨立運行,不能對一級bootloader及OS產生符號依賴。可以對一級bootloader有功能依賴,不能對OS有功能依賴。
2)FLASH分區表中二級boot相關的配置需要與OS的FLASH分區表二級boot相關的配置完全一致。
3、二級bootloader詳細設計方案
3.1、二級bootloader啟動流程
3.1.1、二級bootloader加載啟動
對於一級bootloader來說,二級bootloader與OS一樣,是一個被引導啟動的application,因此二級bootloader編譯及啟動方式與OS基本相同。
由於每個MCU,bootloader啟動OS的方式不一樣,因此二級bootloader被一級bootloader引導啟動的方式也不盡相同。目前AliOS Things支持的MCU,通常有下面幾種啟動引導方式:
1)一級bootloader從固定地址跳轉到二級bootloader的入口執行。目前,mk3060及developerkit等採用的這種方式。
2)一級bootloader從固定地址讀取二級bootloader的入口函數地址,再跳轉到二級bootloader入口執行。目前,mk3080採用的是這種啟動方式。
3)有多個固定的FLASH啟動地址,一級bootloader根據FLASH中的固定參數,決定從哪個FLASH地址啟動。developerkit等STM32系列的MCU均是該方式啟動。
注:mk3080的一級bootloader實際也有選擇啟動地址的過程,選擇完後,再按照步驟2啟動。
下面詳述一下一級bootloader加載啟動二級bootloader的流程。
二級bootloader加載啟動流程
二級bootloader加載啟動流程2
FLASH排列規則如下:
注:部分MCU是一級bootloader實現,一級bootloader會將二級bootloader的data段數據拷貝到RAM中。目前mk3060,是二級bootloader自己拷貝的data段數據;mk3080是一級bootloader加載二級bootloader前完成。
該流程,由一級bootloader完成,二級bootloader本身不需要操作,只需要按照MCU要求OS的編譯鏈接方式生成bin文件即可。
3.1.2、二級bootloader內存初始化
將data段數據拷貝到RAM中對應地址
該操作,需要在FLASH中找到data段的起始地址和結束地址,以及在RAM中的起始地址和結束地址,然後將FLASH中的data數據拷貝到RAM中。
對於大部分CPU,data段的起始和結束地址,定義在鏈接腳本中,代碼通過extern變量方式獲取。少量MCU,如mk3080,需要按照特殊方式獲取(3080的特殊方式,可以參加3080二級bootloader加載啟動流程章節)。
bss段數據清0
該操作需要在RAM中找到bss段的起始地址和結束地址,然後將RAM中對應地址的數據清0。
所有的MCU,bss段的起始和結束地址,都可以直接定義在鏈接腳本中,代碼通過extern變量方式獲取。
動態內存管理
二級bootloader在運行OTA差分功能時,需要使用動態內存申請及釋放功能。因此要求二級bootloader中支持動態內存管理。
二級bootloader中,使用的動態內存範圍在二級bootloader的鏈接腳本中定義,從二級bootloader的bss段結束,到recovery棧空間開始的範圍。內存管理使用與OS相同的動態內存管理算法。
3.2、二級bootloader引導啟動OS流程
3.2.1、OS啟動流程
二級bootloader引導啟動OS的流程,基本與一級bootloader引導啟動二級bootloader的流程相同。基本也分2種方式:固定地址跳轉和從固定地址讀取入口函數地址跳轉,詳見二級bootloader啟動流程種的描述。
下面以mk3060和mk3080為列,詳述一下二級bootloader加載啟動OS的流程。
二級bootloader加載啟動OS流程
注意:FLASH燒寫,需要4K對齊,因此需要從0x1C000開始燒寫。而OS的起始FLASH地址需要從0x1C01C開始,因此需要在OS的bin文件頭部補充0x1C byte的填充數據。
二級bootloader加載啟動OS流程
FLASH排列規則如下:
3.2.2、中斷向量表
二級bootloader本身不處理中斷,全程禁止中斷運行(串口中斷除外),但是在OS啟動後,需要將中斷送給OS。目前有幾種實現方式,如下:
採用逐級中斷向量表跳轉方式,硬件產生中斷後,先進入一級bootloader,一級bootloader轉給二級bootloader,二級bootloader轉給OS。
OS啟動後,直接將中斷註冊給MCU SDK提供的中斷機制。
硬件觸發中斷後,直接調用中斷處理回調函數。
直接修改中斷向量表入口地址
OS啟動後,設置MCU硬件寄存器,將中斷向量表地址設置為OS內部中斷向量表地址。硬件產生中斷後,直接進入OS的中斷向量表。developerkit目前採用的這種方式。
3.3、二級bootloader運行流程
3.3.1、運行流程
說明:1)在recovery中,也會初始化串口。
2)一旦進入recovery流程,不能再返回啟動OS的流程,需要重啟後再進入。
3)一旦進入命令行模式,不能再返回啟動OS的流程,需要重啟後進入。
4)部分MCU,OS的啟動入口地址是寫死的,不需要動態獲取。
3.4、命令行功能
命令行功能,運行開發者通過串口輸入命令方式,查詢版本信息、進行本地升級等操作。
3.4.1、進入流程
在判斷是否需要進入命令行模式時,會持續讀串口100ms,如果讀到字符'w',就會進入命令行模式。
進入後,會打印二級bootloader版本號,以及命令提示信息。然後等待用戶進一步輸入串口命令。
3.4.2、支持命令
1)打印運行區版本號及備份區版本號。
2)Xmodem讀寫flash
3)Ymodem讀寫flash
4)USB升級
5)Canbus升級
6)版本回退到備區
7)reboot
說明,上面命令,支持配置項配置,通過配置項決定是否支持對應功能。
3.5、異常處理
二級bootloader中發生異常時,直接reset。
4、現有系統影響分析
4.1、FLASH空間
4.1.1、FLASH空間消耗增多
增加二級bootloader功能後,相對於沒有實現二級bootloader以及差分升級的設備,會增加36k的FLASH消耗。對於已經實現差分升級的設備,會增加16k的FLASH消耗。
增加的FLASH消耗主要是由下面幾方面導致:
1)增加了二級bootloader的處理邏輯,代碼需要消耗FLASH空間。
2)增加了命令行處理功能,相關代碼需要消耗FLASH空間。
3)增加雙備份及回滾功能,相關代碼需要消耗FLASH空間。
4)增加了任意時刻斷點續傳功能,增加了8K的備份數據區。
4.1.2、FLASH空間規劃發生變化
增加二級boot及差分功能後,會導致FLASH空間規劃發生變化。原因如下:
1)二級bootloader在FLASH中的位置,需要位於一級bootloader之後,OS之前。
2)增加了一個8K備份區,用於備份二級bootloader及差分參數,一級備份斷點續傳數據。
4.2、版本燒寫方式
4.2.1、當前燒寫方式
當前燒寫方式歸納一下,存在下面2種燒寫方式:
OS的bin文件單獨燒寫。
OS與bootloader的bin作為一個文件一起燒寫。
4.2.2、增加二級bootloader後燒寫方式
增加二級bootloader後,有下面3種方式:
可行方案:
1)對於一級bootloader可以燒寫的設備
將二級bootloader與一級bootloader合併成一個bin文件,單獨燒寫。OS的bin文件單獨燒寫。
2)對於一級bootloader不可以燒寫(或者不需要燒寫)的設備
將二級bootloader單獨燒寫。OS的bin文件單獨燒寫。
4.3、啟動時間
由於需要支持命令行模式,在每次啟動時,會有100ms的等待按鍵輸入的時間。導致每次啟動會慢100ms。
5、移植說明
5.1、概述
二級bootloader實現,依賴UART驅動、FLASH驅動、WatchDog驅動,需要能夠被一級bootloader啟動,需要能夠加載啟動OS的bin。
5.2、啟動引導
啟動引導,需要實現下列功能:
1)能夠被一級bootloader引導啟動
2)能夠找到OS的data段在flash中的位置,以及在RAM中的位置,啟動OS前,將data段拷貝到RAM中。
2)能夠找到OS的入口地址,啟動OS。
3)能夠將中斷和異常轉給OS。
5.3、UART驅動移植
UART驅動,需要提供下列功能:
5.4、FLASH驅動移植
FLASH驅動,需要提供下列功能:
5.5、WatchDog驅動移植
WatchDog驅動,需要提供下列內容:
5.6、內存管理
內存管理,主要需要提供動態管理內存的起始地址和結束地址,方式如下:
5.7、復位及延時
需提供如下接口: