一般 Bootloader 實現(xiàn)的邏輯如下:
這種方式適合于簡單的裸機程序或可控的 OS 程序(即所有外設硬件都可把控),在準備環(huán)境的時候將其全部關閉。
但對于一些復雜的或者 OS 中輪子已造好的程序,有一些因素不花時間研究無法把控,在準備環(huán)境時很可能就會遺漏一些未關閉導致出各種各樣的問題。
這里提供一種 萬能 方法:
- 利用芯片中的不受軟件復位影響的可供用戶使用的寄存器 (如 STM32 中的備份寄存器)。
- 在需要跳入 APP 運行時將該寄存器賦值然后軟件復位。
- 在 OS 還沒初始化時判斷該寄存器值,如果需要跳轉只需要簡單的準備環(huán)境即可跳轉。
該方法可以使 Bootloader 就作為一個 OS 應用程序開發(fā),需要跳轉的時候就操作一下寄存器并軟件復位即可。
該倉庫下所有的 Bootloader 例子均使用此方法。
以正點原子探索者開發(fā)板的 STM32F4 為例,將 system_stm32f4xx.c 文件的 SystemInit 函數(shù)修改:
void boot_start_application(void);
2void SystemInit(void)
3{
4 boot_start_application();
boot_start_application的實現(xiàn)為:
typedef void (*boot_app_func)(void);
2void boot_start_application(void) {
3 __HAL_RCC_PWR_CLK_ENABLE();
4 HAL_PWR_EnableBkUpAccess();
5 RTC_HandleTypeDef RTC_Handler = {0};
6 RTC_Handler.Instance = RTC;
7 uint32_t bkp_data = HAL_RTCEx_BKUPRead(&RTC_Handler, BOOT_BKP);
8 HAL_RTCEx_BKUPWrite(&RTC_Handler, BOOT_BKP, 0);
9 if (bkp_data != 0xA5A5) return;
10 boot_app_func app_func = NULL;
11 uint32_t app_addr = BOOT_APP_ADDR;
12 if (((*(__IO uint32_t *)(app_addr + 4)) & 0xff000000) != 0x08000000) return;
13 /* 棧頂?shù)刂吩?128K RAM 間 */
14 if (((*(__IO uint32_t *)app_addr) - 0x20000000) >= (STM32_SRAM_SIZE * 1024)) return;
15 app_func = (boot_app_func) * (__IO uint32_t *)(app_addr + 4);
16 /* Configure main stack */
17 __set_MSP(*(__IO uint32_t *)app_addr);
18 /* jump to application */
19 app_func();
20}
設置寄存器并軟件復位的實現(xiàn)為:
static void boot_app_enable(void) {
2 __disable_irq();
3 RTC_HandleTypeDef RTC_Handler = {0};
4 RTC_Handler.Instance = RTC;
5 HAL_RTCEx_BKUPWrite(&RTC_Handler, BOOT_BKP, 0xA5A5);
6 HAL_NVIC_SystemReset();
7}
-
寄存器
+關注
關注
31文章
5435瀏覽量
124606 -
bootloader
+關注
關注
2文章
239瀏覽量
46722 -
STM32F4
+關注
關注
3文章
203瀏覽量
29077 -
裸機
+關注
關注
0文章
40瀏覽量
6702
發(fā)布評論請先 登錄
自作萬能充電寶
電子萬能試驗機與液壓萬能試驗機的區(qū)別
怎樣去設計基于STM32的紅外萬能遙控器
如何去實現(xiàn)一種基于STM32的萬能紅外遙控器設計呢
萬能遙控器設置方法_萬能遙控器代碼

Bootloader 萬能實現(xiàn)邏輯

評論