Introduction
Application
基本的boot swap用例
不更新bootloader的情況
更新bootloader的情況
Conclusion
Introduction
客戶在開發(fā)量產型的ECU軟件時,大多會考慮實現OTA(在線更新)的功能,方便在將ECU設備裝車之后,可以利用通信過程更新固件。OTA的實現技術中,為了提升更新過程的安全性,避免在更新過程中因意外中斷導致整個ECU軟件系統崩潰,通常會考慮備份更新的方式,如果本次更新固件的過程被意外中斷,MCU仍可啟動至最近一次能夠正常運行的固件中,故而在MCU的片內flash中實際會存放至少兩份程序,A程序和B程序。
這兩份程序存放在不同的存儲區(qū),在創(chuàng)建這些application程序時,需要分別調整linker地址,讓A程序和B程序映射到指定對應不同的地址區(qū)才能正常運行。芯片在上電啟動后進入bootloader,經過信息安全檢查、完整性檢查、有效性檢查等一些列判定條件之后,有選擇地跳轉到存放在不同地址的application程序。而在更新程序的時候,也要分別更新不同區(qū)域的程序。
為了簡化開發(fā)者和用戶區(qū)分application程序的A / B版本,有些專用于ECU的MCU,設計了硬件支持flash存儲的AB面交換功能(boot swap),對應于兩塊獨立的但地址連續(xù)拼接的flash存儲器(pflash0和pflash1),可以通過軟件配置,指定哪塊flash存儲區(qū)被映射到0x0000_0000開始的位置。如此,將用于更新的固件application工程,其linker可以不做調整,始終為一份工程。在bootloader更新固件的過程中,將實際運行地址空間的程序,先寫到備份flash存儲區(qū)(例如flash的后半段)中,在更新成功完畢后,再執(zhí)行boot swap命令,將備份flash存儲區(qū)映射到實際運行的地址空間(例如,flash地址區(qū)間的前半段)。復位芯片后,就會從備份轉正的flash啟動,執(zhí)行新的application了。如此,兩個獨立的存儲區(qū)可互為備份。
Pricinple & Machenisim
以YTM32B1MD1微控制器為例,介紹boot swap的機制和用法。
YTM32B1MD1微控制片上集成了2片容量為256KB的flash,稱為pflash0和pflash1,總計512KB。默認情況下,pflash0被映射在0x0000_0000開始的地址空間,pflash1拼接在pflash0之后。當執(zhí)行了boot swap命令后,復位,pflash1的物理存儲被映射到0x0000_0000開始的地址空間,pflash0拼接在pflash1之后。
執(zhí)行boot swap命令的具體操作,就是向EFM模塊的CMD寄存器中,寫入boot swap的命令碼0x30。如圖x所示。
圖x boot swap的命令碼
而在,EFM模塊的STS寄存器中,可以通過查看BOOT_INFO標志位,判定當前0x0000_0000開始的區(qū)域映射到哪塊pflash上。如圖x所示。
圖x boot_info標志位
切記,只有當芯片復位之后,新的設置才能生效。通常開發(fā)者可以在軟件中,執(zhí)行boot swap命令后,再調用NVIC_SystemReset()函數復位生效。
當然,如果不適用boot swap機制,兩塊拼接在一起的pflash存儲器,也可以作為一個地址連續(xù)的大存儲器。仍然可以適配一些使用回滾策略或者使用復制方式實現的FOTA等機制。
Application
這里提供了一個可運行的用例,展示boot swap的用法。同時還討論了一些同boot swap功能相結合的bootlaoder方案的策略。
基本的boot swap用例
在展示boot swap基本用法的用例中,在main()函數中編寫用例,在同一份代碼中,查看BOOT_INFO標志位,然后打印出來,告知開發(fā)者當前的程序(總是從0x0000_0000開始)運行在哪塊pflash上。
在運行用例時,需要進行兩次下載:第一次下載程序,下載到從0x0000_0000開始的pflash0中,運行程序后,0x0000_0000地址切換到pflash1上,此時,還需要再下載一次程序,程序會覆蓋到pflash1上。注意,第一次下載程序后運行,從pflash1開始啟動,pflash1此時沒有可執(zhí)行的程序,可能會出現“卡死”的狀態(tài)。
/*main.c*/ #include"board_init.h" /* *Functions. */ intmain(void) { BOARD_Init(); printf("efm_swap_bool_flash. "); if(0u==(EFM_FLAG_BOOT_INFO&EFM_GetStatusFlags(BOARD_EFM_PORT))) { printf("bootfrompflash0. "); } else { printf("bootfrompflash1. "); } printf("pressanykeytolaunchtheEFM_SwapBootFlash()... "); uint8_tch=getchar(); putchar(ch);/*echotocheckinput.*/ /*switchthebootflash.*/ EFM_SwapBootFlash(BOARD_EFM_PORT); printf("EFM_SwapBootFlash()done. "); printf("NVIC_SystemReset() "); NVIC_SystemReset(); while(1) { } }
進行了兩次下載之后,pflash0和pflash1上都存放了相同的一份程序。但運行時,每個pflash的程序會查閱BOOT_INFO標志位,從而打印不同的信息。如此相互交替。如圖x所示。
圖x 運行efm_swap_boot_flash
不更新bootloader的情況
在支持A / B面的平臺上,設計bootloader + application的存儲結構。為了確保程序總是從bootloader開始執(zhí)行,實際上是在兩個pflash的開始位置存放了兩個相同的bootloader,對應跳轉到自己專屬的application。如圖x所示。如此,在一個pflash中執(zhí)行更新另一個pflash中的程序時,僅更新其中application的區(qū)域。在執(zhí)行boot swap和復位操作后,將會直接跳轉到相同的一份bootloader,并進一步跳轉到新的application,從而實現僅更新application的效果。
圖x 帶有bootloader的AB面存儲規(guī)劃
這里還討論了一種使用片上flash存放參數(模擬eeprom)的情形。當存放數據(以地址映射方式訪問)在pflash0上后,若執(zhí)行boot swap命令后,實際存放數據的內存區(qū)域,其地址映射發(fā)生了變化。但在程序中,若仍使用原來的地址訪問數據,則不會訪問到正確的存儲區(qū)。此時,如果仍想用一份固定的代碼,以“自適應”的方式訪問之前存放數據的區(qū)域,一種可行的方式,是借助于BOOT_INFO標志位進行判斷。
uint32_teep0_base_addr=(BOOT_INFO=1)?0x3C000:0x1C000; uint32_teep1_base_addr=(BOOT_INFO=0)?0x3C000:0x1C000;
更新bootloader的情況
如果進一步考慮更新bootloader的情況,就需要在更新策略上,在其中一個pflash中執(zhí)行更新另一個pflash程序的過程中,連帶這另一個pflash中的bootlaoder部分一起更新掉。如此,在執(zhí)行boot swap和復位操作后,將會直接跳轉到新的bootloader,從而實現更新bootloader的效果。
Conclusion
在有A / B分區(qū)的存儲平臺上,設計boot swap是為了實現備份程序和提升更新固件提供了便利。操作簡單,效果明顯。
-
mcu
+關注
關注
146文章
17148瀏覽量
351212 -
FlaSh
+關注
關注
10文章
1635瀏覽量
148031 -
存儲器
+關注
關注
38文章
7492瀏覽量
163842 -
ecu
+關注
關注
14文章
886瀏覽量
54504
原文標題:YTM32的flash存儲器boot-swap功能詳解
文章出處:【微信號:Ithingedu,微信公眾號:安芯教育科技】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論