OTA(空中下載技術(shù))是通過移動通信的空中接口實現(xiàn)對移動終端設(shè)備進行遠(yuǎn)程管理和升級的技術(shù)。我們調(diào)試硬件設(shè)備的時候通常是通過數(shù)據(jù)線進行固件的燒錄,如果是在辦公室的環(huán)境下這種方式是很方便的,但是如果設(shè)備距離較遠(yuǎn),有線的方式就有很大的局限性。因此,遠(yuǎn)程升級技術(shù)就顯得很重要了。
RT-thread有一套OTA的方案可以參考,今天主要就介紹這套方案的使用以及優(yōu)缺點。
RT-thread官方介紹:
Bootloader:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/system/rtboot/an0028-rtboot
OTA Downloader:http://packages.rt-thread.org/detail.html?package=ota_downloader
特別說明:本教程的配置如下:
配置 | 說明 |
---|---|
MCU | STM32F429VET6 |
FLASH | W25Q32 |
RT-thread源碼版本 | v4.0.3 |
一、OTA升級原理介紹
OTA升級的固件必須要有一個存儲設(shè)備來存放,如果固件比較小,可以存放在MCU內(nèi)部FLASH(未使用的區(qū)域),如果固件較大則需要掛載一個外置的FLASH。
要進行OTA升級,我們需要使用Bootloader,它的主要功能是作為引導(dǎo)程序,更新app分區(qū)中的固件或者跳轉(zhuǎn)到app應(yīng)用程序。
Bootloader作為一個引導(dǎo)程序,我們自己編寫的代碼作為一個應(yīng)用程序,把兩個固件都燒錄到MCU里面(固件存放的位置不同)之后,MCU啟動時會先運行Bootloader,檢查片外flash是否有可升級的固件,如果有則升級固件,如果沒有則跳轉(zhuǎn)到應(yīng)用程序運行的起始地址,然后正常的運行我們的應(yīng)用程序。
具體流程如下:
1.Bootloader啟動時檢查download分區(qū)和app分區(qū)中的固件版本。
2.如果兩個固件版本相同,則跳轉(zhuǎn)到app分區(qū),Bootloader運行結(jié)束。
3.固件版本不同則將download分區(qū)中的固件搬運到app分區(qū)。
4.在搬運的過程中Bootloader可以對固件進行校驗、解密、解壓縮等操作。
5.搬運完畢后,刪除download分區(qū)中存儲的固件。
6.重啟系統(tǒng)跳轉(zhuǎn)到app分區(qū)中的固件運行,Bootloader運行結(jié)束。
二、生成Bootloader
我這邊主要介紹的是RT-Thread開發(fā)團隊提供的通用Bootloader。
Bootloader的功能前面也有介紹了,它作為一個引導(dǎo)程序,更新app分區(qū)中的固件或者跳轉(zhuǎn)到app應(yīng)用程序。
Bootloader可以通過網(wǎng)頁端在線生成的方式來獲取。開發(fā)者根據(jù)自己使用的芯片,填寫相關(guān)參數(shù),然后點擊生成按鈕,即可在線生成Bootloader。
Bootloader在線獲取地址: http://iot.rt-thread.com
關(guān)于Bootloader的使用在RT-Thread官網(wǎng)有非常詳細(xì)的教程,我覺得就沒有更詳細(xì)的教程了,這里就沒必要再抄一遍了,你們可以直接看官網(wǎng)的教程,我只說一下這里面的一些重點。
Bootloader:https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/application-note/system/rtboot/an0028-rtboot
提示:
1:串口輸出引腳、FLASH引腳和恢復(fù)出廠引腳的引腳號要根據(jù)自己的情況填寫,串口輸出建議使用,通過輸出的log可以清楚看到設(shè)備運行的情況,也便于查找問題。
2:FLASH引腳一定要對好,不然是不能正常加載片外flash的。
3:恢復(fù)出廠要在flash單獨分一個區(qū)域用來存放固件,根據(jù)自己是情況選擇要不要使用按鍵恢復(fù)。
4:分區(qū)表配置要和你實際的分區(qū)保持一致。
5:Bootloader固定為128k,因此MCU片內(nèi)FLASH的0x08000000-0x0801FFFF是用來存放bootloader的,app要從0x08020000開始。
下圖僅供參考,不是實際使用的配置。
我實際使用的配置如下:
硬件配置:
說明 | 配置 |
---|---|
芯片 | stm32f4 |
ROM | 512k |
RAM | 192k |
串口輸出 | PA9 |
SPI Flash | CS:PA4, CLK:PA5, MISO:PA6, MOSI:PA7 |
按鍵引腳 | PE7 低電平有效 |
分區(qū)表配置:
分區(qū)名 | 所處設(shè)備 | 偏移地址 | 大小 |
---|---|---|---|
app | 片內(nèi)Flash | 0x20000 | 384k |
download | 片外Flash | 0x00000 | 256k |
factory | 片外Flash | 0x40000 | 384k |
加密壓縮:
說明 | 配置 |
---|---|
固件加密 | 不使用 |
固件壓縮 | gzip |
logo和郵箱:
說明 | 配置 |
---|---|
logo | 無 |
郵箱 | 自己使用的郵箱 |
配置好參數(shù)之后直接生成bootloader即可。
三、制作app固件
1、掛載FLASH
首先我們要把這個片外flash掛載上。這個我之前的教程已經(jīng)介紹過了,不知道的同學(xué)可以先看下我之前的博客:RT-thread應(yīng)用講解——norflash
2、配置分區(qū)
我們在實際的應(yīng)用中片外flash可能會同時使用多個功能,比如OTA,easyflash、文件系統(tǒng)等,這個時候為了避免數(shù)據(jù)沖突,我們就要先把flash分成幾個區(qū)域。
關(guān)于FLASH分區(qū)的內(nèi)容,請參考我另外一篇博客:RT-thread應(yīng)用講解——FLASH分區(qū)
我這里的分區(qū)具體如下:
分區(qū)名 | FLASH設(shè)備名 | 偏移地址 | 內(nèi)存大小 | 說明 |
---|---|---|---|---|
“bootload” | “onchip_flash_16k” | 0 | 128 * 1024 字節(jié) | bootload引導(dǎo)程序 |
“app” | “onchip_flash_128k” | 0 | 384 * 1024 字節(jié) | 應(yīng)用程序 |
“download” | “norflash0” | 0 | 256 * 1024 字節(jié) | OTA升級固件 |
“factory” | “norflash0” | 256 * 1024 | 384 * 1024 字節(jié) | 恢復(fù)出廠固件 |
“cmb_log” | “norflash0” | 640 * 1024 | 128 * 1024 字節(jié) | 運行日志 |
“filesystem” | “norflash0” | 896 * 1024 | 15488 * 1024 字節(jié) | 文件系統(tǒng) |
提示:實際上本教程的片外flash只使用了download分區(qū),你們可以根據(jù)自己的情況分區(qū)。
3、下載ota_downloader軟件包
1)打開ota_downloader軟件包。
2)根據(jù)自己的情況選擇升級的方式。
提示:我這里沒有連接網(wǎng)絡(luò),所以只選擇串口升級。想通過網(wǎng)絡(luò)升級的話要先把網(wǎng)絡(luò)模塊和webclient調(diào)試好,能正常使用http的話就可以打開這個配置使用網(wǎng)絡(luò)升級。
3)保存配置,更新軟件并重新生成新的工程。
這個應(yīng)該不用我多說了吧,會用env的同學(xué)應(yīng)該都清楚,不清楚的可以翻下我之前的博客,很多教程都有講到。
4、修改app固件配置
1)修改固件的鏈接地址
stm32f429在運行的時候是先從0x08000000地址開始的,前128k我們是用來存放bootloader的,app是從0x08020000開始運行的,所以我們要把固件的鏈接地址修改為0x08020000。
提示:地址根據(jù)自己的實際情況配置。
2)修改中斷向量表的跳轉(zhuǎn)基地址
在工程里面添加下面這段代碼,作用是重新設(shè)定中斷向量跳轉(zhuǎn)地址為 app 分區(qū)的地址。
示例代碼:
/**
* Function ota_app_vtor_reconfig
* Description Set Vector Table base location to the start addr of app(RT_APP_PART_ADDR).
*/
static int ota_app_vtor_reconfig(void)
{
#define RT_APP_PART_ADDR 0x8020000 // app運行的起始地址,根據(jù)自己的實際情況定義
#define NVIC_VTOR_MASK 0x3FFFFF80
/* Set the Vector Table base location by user application firmware definition */
SCB->VTOR = RT_APP_PART_ADDR & NVIC_VTOR_MASK;
return 0;
}
INIT_BOARD_EXPORT(ota_app_vtor_reconfig);
3)添加版本信息
為了方便查看設(shè)備運行的版本,最好在啟動的時候打印設(shè)備的版本號。
我這里直接在main函數(shù)里面寫了。
示例如下:
四、燒錄固件
固件燒錄分成兩部分,bootloader和app。燒錄可以通過ST-Link也可以通過J-Link,具體的燒錄方法這里就不說了,只需要注意燒錄的地址即可。
參考示例:
bootloader固件燒錄地址為0x08000000。
app固件燒錄地址為0x08020000。
提示:app可以直接通過keil uvision燒錄。
兩個固件都燒錄完成之后硬件重啟即可。
五、運行測試
正常運行的日志如下:
先運行bootloader再跳轉(zhuǎn)到app應(yīng)用。
六、升級測試
1、打包要升級的固件
我們先把要升級的程序調(diào)試好,確保程序沒問題,然后通過打包工具打包。
參考示例:
我這里先改一個v1.1.0版本的固件,編譯。
然后在工程目錄下ota的軟件包里面找到打包工具并運行。
注意:工具所在的路徑不能有中文。
打開打包工具,選擇自己要更新的固件,根據(jù)自己的情況修改配置,打包。
打包后的升級固件為rbl格式。
2、升級測試
使用Ymodem協(xié)議升級固件時,推薦使用Xshell終端。
在msh命令行中輸入ymodem_ota命令后,點擊鼠標(biāo)右鍵,然后在菜單欄找到用YMODEM發(fā)送選項發(fā)送文件,如下圖所示:
1.選擇Ymodem方式發(fā)送升級固件。
七、注意事項
1:分區(qū)要合理。
分區(qū)大小和app固件大小有直接關(guān)系,比如我用的這款芯片ROM是512k,前128k用來存放bootloader,那就只剩384k了,所以我后面編寫的app固件大?。╞in文件)不能超過384k。如果你用的不是片外flash而是MCU的片內(nèi)flash的話,那你的分區(qū)就更加要注意了,因為除了app區(qū)還有download分區(qū),要保證兩個固件都不超過分區(qū)的大小。
2:升級固件的bin文件大小要比app分區(qū)小,rbl文件要比download分區(qū)小。
bin文件前面已經(jīng)解釋過了,但是還有一個地方要注意,就是如果你的rbl是進過壓縮的,那實際大小會比bin文件小,存放的時候只要比download分區(qū)小即可,但是升級的時候rbl文件是會解壓的,解壓后的的大小等于這個固件bin文件的大小,因此,你的app分區(qū)一定要大于解壓后的文件大小。
3:升級固件的版本不能相同。
如果設(shè)備已經(jīng)進行過一次升級,那設(shè)備就會有版本記錄(版本號是打包固件時的版本,和你在app代碼里面定義的版本號不是同一個),那下一次升級的固件版本號(打包時的版本號)必須和之前升級的那個固件版本不同,否則會直接跳過升級流程,哪怕這個app固件實際上的代碼不一致。(升級與否只看打包時的版本號)
八、進階學(xué)習(xí)
通過串口升級的這種方式在實際的使用中還是有很大的局限性,為了增加升級的距離,可以對升級的流程進行優(yōu)化。
比如:串口升級的方式可以使用RS485,485的通訊距離很遠(yuǎn),在沒有網(wǎng)絡(luò)的情況下可以考慮這種方式。另外,上面的示例是用命令行啟動之后才會進入升級,實際使用中可以通過其他方式實現(xiàn),比如按鍵觸發(fā)。
除了串口之外可以考慮通過網(wǎng)絡(luò)或者U盤來進行升級,因為這兩種方式涉及到的東西還是比較多的,我就不詳細(xì)的把每個步驟都寫出來了,大概講一下思路吧。
其實不管用哪種方式,最后OTA升級那部分都是一樣的,我們只要把升級的固件存儲到flash的download分區(qū)然后重啟就可以了,區(qū)別只在于怎么把固件存進去。
理清思路之后其實就很簡單了,U盤升級和串口升級基本一樣,串口升級是通過數(shù)據(jù)線從PC端傳輸固件,而U盤升級則是從U盤傳輸固件,只要我們把U盤掛載到虛擬文件系統(tǒng),然后把U盤的升級固件拷貝到flash即可,后面的升級步驟都是一樣的。
U盤升級我之前做了一個例程,感興趣的同學(xué)可以下載來玩一下。
usb固件升級代碼:https://download.csdn.net/download/ShenZhen_zixian/12880749
同樣的思路,通過網(wǎng)絡(luò)升級也是一樣的,首先我們需要一個網(wǎng)絡(luò)模塊,連接上網(wǎng)絡(luò)之后通過http從網(wǎng)頁上下載升級固件到flash里面,然后再重啟升級即可。因為我這邊實際的應(yīng)用是公司量產(chǎn)的設(shè)備,用的也是公司的服務(wù)器和平臺,所以代碼就不太方便拿出來分享了,我只講一下思路,感興趣的同學(xué)可以自己嘗試。
大致的流程如下:
1:設(shè)備連接網(wǎng)絡(luò)
2:通過http定時發(fā)送請求(上傳設(shè)備當(dāng)前的設(shè)備號和版本號到平臺)
3:平臺那邊根據(jù)設(shè)備上傳的設(shè)備號和版本號判斷是否要升級,如果要升級則下發(fā)固件的下載地址
4:設(shè)備下載固件并升級
九、結(jié)束語
OTA是非常使用的一門技術(shù),特別是通過網(wǎng)絡(luò)升級,對設(shè)備的升級迭代來說是非常方便的,RT-thread的這套方案總體上還是很好用的,也不復(fù)雜,缺點就是bootloader占用的內(nèi)存比較大,希望后面可以優(yōu)化一下。
好了,關(guān)于OTA的介紹就到這里,如果還有什么問題,歡迎在評論區(qū)留言。如果這篇文章能夠幫到你,就給我點個贊吧,如果想了解更多RT-thread和單片機的內(nèi)容,可以關(guān)注一下博主,后續(xù)我還會繼續(xù)分享更多的經(jīng)驗給大家。
教程相關(guān)源碼:https://pan.baidu.com/s/1N2D8dM31deKIqNqaIQfPiA
提取碼:7nsx