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