前言:
前陣子做項目時需要IAP升級,遇到了很多問題,我在此總結(jié)一下,避免后面再次踩到同樣的坑。這個過程還是有些學(xué)問的,有時往往理論正確但是實踐起來卻遇到各種bug,需要好好研究,特別是對應(yīng)單片機(jī)型號不同,也有很多地方需要修改。
本人使用的芯片型號是AT32F413CB,FLASH空間為128K,一個扇區(qū)1K。
有紕漏請指出,轉(zhuǎn)載請說明。
學(xué)習(xí)交流請發(fā)郵件?1280253714@qq.com
?
一、為什么產(chǎn)品需要IAP升級
有些高端一點的消費電子產(chǎn)品可能需要升級,但是產(chǎn)品發(fā)布后就不太可能讓用戶插個燒錄線去重新燒寫程序,所以需要預(yù)留一下有線或無線的接口提供給用戶去升級。
比較合理的方式是產(chǎn)品連上藍(lán)牙或WiFi,通過手機(jī)APP進(jìn)行升級(后文會提到,也可以叫做OAT技術(shù))。
二、IAP升級是什么
IAP(In Application Programming,應(yīng)用編程)
ISP(全稱 In System Programming,即系統(tǒng)編程)
ISP 一般都是通過專業(yè)的調(diào)試器或者下載器對單片機(jī)內(nèi)部的 Flash 存儲器進(jìn)程編程(如JTAG等),而 IAP 技術(shù)是從結(jié)構(gòu)上將 Flash 儲存器映射分為兩個或者多個分區(qū),在一個分區(qū)中對其他分區(qū)進(jìn)行編程,這個分區(qū)通常稱為 bootloader。
OTA(全稱 Over The Air Technology,即云端下載技術(shù),也叫做“空中下載技術(shù)”),其基礎(chǔ)是 IAP 技術(shù), 可以簡單理解為 IAP 的另一種實現(xiàn)方式,通常采用的是無線升級方式(串口、CAN 等屬于“直接線控升級”),如通過藍(lán)牙近距離無線升級、ESP8266 網(wǎng)絡(luò)升級等
三、IAP技術(shù)將FLASH至少分為兩個分區(qū),不同的分區(qū)方式有什么區(qū)別?
我們當(dāng)然希望分區(qū)相對多一些比較好,可操作的空間也大,但是在產(chǎn)品開發(fā)中,要評估單片機(jī)的資源,如果FLASH空間為128K,APP需要近100K的空間,那么此時剩余的空間基本上只能留給bootloader,只能分為兩個區(qū)。
劃分兩個分區(qū),只有bootloader和app分區(qū),這個是最簡單也是最基本的功能;而在實際產(chǎn)品開發(fā)過程中,需要考慮多種因素和需求,如:升級失敗了該怎么辦?想恢復(fù)出廠的版本怎么辦?等等一系列的問題。
?兩個分區(qū)的情況如下:
程序首先從bootloader空間執(zhí)行,檢查寫進(jìn)FLASH用戶空間的標(biāo)志位,當(dāng)沒有固件需要升級時,此時跳轉(zhuǎn)到APP,APP程序有一個checkFirmWareUpdate()函數(shù),時刻檢測是否有升級命令,若有,則寫需要升級的標(biāo)志位,跳到bootloader接收新APP寫進(jìn)APP FLASH空間,當(dāng)校驗無誤(MD5校驗文件完整性、特殊標(biāo)志位加密升級),升級完成。
?| booloader Flash | app Flash |
?三個分區(qū)與兩個分區(qū)情況類似:
但在bootloader接收新APP時寫進(jìn)的是空白FLASH空間,且空間大小合適時寫進(jìn)APP FLASH空間,升級完成。
| booloader Flash | app Flash | 空白Flash |
接下來為了講解方便,先講兩個分區(qū)的方案。
四、APP如何跳到bootloader?
首先提個問題,APP接收到升級命令后如何跳到bootloader?
如果通過指針跳轉(zhuǎn)到bootloader,那么之前在APP對外設(shè)的配置,進(jìn)入到IAP后會繼續(xù)生效,需要重新配置,XXX_Reset()或者XXX_DeInit()
而如果是通過復(fù)位操作,則無需考慮這個問題。
我們把bootloader的程序放在FLASH的起始地址,當(dāng)程序復(fù)位后(這里只能用軟件復(fù)位),會執(zhí)行bootloader程序。但是前面從app跳轉(zhuǎn)到bootldoader,為了正常跳轉(zhuǎn),所以需要__set_FAULTMASK (1)屏蔽所有中斷,所以在bootloader剛開始時要__set_FAULTMASK (0)。
軟件復(fù)位反應(yīng)在硬件上就是發(fā)了一個信號給硬件復(fù)位端
所以之前在APP對外設(shè)的配置全部失效,bootloader需要重新配置
五、在bootloader接收APP程序,如果在升級過程因為燒寫時斷了連接/芯片斷電該如何處理?
有個比較好的方法是,通過標(biāo)志位來判斷,如果升級未完成,則標(biāo)志位始終為升級未完成狀態(tài),下次重新接收到升級命令后繼續(xù)按照升級流程走。
這里的標(biāo)志位應(yīng)該放在用戶FLASH空間里(后面會講)
六、如何判斷更新的APP是我要的APP?
為什么會提這個問題呢?
假如APP升級的接口被獲取了,那么程序就能被任意燒寫,假如有人惡意寫些病毒程序進(jìn)單片機(jī)導(dǎo)致功能異常,若出現(xiàn)重大事故,開發(fā)者要負(fù)責(zé)任。
為了避免這個問題,需要通過加密的方式來判定更新的APP是開發(fā)者要的APP。
最簡單的方式是在APP前加一段固件包頭(可由上位機(jī)自動添加),包頭中含加密標(biāo)志位,在接收更新APP程序時進(jìn)行判斷,如果錯誤則不再接收APP程序,或者是已經(jīng)接收到的APP程序失效(丟棄)。
所以實際FLASH空間的分配情況應(yīng)該是這樣:
?| booloader Flash |?firmware header FLASH | app Flash |
七、怎么保證用戶數(shù)據(jù)不因為APP的升級而被丟失?
實際上,有些用戶數(shù)據(jù)需要保存(如睡眠時長、每日步數(shù)),這些數(shù)據(jù)我們不希望隨著APP的升級而被刪除,此時就需要FLASH再開辟一塊空間來保存用戶數(shù)據(jù),所以前面的兩種分區(qū)的方式只是簡化版,實際情況應(yīng)該如下:
?| booloader Flash |?firmware header FLASH | app Flash | User Flash |
八、FLASH只能按頁擦除,但是寫用戶數(shù)據(jù)時一般只寫幾個字節(jié),怎么比較好地保存用戶數(shù)據(jù)?
其實這個問題跟IAP升級無關(guān),但是IAP升級時需要在用戶FLASH寫標(biāo)志位,如果按照傳統(tǒng)方式,先按頁擦除再寫標(biāo)志位,那么可能會誤把其他用戶數(shù)據(jù)擦除掉。
比較好的方法是把用戶FLASH空間分為兩塊,塊里有一個讀寫標(biāo)志位、一個長度標(biāo)志位,然后根據(jù)這兩個標(biāo)志位將用戶數(shù)據(jù)在這兩塊空間進(jìn)行挪騰。
九、升級成功后,BootLoader如何跳轉(zhuǎn)到APP?
通過函數(shù)指針跳轉(zhuǎn)?
IAP Bootload 和 App 間跳轉(zhuǎn)的代碼實現(xiàn)
十、三個分區(qū)(BootLoader、APP1、APP2)有什么用?
- 一種是APP1里存放出廠程序,永不刪除,APP2作為升級后的程序
- 一種是只有APP2正確接受到程序且校驗無誤,把APP2的程序搬移到APP1中,保證每次都有APP程序
- 一種是當(dāng)APP程序過大時,此時可把APP1和APP2合并為一個分區(qū),那么此時這種方式跟前面兩個分區(qū)道理一樣
以上方法根據(jù)產(chǎn)品需求靈活調(diào)整
十一、怎么確保重復(fù)升級/升級過程中不變磚?
為什么會無法重復(fù)升級?原因是升級的接口沒了。
為什么升級會變磚?本來舊版本固件/最新固件/無固件等標(biāo)志位,對應(yīng)著要不要升級,升級時跳到IAP,升級完跳到APP的情況。但是程序跳轉(zhuǎn)的狀態(tài)機(jī)跟實際程序存儲情況矛盾,就可能會發(fā)生異常。
1.首先要確保每次要升級的APP都有可供升級的接口,不然可能出現(xiàn)燒了新的APP程序后,當(dāng)外部升級的命令到來時,卻無法接收升級指令,導(dǎo)致無法跳轉(zhuǎn)到IAP去進(jìn)行升級。
2.升級時,接收到的幀寫進(jìn)FLASH中,要保證寫地址正確,如果把IAP給覆蓋了,就可能導(dǎo)致升級失敗,升級的接口也沒了?;蛘呤菍懙轿粗獏^(qū)域,當(dāng)升級完成時,IAP跳到APP,但是跳到未知區(qū)域?qū)е鲁绦虺鲥e卡死。
3.IAP和APP的地址設(shè)置要正確,不然跳轉(zhuǎn)時跳到未知存儲區(qū)域時,就可能變磚。
4.IAP程序設(shè)計時,要保證正確接收到完整的APP包且校驗無誤后,才能跳轉(zhuǎn)到APP,這樣,即使是掉電或者升級失敗,也能保證再次升級無誤。那么,在發(fā)送端(發(fā)送升級指令和固件包的一端)就要發(fā)一個幀總數(shù),同時每一個幀要標(biāo)注幀編號,且不能丟幀/重復(fù)發(fā)幀;接收端(升級的一端)不能丟幀/重復(fù)寫幀。當(dāng)接收完時,接收端要判斷幀總數(shù)和接收的幀的數(shù)量一致,且校驗無誤后,才能跳轉(zhuǎn)到APP。
十二、一個不容易排除的bug
問題:
全速運行就會進(jìn)入硬錯誤中斷
解決方案:
?擦除app程序后要加一個延時函數(shù)
?參考文檔
STM32中NVIC_SystemReset()函數(shù)的作用?什么時候用?_nvic_systemreset();_魏波.的博客-CSDN博客
常用的幾種 IAP 升級技術(shù)方案 - 知乎
STM32固件升級的一點經(jīng)驗 - 知乎
電子產(chǎn)品如何使用IAP方式升級程序_iap升級_白楊qq_44597856的博客-CSDN博客
IAP固件升級原理及實現(xiàn)詳解文章來源:http://www.zghlxwxcb.cn/news/detail-769222.html
STM32單片機(jī)IAP程序升級方法_iap升級_fflanfj的博客-CSDN博客文章來源地址http://www.zghlxwxcb.cn/news/detail-769222.html
到了這里,關(guān)于單片機(jī)IAP升級的一些問題與經(jīng)驗的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!