嵌入式項目實戰:單片機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元領取學習資源,讓你的學習之路更加順暢!記得點贊、關注、收藏、轉發哦!

點擊這里找小助理0元領取:

the end

評論(0)