前言:
在平常的項目開發(fā)和調(diào)試中,下載程序一般使用的是外部下載器或者串口的方式實現(xiàn)對單片機的程序下載和刷新,這種方法在項目的開發(fā)階段是常用的方式。
但是當項目開發(fā)完成推向市場的時候,很多時候需要對產(chǎn)品進行升級,而這個時候產(chǎn)品又已經(jīng)是加了外殼的或者被封裝起來了,一般也不會在外面預留出來下載接口之類的。
如果這個時候我想要更新產(chǎn)品的程序的話,可能就得要重新打開產(chǎn)品的外殼,然后通過下載器更新程序,更新完成之后再把外殼裝上,這種做法顯然是不太現(xiàn)實的。但是我們又必須要給產(chǎn)品進行升級,那該怎么辦呢?這個時候就可以考慮使用產(chǎn)品本身預留的一些外部通信接口(如:USB、RS232、ES485、以太網(wǎng)口等)或者內(nèi)部無線(如:wifi、藍牙、4/5G網(wǎng)絡)等對產(chǎn)品進行升級。
上面介紹的這種通過外部有線接口或者無線通信的方式進行的更新其實是一種在線更新的方式,即OTA升級技術。
那問題來了,到底什么是OTA升級技術呢?待我慢慢道來!
1、OTA 在線升級
OTA:Over-the-Air Technology,字面意思理解:空中下載技術。
OTA 在線升級:通過OTA的方式實現(xiàn)產(chǎn)品軟件更新的一種方式。
所以,簡單而言,通過外部的方式(有線 / 無線)對產(chǎn)品進行更新,而不是用傳統(tǒng)的編程器刷入固件的方式就可以稱之為 OTA 在線升級。
嚴格意義上來講,OTA 指的是空中下載,即只有通過無線的方式進行更新的才稱之為 OTA 升級;而那種通過外部的接口接線來實現(xiàn)的更新,應該稱之為本地升級。這兩者還是有點區(qū)別的,只是一般我們都沒有那么嚴格去區(qū)分罷了!
2、實現(xiàn)方式
那既然理解了升級的概念了,該怎么去實現(xiàn)呢?
我們一般的做法是會將這個升級功能進行劃分,分為兩部分:
1) 接收新的升級固件并完成新舊固件的替換,這部分代碼為 BootLoader;
2) 產(chǎn)品功能的正常程序,用于執(zhí)行各種應用功能,這部分程序稱為 App。
那就是說,要實現(xiàn)在線升級,就需要準備兩份程序,一份是BootLoader ,另一份是App。其中 bootloader 用于將外部傳入的新固件(應用程序App)接收到內(nèi)部并存儲,接收完成以后,由 bootloader 用新接收到的固件去替換舊的固件,替換完成之后跳轉到新的應用程序中進行執(zhí)行。這樣就完成了產(chǎn)品的固件更新。
注意:需要將 bootloader 和應用程序App的空間分開,兩者是不能發(fā)生重疊的。
3、操作方式
3.1、后臺式升級
后臺式升級的意思是:在進行升級的時候,接收新固件包的方式是在后臺進行的,不會影響功能的正常執(zhí)行。等到固件更新完成之后,再跳轉到Bootloader中去用新的固件替換舊的固件,替換完成之后呢再跳轉到App去執(zhí)行。
比如,現(xiàn)在的智能手機的在線更新就是后臺式升級的方式。在你升級系統(tǒng)的時候,接收升級包的過程中,你還是可以正常使用的手機的,打電話、看視頻、玩游戲等都不耽誤,直到下載完成,你點擊了開始更新之后,手機才進入更新狀態(tài),不讓你操作,等更新完畢之后重啟就又可以繼續(xù)操作了。
3.2、非后臺式式更新
非后臺式升級的意思是:在進行升級的時候,接收固件時需要跳轉到Bootloader,這個時候你不能在使用這個產(chǎn)品的任何功能,只能一直等著它接收并完成更新,完成之后你才能繼續(xù)操作其他的功能。
4、STM32 的在線升級
本文以STM32為例展開講解怎么實現(xiàn)OTA升級和操作的方法。
4.1、劃分 Flash 區(qū)域
按照前面講述的有關在線升級的原理,我們知道是要準備兩份代碼的,一份是BootLoader,另外一份是App。由于這兩份代碼在STM32中都是要存放在Flash中的,而且它們的空間還不能重疊,要獨立區(qū)分開。
所以,按照這個原則,我們可以考慮在Flash中分三個區(qū)域出來,如下圖所示:
上圖中的三塊Flash分別用于:
(1)用于存放Bootloader程序;
(2)用于存放應用程序;
(3)用于存放接收到的新固件。(注:這部分可要可不要,根據(jù)你的設計選擇)
注意:上圖中(3)這個Flash區(qū)域是考慮用于保存在線升級的固件的,作為備份固件。方便用于以后系統(tǒng)出現(xiàn)異常時,可以從這個備份固件中重新加載到App中,防止固件丟失!
4.2、實操1 - Flash空間地址的劃分
首先,我們要知道,在stm32中,flash的地址空間是從0x08000000開始的,在keil中也是默認的從這個位置開始的。
一般而言,Bootloader 是在上電時默認開始執(zhí)行,因此將Bootloader程序可以存放到STM32默認執(zhí)行的位置(keil編譯器默認從0x08000000地址開始存放)。
應用程序從 Bootloader 后開始存放即可,只要不和BootLoader發(fā)生沖突即可。
假設 Bootloader 的大小為10k,即0x2800字節(jié),那么可以選取 0x08000000 ~ 0x08002800 地址范圍作為BootLoader的存放區(qū)域。
應用程序從0x08005000開始存放(至于選多大的范圍,要根據(jù)你的應用程序大小進行考慮,建議保留一些余量)。
劃分如下圖所示:
4.3、實操2 - 設置工程
(1)設置起始地址和大小
準備兩個工程,一個是bootloader的程序,另外一個是應用程序的工程,并對工程進行設置。bootloader選擇默認執(zhí)行的位置,應用程序根據(jù)實際需要設置開始存放到flash指定的位置。
比如:App的起始地址設為0x08005000,大小設為0x1B000(RAM總大小0x20000-0x5000)。設置如下圖:
BootLoader 也是一樣的設置方式,只是地址不同而已。
(2)生成 bin 文件
另外需要注意的,應用程序需要轉換為bin文件才可以寫入Flash中,能發(fā)送到產(chǎn)品中的固件也是要先轉為bin格式的文件的。
編譯器可以選擇生成hex文件,再把hex文件轉換為bin文件。還可以使用簡單方法,MDK-Keil中點開User選項卡,設置如下圖:
即在編譯后直接執(zhí)行fromelf.exe命令將.axf文件轉換為.bin文件。生成的bin文件在工程目錄下的out文件夾下。
4.4、實操3 - 接收固件更新包
接收固件更新包的話,就要根據(jù)你的實際產(chǎn)品進行選擇了。
首先,如果你是后臺式更新的話,那接收固件更新包的功能就要在App中實現(xiàn);如果你是非后臺式更新的話,那接收固件更新包的功能就要在BootLoader中實現(xiàn)。
其次,要考慮接收固件更新包的方式。無線的話用的是wifi、藍牙、4/5G網(wǎng)絡還是啥的;有線的話用的是串口UART、Spi、IIC、CAN、以太網(wǎng)還是啥的。
最后,最好的方式是能夠對接收到的固件更新包做一個校驗,防止數(shù)據(jù)接收過程中出現(xiàn)錯誤,導致升級后出現(xiàn)嚴重問題。
注意:BootLoader 需要提前刷入,不然無法完成在線升級!
4.5、實操4 - 拷貝程序至Flash
接收成功固件包之后,需要將數(shù)據(jù)寫入到 Flash 的指定位置(比如 0x08005000)完成固件的更新程序寫入。
STM32對Flash的操作過程如下:
1) Flash解鎖。(FlashUnclock)
2) 擦除App所在的Flash頁。
3) 向App的Flash區(qū)域寫入數(shù)據(jù)。
4) 寫完后,F(xiàn)lash上鎖。(FlashClock)
4.6、實操5 - 跳轉至 App 應用程序
將接收到應用程序全部正確寫入Flash的App指定位置后,Bootloader 需要完成跳轉到應用程序App的開始位置的操作。
跳轉過程如下:
1)關閉中斷,防止在跳轉過程中有中斷發(fā)生。
2)獲取棧指針。
3)獲取復位向量,即為棧指針后的四字節(jié)內(nèi)容(32bits)。
4)重定向中斷向量表,以保證應用程序中中斷的正常工作。應用程序從0x08005000存儲,因此相對于Flash基地址0x08000000偏移了0x5000。
5)設置新的棧指針,上述中所獲取的棧指針。
6)跳轉至復位向量開始運行。
4.7、特別注意 - 設置向量中斷表偏移
這個跳轉到應用程序之后,有一個非常重要的事情要注意,就是要重新設置App的中斷向量表,否則不能正常運行的。
首先要理解STM32的正常運行是怎么樣的,如下圖所示:
STM32的內(nèi)部閃存(FLASH)的地址默認是從0x8000000開始的,默認也是從這個位置開始執(zhí)行程序的。并且在STM32的內(nèi)部有一張 “中斷向量表” 用于響應中斷,程序在啟動以后首先會從中斷向量表取出復位中斷程序,執(zhí)行完復位中斷程序以后才會跳轉到main( )函數(shù)開始執(zhí)行。
中斷向量表的位置從0x8000004開始,如果采用的是bootloader和應用程序的方式的話,bootloader一般放在默認開始的位置,所以它的中斷向量表還是正確的。
而APP應用程序是放置在其他的位置,那么APP應用程序部分的中斷向量表就要發(fā)生偏移,才能為應用程序找到并響應中斷。
在應用程序中,與程序跳轉需要注意的是,單片機從Bootloader程序跳轉至應用程序的復位向量處開始執(zhí)行,單片機在執(zhí)行main函數(shù)之前會執(zhí)行一些系統(tǒng)初始化程序。在系統(tǒng)初始化函數(shù)void SystemInit (void);在該函數(shù)中有對中斷向量表的設置,如下:
在上圖中VECT_TAB_OFFSET默認為0x0,而應用程序的中斷向量表需要定位到0x08005000,因此這里需要將VECT_TAB_OFFSET值修改為0x5000。(這里可能跟跳轉程序中的設置中斷向量表的過程重復,所以需要慎重考慮)。
如下:
/* Configure the Vector Table location add offset address -配置中斷向量表的起始地址-*/
#ifdef VECT_TAB_SRAM //默認沒有定義
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
#else
SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
#endif
修改這個偏移:
#define VECT_TAB_OFFSET 0x5000 /*向量表基本偏移量字段。此值必須是0x200的倍數(shù) */
注意:這個中斷向量表的偏移一定要在初始化階段去完成!
到此,在線升級的原理和STM32的操作已經(jīng)講完,如果有講的不正確的地方,還請指正!
評論
查看更多