OTA的学习
一、什么是OTA?
OTA升級(jí)機(jī)制可以讓聯(lián)網(wǎng)設(shè)備在固件正常運(yùn)行時(shí)通過(guò)網(wǎng)絡(luò)(WIFI或藍(lán)牙)進(jìn)行固件升級(jí)。
要想通過(guò)OTA方式進(jìn)行固件升級(jí),首先要配置設(shè)備的分區(qū)表。
二、什么是分區(qū)表?
每片ESP32的flash上,可包含多個(gè)應(yīng)用程序和多種不同類型的數(shù)據(jù)(例如校準(zhǔn)數(shù)據(jù)、文件系統(tǒng)數(shù)據(jù)、參數(shù)存儲(chǔ)器數(shù)據(jù)等)。具體來(lái)說(shuō),分區(qū)表就在ESP32flash的默認(rèn)偏移地址0x8000處,長(zhǎng)度為0x1000(4KB)。
flash地址在0x9000之前的結(jié)構(gòu)是固定的,第一部分是二級(jí)的BootLoader,后面緊接著就是分區(qū)表,尺寸為0x1000。分區(qū)表的主要作用就是用來(lái)管理0x9000之后的數(shù)據(jù)。
三、如何創(chuàng)建分區(qū)表?
我們可以創(chuàng)建一個(gè)分區(qū)表文件來(lái)實(shí)現(xiàn),即CSV文件。下表是一張ESP32 flash大小為4M的分區(qū)表文件。
在這個(gè)分區(qū)表中,指定了兩個(gè)1600KB大小的應(yīng)用程序分區(qū)(APP),存放我們待升級(jí)的固件,因此我們升級(jí)的固件大小不能超過(guò)1600KB。
ESP32 SPI Flash 內(nèi)有與升級(jí)相關(guān)的(至少)四個(gè)分區(qū):OTA data、Factory App、OTA_0、OTA_1。其中 FactoryApp 內(nèi)存有出廠時(shí)的默認(rèn)固件。
首次進(jìn)行 OTA 升級(jí)時(shí),OTA Demo 向 OTA_0 分區(qū)燒錄目標(biāo)固件,并在燒錄完成后,更新 OTA data 分區(qū)數(shù)據(jù)并重啟。
系統(tǒng)重啟時(shí)獲取 OTA data 分區(qū)數(shù)據(jù)進(jìn)行計(jì)算,決定此后加載 OTA_0 分區(qū)的固件執(zhí)行(而不是默認(rèn)的 Factory App 分區(qū)內(nèi)的固件),從而實(shí)現(xiàn)升級(jí)。
同理,若某次升級(jí)后 ESP32 已經(jīng)在執(zhí)行 OTA_0 內(nèi)的固件,此時(shí)再升級(jí)時(shí) OTA Demo 就會(huì)向 OTA_1 分區(qū)寫(xiě)入目標(biāo)固件。再次啟動(dòng)后,執(zhí)行 OTA_1 分區(qū)實(shí)現(xiàn)升級(jí)。以此類推,升級(jí)的目標(biāo)固件始終在 OTA_0、OTA_1 兩個(gè)分區(qū)之間交互燒錄,不會(huì)影響到出廠時(shí)的 Factory App 固件。
四、怎么配置OTA FLASH分區(qū)?
在創(chuàng)建此分區(qū)文件后,我們可以在編譯項(xiàng)目時(shí)通過(guò) menuconfig中配置指定自定義分區(qū)表文件。
你可以在菜單Partition Table-->Partition Table中選擇為Custom partition table CSV,同時(shí)選定分區(qū)表文件。
芯片升級(jí)整體過(guò)程
首先是連接上網(wǎng)絡(luò)。其次是定義分區(qū)表,確定OTA_0和OTA_1。
芯片從OTA_0啟動(dòng)然后觸發(fā)OTA升級(jí)。芯片將從HTTPS服務(wù)器下載新固件并將其保存到OTA_1分區(qū)中,然后將自動(dòng)更新ota_data分區(qū)數(shù)據(jù),指示下次重啟后應(yīng)從OTA1分區(qū)啟動(dòng)。引導(dǎo)加載程序?qū)⒆x取ota_data分區(qū)中的內(nèi)容并運(yùn)行所選定的應(yīng)用程序分區(qū)。
應(yīng)用程序回滾
如果在新版應(yīng)用第一次啟動(dòng)時(shí)發(fā)生斷電或意外崩潰,則會(huì)回滾至之前正常運(yùn)行的版本。
建議:盡快完成自測(cè),防止因斷電回滾。
只有?OTA?分區(qū)可以回滾。工廠分區(qū)不會(huì)回滾。
回滾的主要目的是確保設(shè)備更新后正常運(yùn)轉(zhuǎn)。該功能可使設(shè)備在更新新版本后出現(xiàn)嚴(yán)重錯(cuò)誤時(shí),回滾到之前正常運(yùn)行的應(yīng)用版本。當(dāng)設(shè)置了回滾使能,并執(zhí)行完OTA升級(jí),應(yīng)用更新至新版本后,芯片可能有三種情況。
1、應(yīng)用程序運(yùn)行正常。esp_ota_mark_app_valid_cancel_rollback()標(biāo)記合法函數(shù)將應(yīng)用程序狀態(tài)標(biāo)記為合法 ESP_OTA_IMG_VALID,啟動(dòng)無(wú)限制。
2、應(yīng)用程序出現(xiàn)嚴(yán)重錯(cuò)誤,無(wú)法繼續(xù)工作,必須回滾到原先版本。esp_ota_mark_app_invalid_rollback_and_reboot()標(biāo)記非法重啟函數(shù)將正在運(yùn)行的版本標(biāo)記為非法ESP_OTA_IMG_INVALID,然后重啟芯片。重啟后引導(dǎo)加載器不會(huì)選取剛才更新的版本,而是此前正常運(yùn)行的版本。
?實(shí)現(xiàn)原理
核心流程:
1.制作升級(jí)包
2.下載升級(jí)包
3.驗(yàn)簽升級(jí)包
4.更新程序
下載方式:
不管采用OTA方式還是有線通信方式升級(jí),下載升級(jí)包的方式包括后臺(tái)式下載和非后臺(tái)式下載兩種模式。
后臺(tái)式下載:
在升級(jí)的時(shí)候,新固件在后臺(tái)悄悄下載,即新固件下載屬于應(yīng)用程序功能的一部分,在新固件下載過(guò)程中,應(yīng)用可以正常使用,也就是說(shuō)整個(gè)下載過(guò)程對(duì)用戶來(lái)說(shuō)是無(wú)感的,下載完成后,系統(tǒng)再跳到BootLoader程序,由BootLoader完成新固件覆蓋老固件的操作。比如智能手機(jī)升級(jí)Android或者iOS系統(tǒng)都是采用后臺(tái)式方式,新系統(tǒng)下載過(guò)程中,手機(jī)可以正常使用。
非后臺(tái)式下載:
在升級(jí)的時(shí)候,系統(tǒng)需要先從應(yīng)用程序跳入到BootLoader程序,由BootLoader進(jìn)行新固件下載工作,下載完成后BootLoader繼續(xù)完成新固件覆蓋老固件的操作,至此升級(jí)結(jié)束。早先的功能機(jī)就是采用非后臺(tái)來(lái)升級(jí)操作系統(tǒng)的,即用戶需要先長(zhǎng)按某些按鍵進(jìn)入bootloader模式,然后再進(jìn)行升級(jí),整個(gè)升級(jí)過(guò)程中手機(jī)正常功能都無(wú)法使用
新舊固件覆蓋模式:
新固件替換老固件覆蓋的兩種方式:雙區(qū)模式和單區(qū)模式。
雙區(qū)模式:
雙區(qū)模式中老固件和新固件在flash中各占一塊bank(存儲(chǔ)區(qū))。假設(shè)老固件放在bank0(運(yùn)行區(qū))中,新固件放在bank1(下載區(qū))中,升級(jí)的時(shí)候,應(yīng)用程序先把新固件下載到bank1中,只有當(dāng)新固件下載完成并校驗(yàn)成功后,系統(tǒng)才會(huì)跳入BootLoader程序,然后擦除老固件所在的bank0區(qū),并把bank1的新固件拷貝到bank0中。
后臺(tái)式下載必須采用雙區(qū)模式進(jìn)行升級(jí)。
優(yōu)點(diǎn):
升級(jí)過(guò)程中出現(xiàn)問(wèn)題或者新固件有問(wèn)題,它還可以選擇之前的老固件老系統(tǒng)繼續(xù)執(zhí)行而不受其影響。
缺點(diǎn):
多占用flash空間的一個(gè)存儲(chǔ)區(qū),在系統(tǒng)資源比較緊張的時(shí)候較為困難。
?
單區(qū)模式:
單區(qū)模式的非后臺(tái)式下載只有一個(gè)bank0(運(yùn)行區(qū)),老固件和新固件共享這一個(gè)bank0。升級(jí)的時(shí)候,進(jìn)入bootloader程序后先擦除老固件,然后直接把新固件下載到同一個(gè)bank中,下載完成后校驗(yàn)新固件的有效性,新固件有效升級(jí)完成,否則要求重來(lái)。
優(yōu)點(diǎn):
跟雙區(qū)模式相比,單區(qū)模式節(jié)省了Flash空間的一個(gè)bank,在系統(tǒng)資源比較緊張的時(shí)候,單區(qū)模式是一個(gè)不錯(cuò)的選擇。
缺點(diǎn):
如果升級(jí)過(guò)程中出現(xiàn)問(wèn)題或者新固件有問(wèn)題,單區(qū)模式碰到這種情況就只能一直待在bootloader中,然后等待再次升級(jí)嘗試,此時(shí)設(shè)備的正常功能已無(wú)法使用,從用戶使用這個(gè)角度來(lái)說(shuō),可以說(shuō)此時(shí)設(shè)備已經(jīng)“變磚”了。
相比較,雙區(qū)模式雖然犧牲了很多存儲(chǔ)空間,但是換來(lái)了更好的升級(jí)體驗(yàn)。
二、MCU OTA升級(jí)
以MCU(微控制器)固件升級(jí)為例,講解嵌入式裸機(jī)程序的OTA升級(jí)。由于裸機(jī)固件是固化在設(shè)備的存儲(chǔ)器(如flash)中,即存儲(chǔ)器中保存的是機(jī)器碼,對(duì)MCU進(jìn)行OTA固件升級(jí),也就是要實(shí)現(xiàn)通過(guò)OTA方式將存儲(chǔ)器中舊固件的機(jī)器碼替換為新固件的機(jī)器碼。
數(shù)字簽名
簽名:
A給B發(fā)送消息,A先計(jì)算出消息的消息摘要,然后使用自己的私鑰加密消息摘要,被加密的消息摘要就是簽名。
驗(yàn)簽:
B收到消息后,也會(huì)使用和A相同的方法計(jì)算消息摘要,然后用A的公鑰解密簽名,并與自己計(jì)算出來(lái)的消息
摘要進(jìn)行比較,如果相同則說(shuō)明消息是A發(fā)送給B的,同時(shí),A也無(wú)法否認(rèn)自己發(fā)送消息給B的事實(shí)。
(B使用A的公鑰解密簽名文件的過(guò)程,叫做"驗(yàn)簽")
密碼學(xué)基礎(chǔ)概念:
1.什么是消息摘要?
2.什么是非對(duì)稱加解密?私鑰與公鑰?
3.什么是數(shù)字簽名?
數(shù)字簽名的作用:
保證數(shù)據(jù)完整性,機(jī)密性和發(fā)送方角色的不可抵賴性。
消息摘要函數(shù):
MD4、MD5、SHA-1、SHA-256、SHA-384、SHA-512
數(shù)字簽名算法:
RSA、Rabin方式、ElGamal方式、DSA
2.1 ?制作升級(jí)包
通過(guò)簽名工具使用簽名算法對(duì)固件進(jìn)行數(shù)字簽名,簽名后的文件即為升級(jí)包。
升級(jí)包的內(nèi)容一般包括firmware、header和signature value。
Firmware:固件
Header:頭部信息。存放配置信息,如版本號(hào)、產(chǎn)品類型等。
Signature value:簽名值。對(duì)firmware和header簽名后的值。
簽名工具:
上位機(jī)軟件,能計(jì)算固件的簽名值,并將固件打包為升級(jí)包的格式。
固件簽名:
上位機(jī)軟件先計(jì)算整個(gè)固件的消息摘要,使用非對(duì)稱密碼的私鑰對(duì)摘要進(jìn)行加密,
被加密后的消息摘要數(shù)據(jù)就是簽名值。
固件簽名的意義:
計(jì)算hash值可以識(shí)別固件是否被篡改和偽裝,確保固件的完整性。
使用非對(duì)稱秘鑰簽名方便后續(xù)驗(yàn)證升級(jí)包身份的合法性。
2.2? 下載升級(jí)包
根據(jù)上位機(jī)軟件和MCU設(shè)備約定的通信協(xié)議,上位機(jī)軟件將升級(jí)包通過(guò)OTA方式發(fā)送給MCU設(shè)備,
MCU設(shè)備收到數(shù)據(jù)后,根據(jù)通信協(xié)議解析出升級(jí)包的數(shù)據(jù),并將升級(jí)包的數(shù)據(jù)保存到存儲(chǔ)器中。
通信協(xié)議的作用:
通訊雙方約定俗成地用于數(shù)據(jù)交流的格式。
下載的方式:
1.在應(yīng)用程序中下載:后臺(tái)式
2.在BootLoader中下載:非后臺(tái)式
2.3? 驗(yàn)簽升級(jí)包
MCU設(shè)備接收完所有的升級(jí)包后,先計(jì)算升級(jí)包中固件的摘要,然后使用非對(duì)稱秘鑰的
公鑰解密升級(jí)包的簽名值,如果解密出來(lái)的固件摘要與自己計(jì)算的摘要相同,則驗(yàn)簽成功。
2.4? 更新固件
驗(yàn)簽成功保證了固件的完整性和合法性后,MCU設(shè)備從應(yīng)用程序進(jìn)入BootLoader程序,
在BootLoader程序中將flash中的新固件數(shù)據(jù)搬運(yùn)到舊固件的存儲(chǔ)區(qū),將其覆蓋。
然后BootLoader程序啟動(dòng)固件運(yùn)行,此時(shí)固件為新固件。
flash固件數(shù)據(jù)更新:
擦除flash,寫(xiě)flash。
在使用分區(qū)表時(shí),最簡(jiǎn)單的方法就是打開(kāi)項(xiàng)目配置菜單(idf.py?menuconfig),并在?CONFIG_PARTITION_TABLE_TYPE?下選擇一個(gè)預(yù)定義的分區(qū)表:
-
“Single factory app, no OTA”
-
“Factory app, two OTA definitions”
-
分區(qū)表設(shè)置成Factory app, two OTA definitions
-
這里我們選擇如下:
- 在以上兩種選項(xiàng)中,出廠應(yīng)用程序均將被燒錄至 flash 的 0x10000 偏移地址處。這時(shí),運(yùn)行?idf.py partition-table?,即可以打印當(dāng)前使用分區(qū)表的信息摘要(當(dāng)然肯定是得先燒寫(xiě)程序到ESP32里面)
-
?
?
-
?
?
輸入 idf.py monitor,結(jié)果如下
?分區(qū)表設(shè)置成Single factory app, no OTA
?輸入 idf.py monitor,結(jié)果如下
?
?分區(qū)表設(shè)置為Single factory app(large),no OTA
?
?
?
?接下來(lái)演示在本地 PC 端搭建 http 服務(wù)器實(shí)現(xiàn)?ESP32?OTA 過(guò)程
?設(shè)置 WiFi 賬號(hào)密碼:
?
注意:wifi的SSID和密碼一定要跟連接的熱點(diǎn)或者路由器一致。
?使能 HTTP OTA:
?由于 ESP-IDF 默認(rèn)為 HTTPS OTA,需要在?menuconfig?里打開(kāi)以下選項(xiàng)來(lái)讓 HTTP OTA 成功進(jìn)行
?
準(zhǔn)備需要 OTA 的 Bin 文件
在此處以需要升級(jí)的 Bin 為 helloworld.bin?為例,將?helloworld.bin?文件放在build目錄下?
?
?查詢 python 版本,執(zhí)行如下命令:
?
- 如果上述指令返回的 Python 版本是 3.X ,通過(guò)如下命令建立服務(wù)器
?
??查詢本機(jī) IP
在任意終端輸入?ipconfig,結(jié)果如下
?
可以看到 PC 的 ip 地址為?192.168.1.102?,后續(xù)在填寫(xiě) OTA URL 時(shí)需要用到此 ip。?
?注:服務(wù)器建立好后,可通過(guò)網(wǎng)址 ip地址:8070?在網(wǎng)頁(yè)端查詢本地服務(wù)器(ip地址為pc機(jī)的地址)
?
?這個(gè)目錄列表就是終端的路徑下的。
進(jìn)入網(wǎng)頁(yè)后,這里主要是復(fù)制hello_world.bin的地址
?我這里復(fù)制到的地址如下所示,這就是新固件的下載地址待會(huì)需要用到
?
配置 OTA URL?
?menuconfig 里配置 OTA URL 為?http://192.168.1.102:8070/hello_world.bin
1.到此升級(jí)包準(zhǔn)備工作已經(jīng)完成
2.那個(gè)http服務(wù)端需要一直打開(kāi),不能關(guān)閉
3.你的電腦必須是在2.4G頻段的wifi,否則ESP32無(wú)法和電腦在同一個(gè)局域網(wǎng)內(nèi)
4.點(diǎn)擊hello_world.bin,看看能不能下載,如果不能下載,可能是電腦的防火墻攔截了,可以關(guān)閉防火墻試試。否則你的ESP32也是不能下載到固件的
?
?檢查分區(qū)表
在上述 menuconfig 里檢查分區(qū)表是否選擇為正確包含 OTA 分區(qū)的分區(qū)表,OTA 示例里會(huì)默認(rèn)做以下修改:?
?
?
?開(kāi)始 OTA
此時(shí)在 OTA 示例終端 下輸入?idf.py flash monitor?編譯燒寫(xiě) OTA 示例至 ESP32 中即可發(fā)現(xiàn) OTA 升級(jí)成功。?
?
總結(jié)
- 上一篇: OTA升级二——阿里云端OTA配置及应用
- 下一篇: OTA测试