嵌入式IAP开发笔记之一:面向STM32的BootLoader程序
對于很多人來說,BootLoader并不是一個陌生的詞,甚至會經常用到它。因為在很多情況下我們都需要BootLoader程序,比如我們需要對系統在線升級時就需要它,還有當我們需要在外部存儲器中運行程序時也需要用到它。在這里我們就來設計一個應用于STM32系列MCU的BootLOader程序。
1、BootLoader的基本原理
既然我們想要實現一個面向STM32的BootLOader程序,那么首先我們必須來了解一下BootLOader程序的基本原理。
顧名思義,BootLOader程序肯定是要實現系統的引導,這是BootLOader程序的基本功能。對于STM32系列MCU來說,系統啟動后都會從內部Flash存儲器的起始地址開始執行程序。然后進入應用程序并按既定的順序執行下去,這時BootLoader與應用程序是一體的,具體如圖所示:
但有些時候,我們希望應用程序并不是直接運行,如我們希望對系統實現IAP的時候;或者我們希望應用程序并不在我們的內部Flash中運行;又或者應用程序雖然在內部Flash運行,但我們希望應用程序從我們指定的內部Flash地址運行等等。在這些時候我們就需要一個單獨的BootLoader程序。系統首先啟動BootLoader程序,系統準備就緒后進入到應用程序執行,具體如圖所示:
在上圖中,我們實際上將應用程序存儲在內部Flash的指定位置,這樣做當然是為了實現我們某種需求,如系統IAP。當然我們也可以讓應用程序存儲于外部Flash中,然后BootLoader程序跳轉到外部Flash去執行應用程序,不過前提是外部Flash內購執行程序。具體過程如下:
當然,這只是一種示例,對于不同的存儲器我們只需要修改地址就可以了。至于在BootLoader程序中要實現的功能就看使用情況了。原則上我們可以添加我們任意想要的功能,如硬件檢測、系統升級等等。
2、目標BootLoader設計
我們的目標是實現一個面向STM32的BootLoader程序。那么接下來我們就設計如何實現一個面向STM32的BootLoader程序。
2.1、Flash規劃
我們以STM32F407IGT6為目標MCU,這款MCU具有1M的Flash和192K的SRAM。我們將Flash劃分為2個部分,一個是啟動程序區(0x0800 0000 - 0x0800 3FFF )大小為16K Bytes,剩下的為應用程序區(0x0800 4000 - 0x080F FFFF)。具體分配如下圖:
我們讓BootLoader程序占用16K的存儲空間。但它是可以操作整個Flash存儲空間的。
2.2、BootLoader程序結構
我們來考慮一下BootLoader程序的結構問題。我們設計BootLoader程序的主要目的就是為了對應用程序進行升級。那么在BootLoader程序中主要需要實現哪些功能呢?有幾個方面是必須要包括的,一是基本的配置,如時鐘等,我們在主程序中實現;二是對Flash的操作,我們升級應用程序肯定會對Flash進行查處和寫入操作;三是跳轉控制程序,我們最終是需要去執行應用程序的,跳轉功能必不可少。當然根據不同的需求可能會有其它的需要。具體如下圖所示:
上圖中,我們除了簽署的三項基本實現外,還添加了IAP文件的獲取功能。這部分功能也是需要的,但在不同的模式下可能會有較大區別。因為獲取文件的方式可以是各類通訊如以太網口、串口等。也可以是各類存儲器,如SD卡、U盤等。所以這一功能雖然必不可少但實現方式則非常靈活,在后續實現中,我們具體問題具體分析。
3、目標BootLoader實現
我們已經確定了Flash的劃分,也基本明白了BootLoader的基本工作流程。在接下來我就來討論一下究竟怎么實現一個BootLoader程序。
3.1、BootLoader編碼
我們知道芯片上電時先運行BootLoader程序,然后跳轉到應用程序區執行應用程序。所以我們在編寫BootLoader程序時我們首先判斷系統是否有IAP的需求,如果有IAP請求則進入IAP模式,完成后再跳轉到應用程序執行,如果沒有IAP請求則直接跳轉到應用程序執行。具體流程如下:
關于IAP的處理在不同的情況下會有不同的處理方式,在這里我們主要看一看跳轉控制程序。首先定義應用程序的首地址并聲明一個函數指針類型。具體如下:
#define? ApplicationAddress? 0x08004000??? //應用程序首地址定義
typedef void (*pFunction)(void);??????? //定義跳轉函數指針類型
可能有人要問問什么定義這樣一個函數指針類型,因為我們最終是跳轉到Reset_Handler函數,所以必須要一個可以指向這個函數的函數指針。接下來我們就可以實現跳轉程序了。
/*跳轉到應用程序處理函數*/ static void JumpToApplication(void) {uint32_t StackAddr;?????????? //應用程序棧地址uint32_t ResetVector;???????? //應用程序中斷向量表的地址pFunction JumpToApp;????????? //定義跳轉函數指針__set_PRIMASK(1);??? //關閉全局中斷StackAddr = *(__IO uint32_t*)ApplicationAddress;????????????? //0x08004000;ResetVector = *(__IO uint32_t*)(ApplicationAddress + 4);????? //0x08004004;if((StackAddr&0x2FFC0000)==0x20000000)??????? //檢查棧頂地址是否合法.{__set_MSP(StackAddr);???? ??????????????????//初始化應用程序棧指針JumpToApp = (pFunction)ResetVector;???????????JumpToApp();} }3.2、應用程序處理
實現了BootLoader的編碼后,要想正確的跳轉到App運行,我們還需要對App作相應的修改。重要的修改有2處。如果應用程序是裸機程序則在配置時鐘前我們需要打開全局中端。
/*開啟全局中斷,在BootLoader中關閉的*/
? __set_PRIMASK(0);
同時,還需要修改中端向量表的偏移量地址。對于我們所使用的STM32F07可直接在system_stm32f4xx.c文件中修改就可以了。
#define VECT_TAB_OFFSET? 0x4000 /*!< Vector Table base offset field.
實現了上述修改并不能達到我們想要的目的,我們還需要在開發環境中做必要的修改。以我們使用的IAR EWARM V8.4為例。修改icf文件中對中斷向量表和Flash存儲區域的設定。具體如下圖:
完成上述配置后我們下載應用程序和BootLoader程序就可以實現正確的跳轉了。
4、小結
本篇中,我們只是實現了一個簡單的BootLoader程序。下載到目標MCU后實現了跳轉,應用程序也正常運行,說明我們的設計是正確的,后續可在次基礎上添加各種功能實現相應的IAP應用。
需要注意的是在BootLoader程序中我們關閉了全局中斷,在應用程序初始化系統時鐘之前一定要記得打開全局中斷,否則SystemTick不能工作會產生硬件故障(hardfault)。不過如果App是運行在RTOS上,則打開中斷可能會出錯,這一點需要注意。
歡迎關注:
總結
以上是生活随笔為你收集整理的嵌入式IAP开发笔记之一:面向STM32的BootLoader程序的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Modbus协议栈开发笔记之五:Modb
- 下一篇: WinSock I/O 模型 -- WS