嵌入式項(xiàng)目實(shí)戰(zhàn):?jiǎn)纹瑱C(jī)STM32 Bootloader 快速實(shí)現(xiàn)(超詳細(xì))

前言

嵌入式的設(shè)備,或多或少都需要對(duì)設(shè)備進(jìn)行更新已適配更多的需求,如果未出貨的設(shè)備還可以使用下載線去下載,但是如果出貨之后到了客戶(hù)那里,客戶(hù)沒(méi)有下載線而且不是專(zhuān)業(yè)人員,無(wú)法對(duì)設(shè)備進(jìn)行升級(jí),這時(shí)候,bootLoader 的重要性就凸顯出來(lái)了,bootLoader 的設(shè)計(jì)就是為了設(shè)備能夠進(jìn)行遠(yuǎn)程升級(jí)或者只用指令升級(jí),極大簡(jiǎn)便了升級(jí)需要的步驟,做到傻瓜式升級(jí),極大增強(qiáng)了產(chǎn)品的后續(xù)維護(hù)性。

下面我來(lái)介紹寫(xiě)如何快速實(shí)現(xiàn) STM32 BootLoader 的引導(dǎo),幫助正在讀文章的您更快將此技術(shù)運(yùn)用起來(lái)!

一、Bootloader 是什么?

Bootloader是在應(yīng)用程序開(kāi)始前運(yùn)行的一個(gè)小程序,里面可以進(jìn)行一些初始化操作,升級(jí)引用程序等,在嵌入式設(shè)備中很常見(jiàn)。

二、BootLoader 的實(shí)現(xiàn)

我這里做了一個(gè)簡(jiǎn)單的 BootLoader 程序,只能進(jìn)行引導(dǎo),還沒(méi)有對(duì)升級(jí)進(jìn)行編寫(xiě),升級(jí)是對(duì)約定好的應(yīng)用程序的 Flash 進(jìn)行擦+寫(xiě),比較常用的升級(jí)方式是通過(guò) TFTP 的方式進(jìn)行升級(jí),您可以在 STM32官方的這個(gè)例程找到答案: 基于LwIP TCP/IP棧通過(guò)以太網(wǎng)進(jìn)行STM32F4x7應(yīng)用內(nèi)編程(IAP)(AN3968)

2.1 生成 bin 文件

  • 使用 Cube 生成出來(lái)后,打開(kāi)工程的設(shè)置選項(xiàng),填入如下命令
fromelf --bin -o ".\bin_file\@L.bin" "#L"


編譯之后,可以看到 bin_file 文件夾里面生成了 bin 文件,并可以知道其大小,我們根據(jù)其大小約定應(yīng)用程序在 Flash 的起始位置

2.2 確認(rèn)應(yīng)用程序的起始位置

  • 升級(jí)的過(guò)程被稱(chēng)為 IAP(In Application Programming) ,每個(gè)芯片的 Flash 的扇區(qū)不同,我這里使用的是 STM32F767,上官網(wǎng)查看有關(guān)資料:STM32F76xxx and STM32F77xxx advanced Arm®-based 32-bit MCUs.pdf 里面有關(guān)于 Flash 扇區(qū)的地址信息:
  • 步驟2.1已經(jīng)知道 BootLoader 的 bin文件大小是22 KB,我們可以根據(jù)上面的 Flash 扇區(qū)進(jìn)行分配,我將應(yīng)用程序的起始位置定在 扇區(qū)1,起始地址為 0x0800 8000

2.3 編寫(xiě)引導(dǎo)程序

#include "stm32f7xx.h" typedef void (*pFunction)(void); /*!
* @brief 跳轉(zhuǎn)到應(yīng)用程序段
*        執(zhí)行條件:無(wú)
* @param[in1] : 用戶(hù)代碼起始地址.
*
* @retval: 無(wú)
*/ 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 的實(shí)現(xiàn)

3.1 修改 IROM1 的位置

根據(jù)約定好的 Flash 起始位置進(jìn)行更改,上面步驟 2.2 已經(jīng)確定好是 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 循環(huán)打印提示

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 */ }

四、演示效果

  • 確認(rèn)燒錄過(guò)程是 Erase Sectors


  • 打開(kāi) RTT 窗口,連接 RTT 到 STM32 ,依次燒錄 BootLoader 和 App 的程序;
    如何使用 JLink 實(shí)現(xiàn) Segger log 可以按參考我之前的文章: 【嵌入式小技巧】stm32 實(shí)現(xiàn) Segger RTT 打印(超詳細(xì))
  • 燒錄完 App 程序之后,可以在 RTT窗口 看到正確引導(dǎo)到 App成功!!!


總結(jié)

以上是使用 快速搭建 STM32 Bootloader 的引導(dǎo)程序,希望能夠幫助正在讀文章的您更快將此技術(shù)運(yùn)用起來(lái)!

完整代碼可進(jìn)群免費(fèi)領(lǐng)取!!!

嵌入式物聯(lián)網(wǎng)的學(xué)習(xí)之路非常漫長(zhǎng),不少人因?yàn)閷W(xué)習(xí)路線不對(duì)或者學(xué)習(xí)內(nèi)容不夠?qū)I(yè)而錯(cuò)失高薪offer。不過(guò)別擔(dān)心,我為大家整理了一份150多G的學(xué)習(xí)資源,基本上涵蓋了嵌入式物聯(lián)網(wǎng)學(xué)習(xí)的所有內(nèi)容。點(diǎn)擊下方鏈接,0元領(lǐng)取學(xué)習(xí)資源,讓你的學(xué)習(xí)之路更加順暢!記得點(diǎn)贊、關(guān)注、收藏、轉(zhuǎn)發(fā)哦!

點(diǎn)擊這里找小助理0元領(lǐng)取:

the end

評(píng)論(0)