嵌入式項目實戰:單片機STM32 Bootloader 快速實現(超詳細)
前言
嵌入式的設備,或多或少都需要對設備進行更新已適配更多的需求,如果未出貨的設備還可以使用下載線去下載,但是如果出貨之后到了客戶那里,客戶沒有下載線而且不是專業人員,無法對設備進行升級,這時候,bootLoader 的重要性就凸顯出來了,bootLoader 的設計就是為了設備能夠進行遠程升級或者只用指令升級,極大簡便了升級需要的步驟,做到傻瓜式升級,極大增強了產品的后續維護性。
下面我來介紹寫如何快速實現 STM32 BootLoader 的引導,幫助正在讀文章的您更快將此技術運用起來!
一、Bootloader 是什么?
Bootloader是在應用程序開始前運行的一個小程序,里面可以進行一些初始化操作,升級引用程序等,在嵌入式設備中很常見。
二、BootLoader 的實現
我這里做了一個簡單的 BootLoader 程序,只能進行引導,還沒有對升級進行編寫,升級是對約定好的應用程序的 Flash 進行擦+寫,比較常用的升級方式是通過 TFTP 的方式進行升級,您可以在 STM32官方的這個例程找到答案: 基于LwIP TCP/IP棧通過以太網進行STM32F4x7應用內編程(IAP)(AN3968)
2.1 生成 bin 文件
- 使用 Cube 生成出來后,打開工程的設置選項,填入如下命令
fromelf --bin -o ".\bin_file\@L.bin" "#L"
編譯之后,可以看到 bin_file 文件夾里面生成了 bin 文件,并可以知道其大小,我們根據其大小約定應用程序在 Flash 的起始位置
2.2 確認應用程序的起始位置
- 升級的過程被稱為 IAP(In Application Programming) ,每個芯片的 Flash 的扇區不同,我這里使用的是 STM32F767,上官網查看有關資料:STM32F76xxx and STM32F77xxx advanced Arm®-based 32-bit MCUs.pdf 里面有關于 Flash 扇區的地址信息:
- 在步驟2.1已經知道 BootLoader 的 bin文件大小是22 KB,我們可以根據上面的 Flash 扇區進行分配,我將應用程序的起始位置定在 扇區1,起始地址為 0x0800 8000
2.3 編寫引導程序
#include "stm32f7xx.h" typedef void (*pFunction)(void); /*!
* @brief 跳轉到應用程序段
* 執行條件:無
* @param[in1] : 用戶代碼起始地址.
*
* @retval: 無
*/ void jump_to_app(uint32_t app_addr) {
pFunction jump_to_application; uint32_t jump_address; /* Check if valid stack address (RAM address) then jump to user application */ if (((*(__IO uint32_t*)app_addr) & 0x2FFE0000 ) == 0x20000000)
{ /* Jump to user application */ jump_address = *(__IO uint32_t*) (app_addr + 4);
jump_to_application = (pFunction) jump_address; /* Initialize user application's Stack Pointer */ __set_MSP(*(__IO uint32_t*) jump_address);
jump_to_application();
}
} #define FLASH_JUMP_ADDR (0x08008000) int main(void) { /*
初始化程序省略.....
*/ if(((FLASH_JUMP_ADDR+4)&0xFF000000)==0x08000000) //Judge if start at 0X08XXXXXX. {
jump_to_app(FLASH_JUMP_ADDR); // Jump to APP } while(1)
{
}
}
三、App 的實現
3.1 修改 IROM1 的位置
根據約定好的 Flash 起始位置進行更改,上面步驟 2.2 已經確定好是 0x08008000
3.2 修改向量表
搜索宏定義 VECT_TAB_OFFSET,將 0x00 改為距離 0x08000000 的偏移量
/*!< Uncomment the following line if you need to relocate your vector Table in Internal SRAM. */ /* #define VECT_TAB_SRAM */ #define VECT_TAB_OFFSET 0x8000 /*!< Vector Table base offset field.
This value must be a multiple of 0x200. */
3.3 加入 App 循環打印提示
void StartDefaultTask(void const * argument)
{ /* USER CODE BEGIN StartDefaultTask */ segger_rtt_init("APP enter!"); /* Infinite loop */ for(;;)
{ print_log("You are in App now !!\n"); osDelay(1000);
} /* USER CODE END StartDefaultTask */ }
四、演示效果
- 確認燒錄過程是 Erase Sectors!
-
打開 RTT 窗口,連接 RTT 到 STM32 ,依次燒錄 BootLoader 和 App 的程序;
如何使用 JLink 實現 Segger log 可以按參考我之前的文章: 【嵌入式小技巧】stm32 實現 Segger RTT 打?。ǔ敿殻? - 燒錄完 App 程序之后,可以在 RTT窗口 看到正確引導到 App,成功!??!
總結
以上是使用 快速搭建 STM32 Bootloader 的引導程序,希望能夠幫助正在讀文章的您更快將此技術運用起來!
完整代碼可進群免費領取!??!
嵌入式物聯網的學習之路非常漫長,不少人因為學習路線不對或者學習內容不夠專業而錯失高薪offer。不過別擔心,我為大家整理了一份150多G的學習資源,基本上涵蓋了嵌入式物聯網學習的所有內容。點擊下方鏈接,0元領取學習資源,讓你的學習之路更加順暢!記得點贊、關注、收藏、轉發哦!
- 贊