基于Bootloader的可靠嵌入式軟件遠(yuǎn)程更新機(jī)制
掃描二維碼
隨時(shí)隨地手機(jī)看文章
1 隨著嵌入式系統(tǒng)在各個(gè)領(lǐng)域的廣泛應(yīng)用,嵌入式軟件的維護(hù)變得日益重要[1]。嵌入式系統(tǒng)投入實(shí)際環(huán)境中運(yùn)行后,一部分在軟件開(kāi)發(fā)過(guò)程中無(wú)法充分測(cè)試的錯(cuò)誤便會(huì)暴露出來(lái);在嵌入式系統(tǒng)的運(yùn)行期內(nèi),用戶也往往會(huì)對(duì)嵌入式軟件提出新的功能要求和性能要求。因此,嵌入式軟件的更新逐漸成為嵌入式系統(tǒng)實(shí)際應(yīng)用的一個(gè)重要問(wèn)題。當(dāng)嵌入式系統(tǒng)安裝數(shù)量較多,或安裝位置不方便的情況下,采用人工更新方式會(huì)花費(fèi)較大的人力和物力。遠(yuǎn)程自動(dòng)更新則在嵌入式系統(tǒng)中設(shè)計(jì)一個(gè)有線或無(wú)線的通信接口,在異地采用遠(yuǎn)程通信的方式實(shí)現(xiàn)嵌入式軟件的自動(dòng)更新。該方式能有效地降低嵌入式軟件的更新和維護(hù)成本,因此受到了廣泛的關(guān)注。當(dāng)前對(duì)嵌入式軟件遠(yuǎn)程自更新技術(shù)的研究主要停留在更新方法的設(shè)計(jì)上,對(duì)如何確保更新過(guò)程的可靠性還沒(méi)有深入的研究。更新的可靠性主要受兩個(gè)方面的影響:一是更新數(shù)據(jù)遠(yuǎn)程傳輸?shù)目煽啃裕涣硪环矫媸窍到y(tǒng)更新后啟動(dòng)的可靠性。在采用嵌入式Linux、Windows CE等較為復(fù)雜的操作系統(tǒng)時(shí),一般設(shè)計(jì)一個(gè)獨(dú)立的bootloader程序[2][3],對(duì)系統(tǒng)進(jìn)行初始化并引導(dǎo)嵌入式操作系統(tǒng)。這種結(jié)構(gòu)的嵌入式系統(tǒng)的啟動(dòng)與bootloader緊密相關(guān)。本文針對(duì)采用bootloader的嵌入式系統(tǒng),提出了一種高可靠的嵌入式軟件遠(yuǎn)程自動(dòng)更新機(jī)制,并以基于ARM微處理器[4]、嵌入式Linux操作系統(tǒng)[5]和無(wú)線通信接口的嵌入式系統(tǒng)為例進(jìn)行了軟硬件設(shè)計(jì)。然后將更新機(jī)制應(yīng)用到實(shí)際系統(tǒng)中進(jìn)行測(cè)試,最后給出了本文的結(jié)論。
2 更新系統(tǒng)的總體結(jié)構(gòu)
本部分以ARM和嵌入式Linux操作系統(tǒng)為例,介紹遠(yuǎn)程自更新系統(tǒng)的整體結(jié)構(gòu)。支持遠(yuǎn)程自更新的嵌入式系統(tǒng)可以劃分為前端運(yùn)行模塊和后臺(tái)控制模塊兩部分。前端運(yùn)行模塊采用基于ARM9核心的S3C2410微處理器,最高主頻可達(dá)200Mhz,配有8M的RAM和32M的FLASH存儲(chǔ)器,運(yùn)行ARM-Linux嵌入式操作系統(tǒng),具有獨(dú)立設(shè)計(jì)的bootloader程序。后臺(tái)控制模塊用于實(shí)現(xiàn)對(duì)前端運(yùn)行模塊的遠(yuǎn)程異地控制,是系統(tǒng)的控制核心。前端運(yùn)行模塊通過(guò)無(wú)線模塊BCM860接入到CDMA2000-1X無(wú)線通信系統(tǒng),繼而連接到Internet。CDMA2000-1X是第2.5代移動(dòng)通信系統(tǒng),支持較高速率的數(shù)據(jù)分組業(yè)務(wù)。后臺(tái)控制模塊采用有線方式直接與Internet相連接,與前臺(tái)運(yùn)行模塊之間進(jìn)行標(biāo)準(zhǔn)的基于TCP/IP協(xié)議的通信。狀態(tài)信息、控制信息和更新文件都在這一數(shù)據(jù)鏈路上進(jìn)行傳輸。
圖1 系統(tǒng)結(jié)構(gòu)
3 更新系統(tǒng)的軟件設(shè)計(jì)
3.1 Flash存儲(chǔ)器的布局
傳統(tǒng)的采用Linux的嵌入式系統(tǒng)的FLASH存儲(chǔ)器的布局如圖2(a)所示。為了敘述方便,我們將Linux內(nèi)核和文件系統(tǒng)合并稱為L(zhǎng)inux鏡像文件。系統(tǒng)進(jìn)行軟件更新時(shí),先把新鏡像文件下載到內(nèi)存中,然后燒寫(xiě)到FLASH的鏡像文件存儲(chǔ)區(qū),覆蓋舊的鏡像文件。該方法沒(méi)有考慮更新過(guò)程中可能遇到的干擾。如果在更新中因?yàn)橥话l(fā)的干擾出現(xiàn)更新數(shù)據(jù)錯(cuò)誤或燒寫(xiě)錯(cuò)誤,就可能導(dǎo)致軟件更新后bootloader無(wú)法啟動(dòng)新的鏡像文件,前端模塊無(wú)法運(yùn)行,并失去了與后臺(tái)控制中心的聯(lián)系,成為“孤立系統(tǒng)”。這種情況發(fā)生后只能到前端系統(tǒng)的安裝地點(diǎn)進(jìn)行人工處理,從而導(dǎo)致花費(fèi)較大的代價(jià)。
圖2 (a) 傳統(tǒng)的FLASH布局 (b) 自更新系統(tǒng)的FLASH布局
為了提高軟件更新的可靠性,本機(jī)制對(duì)FLASH存儲(chǔ)器的布局進(jìn)行了重新設(shè)計(jì),如圖2(b)所示。Bootloader存儲(chǔ)區(qū)后面設(shè)計(jì)了3個(gè)鏡像文件存儲(chǔ)區(qū)。其中一個(gè)存儲(chǔ)區(qū)用于存放當(dāng)前要啟動(dòng)的最新的鏡像文件,稱為當(dāng)前區(qū);另一個(gè)存儲(chǔ)區(qū)用于存放上一版本的鏡像文件,稱為前版本區(qū);剩下一個(gè)存儲(chǔ)區(qū)用于存放最初版本的鏡像文件,稱為初版本區(qū)。當(dāng)前區(qū)和前版本區(qū)位于前兩個(gè)存儲(chǔ)區(qū),隨著軟件的更新而動(dòng)態(tài)交替變化。每次進(jìn)行軟件更新,把新的鏡像文件寫(xiě)入前版本區(qū),這樣當(dāng)前區(qū)就變成了前版本區(qū),前版本區(qū)則變成了當(dāng)前區(qū)。初版本區(qū)固定在第三個(gè)分區(qū),所存放的鏡像文件是嵌入式系統(tǒng)投入運(yùn)行時(shí)的最初程序,每次的軟件更新都不更改該存儲(chǔ)區(qū)的內(nèi)容。此外,在FLASH的高地址處設(shè)計(jì)一個(gè)參數(shù)存儲(chǔ)區(qū),用于存放需要固化的系統(tǒng)配置參數(shù)。更新程序需要用到啟動(dòng)點(diǎn)和更新位兩個(gè)配置參數(shù)。啟動(dòng)點(diǎn)用來(lái)指示bootloader需要從哪個(gè)存儲(chǔ)區(qū)加載鏡像文件,更新位用來(lái)指示系統(tǒng)進(jìn)行軟件更新的狀態(tài)。
3.2 更新任務(wù)的設(shè)計(jì)
在嵌入式Linux系統(tǒng)中,將更新該任務(wù)設(shè)計(jì)成一個(gè)阻塞在更新信號(hào)量上的進(jìn)程。系統(tǒng)每次啟動(dòng)后,更新進(jìn)程首先向后臺(tái)控制模塊報(bào)告當(dāng)前的軟件版本號(hào),隨后檢查FLASH上的更新位,然后進(jìn)入阻塞狀態(tài)。當(dāng)系統(tǒng)收到控制模塊發(fā)來(lái)的更新指令后,釋放更新信號(hào)量,更新進(jìn)程開(kāi)始進(jìn)行軟件更新。更新進(jìn)程采用TCP協(xié)議接收控制模塊發(fā)來(lái)的新程序鏡像文件??紤]到無(wú)線數(shù)據(jù)傳輸?shù)奶攸c(diǎn),為了增強(qiáng)傳輸可靠性,在應(yīng)用層設(shè)計(jì)一套具有校驗(yàn)、確認(rèn)和重傳功能的收發(fā)協(xié)議,以保證新鏡像文件的數(shù)據(jù)能夠準(zhǔn)確無(wú)誤的通過(guò)Internet和移動(dòng)通信系統(tǒng)傳輸?shù)角岸四K的內(nèi)存中。當(dāng)新鏡像文件下載完畢后,更新進(jìn)程先判斷前版本區(qū)在FLASH上的位置,然后調(diào)用FLASH的讀寫(xiě)函數(shù)將新鏡像文件寫(xiě)入前版本存儲(chǔ)區(qū)中。寫(xiě)完后將更新位置1,并更改啟動(dòng)點(diǎn)。如果當(dāng)前運(yùn)行的程序版本為最初版本,則將新鏡像文件同時(shí)寫(xiě)入前兩個(gè)存儲(chǔ)區(qū)。更新進(jìn)程的程序流程如圖3所示。
圖3 更新進(jìn)程流程圖
圖4 異常處理流程圖
3.3 更新后的啟動(dòng)流程
前端運(yùn)行模塊具有獨(dú)立的bootloader,并固化在FLASH存儲(chǔ)器的低地址處,系統(tǒng)啟動(dòng)后總是能夠進(jìn)入bootloader。Bootloader通過(guò)讀取參數(shù)存儲(chǔ)區(qū)的啟動(dòng)點(diǎn)參數(shù)來(lái)引導(dǎo)3個(gè)程序存儲(chǔ)區(qū)的某一個(gè)鏡像文件。在正常情況下,啟動(dòng)點(diǎn)參數(shù)總是指向當(dāng)前區(qū)。當(dāng)軟件更新后,啟動(dòng)點(diǎn)也隨之在存儲(chǔ)區(qū)1和存儲(chǔ)區(qū)2之間交替切換,指向新鏡像文件的存儲(chǔ)區(qū)。這樣,當(dāng)更新進(jìn)程重新啟動(dòng)前端模塊后,bootloader便會(huì)引導(dǎo)新的鏡像文件。
為了增強(qiáng)軟件更新后系統(tǒng)啟動(dòng)的可靠性,本機(jī)制利用ARM體系的異常來(lái)處理啟動(dòng)時(shí)的出錯(cuò)情況。在ARM體系結(jié)構(gòu)中有7種異常,與啟動(dòng)過(guò)程密切相關(guān)的異常有未定義指令、指令預(yù)取中止和數(shù)據(jù)訪問(wèn)中止3種。通過(guò)設(shè)計(jì)異常處理程序來(lái)加載備份存儲(chǔ)區(qū)的鏡像文件。當(dāng)bootloader引導(dǎo)新鏡像文件失敗后,進(jìn)入異常處理函數(shù),在此函數(shù)中將啟動(dòng)點(diǎn)更改為指向前版本區(qū),并把更新位置為2,表示已經(jīng)更改過(guò)兩次啟動(dòng)點(diǎn)。重啟系統(tǒng)后bootloader便會(huì)恢復(fù)引導(dǎo)上一版本的程序鏡像文件。由于軟件更新時(shí)只是在相鄰的存儲(chǔ)區(qū)寫(xiě)入了新鏡像文件,并未對(duì)上一版本程序的存儲(chǔ)區(qū)進(jìn)行任何操作,而且上一版本程序是更新前已經(jīng)正常啟動(dòng)運(yùn)行過(guò)的程序,所以一般情況下上一版本程序應(yīng)該能夠正常引導(dǎo)成功。如果由于意外干擾導(dǎo)致上一版本程序仍然無(wú)法啟動(dòng)成功,此時(shí)將再次進(jìn)入異常處理程函數(shù)。在函數(shù)中先讀取更新位的值,如果更新位為2則將啟動(dòng)點(diǎn)指向初版本區(qū),并把更新位置為3。重啟系統(tǒng)后bootloader便會(huì)引導(dǎo)最初版本的程序鏡像文件。最初版本的鏡像文件在前端模塊安裝后從未更改過(guò),并在安裝前進(jìn)行過(guò)驗(yàn)證測(cè)試,具有非常高的可靠性。當(dāng)新版本程序和上一版本程序都無(wú)法啟動(dòng)成功時(shí),系統(tǒng)嘗試啟動(dòng)最初版本的鏡像文件,以保證系統(tǒng)基本功能的正常運(yùn)行,并確保前端模塊與后臺(tái)控制模塊之間不會(huì)失去聯(lián)系。后臺(tái)控制模塊根據(jù)前端模塊啟動(dòng)后報(bào)告的版本號(hào)來(lái)獲知軟件更新的信息并采取相應(yīng)的措施。在異常處理函數(shù)中讀取啟動(dòng)點(diǎn)值的時(shí)候,如果讀取值異常或讀取出錯(cuò),則對(duì)啟動(dòng)點(diǎn)進(jìn)行修復(fù),異常處理函數(shù)的流程如圖4所示。通過(guò)利用啟動(dòng)點(diǎn)、更新位和異常處理程序,當(dāng)軟件更新過(guò)程中遇到了干擾和錯(cuò)誤時(shí),本機(jī)制能夠依次選擇啟動(dòng)兩個(gè)備份的軟件版本,有效地提高了軟件更新的可靠性,防止了“孤立系統(tǒng)”的出現(xiàn)。
4 測(cè)試結(jié)果[!--empirenews.page--]
在一個(gè)實(shí)際運(yùn)行的無(wú)線遠(yuǎn)程監(jiān)控系統(tǒng)中應(yīng)用本更新機(jī)制,以驗(yàn)證和測(cè)試其性能。首先對(duì)更新進(jìn)程的運(yùn)行效果進(jìn)行測(cè)試。結(jié)果表明,每次測(cè)試更新進(jìn)程均能正確的啟動(dòng)與控制模塊之間的數(shù)據(jù)傳輸,通過(guò)在應(yīng)用層引入確認(rèn)和重傳機(jī)制,新程序的鏡像文件均能通過(guò)Internet和無(wú)線網(wǎng)絡(luò)準(zhǔn)確的傳輸至前端運(yùn)行模塊。測(cè)試的重點(diǎn)是系統(tǒng)軟件更新完畢后新程序啟動(dòng)的可靠性。對(duì)軟件更新過(guò)程中遇到的干擾和數(shù)據(jù)錯(cuò)誤采取模擬的方式,以此測(cè)試bootloader能否正確的啟動(dòng)備份程序。測(cè)試中模擬了3類情況:一類是FLASH上的程序鏡像文件隨機(jī)的在某些地址處出現(xiàn)數(shù)據(jù)錯(cuò)誤,另一類是FLASH上的程序鏡像文件隨機(jī)的出現(xiàn)某些數(shù)據(jù)的地址錯(cuò)位,第三類是啟動(dòng)點(diǎn)的數(shù)值發(fā)生錯(cuò)誤。將這3類情況分為6種具體方案進(jìn)行測(cè)試,每個(gè)方案測(cè)試20次,查看系統(tǒng)能否按照期望的結(jié)果啟動(dòng)程序鏡像。測(cè)試方案及結(jié)果如表1所示。
從測(cè)試結(jié)果中可以看出,本更新機(jī)制對(duì)FLASH中的數(shù)據(jù)錯(cuò)誤識(shí)別效果最好,每次啟動(dòng)時(shí)均能正確地進(jìn)入異常并啟動(dòng)備份程序;對(duì)FLASH中的數(shù)據(jù)地址錯(cuò)位的識(shí)別率也達(dá)到了80%以上。當(dāng)程序的數(shù)據(jù)正確但存放地址錯(cuò)位時(shí),存在一定的概率會(huì)使得ARM處理器取出的指令是可以識(shí)別和執(zhí)行的,從而使程序運(yùn)行到未知狀態(tài)而導(dǎo)致系統(tǒng)無(wú)法啟動(dòng)。此外,更新機(jī)制對(duì)配置區(qū)具有較強(qiáng)的修復(fù)能力,防止了因?yàn)榕渲脜^(qū)數(shù)據(jù)出現(xiàn)錯(cuò)誤而導(dǎo)致無(wú)法啟動(dòng)的情況的發(fā)生。實(shí)驗(yàn)平臺(tái)的測(cè)試結(jié)果表明本更新機(jī)制能有效地提高嵌入式軟件更新后重新啟動(dòng)的穩(wěn)定性和可靠性,具有較強(qiáng)的自我恢復(fù)能力。
5 結(jié)語(yǔ)
本文以提高可靠性為設(shè)計(jì)目標(biāo),提出了一種基于bootloader的嵌入式軟件遠(yuǎn)程自動(dòng)更新機(jī)制。本更新機(jī)制由于同時(shí)保存了三個(gè)鏡像文件,因此需要更多的FLASH存儲(chǔ)空間,略微增加了嵌入式系統(tǒng)的硬件成本。但相對(duì)于更新機(jī)制的遠(yuǎn)程化、自動(dòng)化和可靠性所帶來(lái)的維護(hù)成本的巨大降低,這個(gè)代價(jià)是值得的。
本文主要?jiǎng)?chuàng)新點(diǎn):通過(guò)設(shè)置兩個(gè)備份程序存儲(chǔ)區(qū),利用嵌入式處理器的異常機(jī)制,使嵌入式系統(tǒng)的更新具有了較強(qiáng)的自我恢復(fù)能力,較大的提升嵌入式軟件更新過(guò)程的可靠性,尤其能夠有效地防止嵌入式系統(tǒng)更新后出現(xiàn)的系統(tǒng)啟動(dòng)失敗的情況,具有較高的實(shí)用價(jià)值。另外,通過(guò)CDMA系統(tǒng)實(shí)現(xiàn)遠(yuǎn)程自動(dòng)更新,可以擺脫地域限制,不受布線的束縛,提高了嵌入式系統(tǒng)遠(yuǎn)程更新的便捷性。