基于Bootloader的可靠嵌入式軟件遠程更新機制
1 隨著嵌入式系統(tǒng)在各個領域的廣泛應用,嵌入式軟件的維護變得日益重要[1]。嵌入式系統(tǒng)投入實際環(huán)境中運行后,一部分在軟件開發(fā)過程中無法充分測試的錯誤便會暴露出來;在嵌入式系統(tǒng)的運行期內(nèi),用戶也往往會對嵌入式軟件提出新的功能要求和性能要求。因此,嵌入式軟件的更新逐漸成為嵌入式系統(tǒng)實際應用的一個重要問題。當嵌入式系統(tǒng)安裝數(shù)量較多,或安裝位置不方便的情況下,采用人工更新方式會花費較大的人力和物力。遠程自動更新則在嵌入式系統(tǒng)中設計一個有線或無線的通信接口,在異地采用遠程通信的方式實現(xiàn)嵌入式軟件的自動更新。該方式能有效地降低嵌入式軟件的更新和維護成本,因此受到了廣泛的關注。當前對嵌入式軟件遠程自更新技術的研究主要停留在更新方法的設計上,對如何確保更新過程的可靠性還沒有深入的研究。更新的可靠性主要受兩個方面的影響:一是更新數(shù)據(jù)遠程傳輸?shù)?a class="contentlabel" href="http://www.ex-cimer.com/news/listbylabel/label/可靠">可靠性;另一方面是系統(tǒng)更新后啟動的可靠性。在采用嵌入式Linux、Windows CE等較為復雜的操作系統(tǒng)時,一般設計一個獨立的bootloader程序[2][3],對系統(tǒng)進行初始化并引導嵌入式操作系統(tǒng)。這種結構的嵌入式系統(tǒng)的啟動與bootloader緊密相關。本文針對采用bootloader的嵌入式系統(tǒng),提出了一種高可靠的嵌入式軟件遠程自動更新機制,并以基于ARM微處理器[4]、嵌入式Linux操作系統(tǒng)[5]和無線通信接口的嵌入式系統(tǒng)為例進行了軟硬件設計。然后將更新機制應用到實際系統(tǒng)中進行測試,最后給出了本文的結論。
本文引用地址:http://www.ex-cimer.com/article/152617.htm2 更新系統(tǒng)的總體結構
本部分以ARM和嵌入式Linux操作系統(tǒng)為例,介紹遠程自更新系統(tǒng)的整體結構。支持遠程自更新的嵌入式系統(tǒng)可以劃分為前端運行模塊和后臺控制模塊兩部分。前端運行模塊采用基于ARM9核心的S3C2410微處理器,最高主頻可達200Mhz,配有8M的RAM和32M的FLASH存儲器,運行ARM-Linux嵌入式操作系統(tǒng),具有獨立設計的bootloader程序。后臺控制模塊用于實現(xiàn)對前端運行模塊的遠程異地控制,是系統(tǒng)的控制核心。前端運行模塊通過無線模塊BCM860接入到CDMA2000-1X無線通信系統(tǒng),繼而連接到Internet。CDMA2000-1X是第2.5代移動通信系統(tǒng),支持較高速率的數(shù)據(jù)分組業(yè)務。后臺控制模塊采用有線方式直接與Internet相連接,與前臺運行模塊之間進行標準的基于TCP/IP協(xié)議的通信。狀態(tài)信息、控制信息和更新文件都在這一數(shù)據(jù)鏈路上進行傳輸。
圖1 系統(tǒng)結構
3 更新系統(tǒng)的軟件設計
3.1 Flash存儲器的布局
傳統(tǒng)的采用Linux的嵌入式系統(tǒng)的FLASH存儲器的布局如圖2(a)所示。為了敘述方便,我們將Linux內(nèi)核和文件系統(tǒng)合并稱為Linux鏡像文件。系統(tǒng)進行軟件更新時,先把新鏡像文件下載到內(nèi)存中,然后燒寫到FLASH的鏡像文件存儲區(qū),覆蓋舊的鏡像文件。該方法沒有考慮更新過程中可能遇到的干擾。如果在更新中因為突發(fā)的干擾出現(xiàn)更新數(shù)據(jù)錯誤或燒寫錯誤,就可能導致軟件更新后bootloader無法啟動新的鏡像文件,前端模塊無法運行,并失去了與后臺控制中心的聯(lián)系,成為“孤立系統(tǒng)”。這種情況發(fā)生后只能到前端系統(tǒng)的安裝地點進行人工處理,從而導致花費較大的代價。
圖2 (a) 傳統(tǒng)的FLASH布局 (b) 自更新系統(tǒng)的FLASH布局
為了提高軟件更新的可靠性,本機制對FLASH存儲器的布局進行了重新設計,如圖2(b)所示。Bootloader存儲區(qū)后面設計了3個鏡像文件存儲區(qū)。其中一個存儲區(qū)用于存放當前要啟動的最新的鏡像文件,稱為當前區(qū);另一個存儲區(qū)用于存放上一版本的鏡像文件,稱為前版本區(qū);剩下一個存儲區(qū)用于存放最初版本的鏡像文件,稱為初版本區(qū)。當前區(qū)和前版本區(qū)位于前兩個存儲區(qū),隨著軟件的更新而動態(tài)交替變化。每次進行軟件更新,把新的鏡像文件寫入前版本區(qū),這樣當前區(qū)就變成了前版本區(qū),前版本區(qū)則變成了當前區(qū)。初版本區(qū)固定在第三個分區(qū),所存放的鏡像文件是嵌入式系統(tǒng)投入運行時的最初程序,每次的軟件更新都不更改該存儲區(qū)的內(nèi)容。此外,在FLASH的高地址處設計一個參數(shù)存儲區(qū),用于存放需要固化的系統(tǒng)配置參數(shù)。更新程序需要用到啟動點和更新位兩個配置參數(shù)。啟動點用來指示bootloader需要從哪個存儲區(qū)加載鏡像文件,更新位用來指示系統(tǒng)進行軟件更新的狀態(tài)。
3.2 更新任務的設計
在嵌入式Linux系統(tǒng)中,將更新該任務設計成一個阻塞在更新信號量上的進程。系統(tǒng)每次啟動后,更新進程首先向后臺控制模塊報告當前的軟件版本號,隨后檢查FLASH上的更新位,然后進入阻塞狀態(tài)。當系統(tǒng)收到控制模塊發(fā)來的更新指令后,釋放更新信號量,更新進程開始進行軟件更新。更新進程采用TCP協(xié)議接收控制模塊發(fā)來的新程序鏡像文件??紤]到無線數(shù)據(jù)傳輸?shù)奶攸c,為了增強傳輸可靠性,在應用層設計一套具有校驗、確認和重傳功能的收發(fā)協(xié)議,以保證新鏡像文件的數(shù)據(jù)能夠準確無誤的通過Internet和移動通信系統(tǒng)傳輸?shù)角岸四K的內(nèi)存中。當新鏡像文件下載完畢后,更新進程先判斷前版本區(qū)在FLASH上的位置,然后調用FLASH的讀寫函數(shù)將新鏡像文件寫入前版本存儲區(qū)中。寫完后將更新位置1,并更改啟動點。如果當前運行的程序版本為最初版本,則將新鏡像文件同時寫入前兩個存儲區(qū)。更新進程的程序流程如圖3所示。
圖3 更新進程流程圖
圖4 異常處理流程圖
3.3 更新后的啟動流程
前端運行模塊具有獨立的bootloader,并固化在FLASH存儲器的低地址處,系統(tǒng)啟動后總是能夠進入bootloader。Bootloader通過讀取參數(shù)存儲區(qū)的啟動點參數(shù)來引導3個程序存儲區(qū)的某一個鏡像文件。在正常情況下,啟動點參數(shù)總是指向當前區(qū)。當軟件更新后,啟動點也隨之在存儲區(qū)1和存儲區(qū)2之間交替切換,指向新鏡像文件的存儲區(qū)。這樣,當更新進程重新啟動前端模塊后,bootloader便會引導新的鏡像文件。
為了增強軟件更新后系統(tǒng)啟動的可靠性,本機制利用ARM體系的異常來處理啟動時的出錯情況。在ARM體系結構中有7種異常,與啟動過程密切相關的異常有未定義指令、指令預取中止和數(shù)據(jù)訪問中止3種。通過設計異常處理程序來加載備份存儲區(qū)的鏡像文件。當bootloader引導新鏡像文件失敗后,進入異常處理函數(shù),在此函數(shù)中將啟動點更改為指向前版本區(qū),并把更新位置為2,表示已經(jīng)更改過兩次啟動點。重啟系統(tǒng)后bootloader便會恢復引導上一版本的程序鏡像文件。由于軟件更新時只是在相鄰的存儲區(qū)寫入了新鏡像文件,并未對上一版本程序的存儲區(qū)進行任何操作,而且上一版本程序是更新前已經(jīng)正常啟動運行過的程序,所以一般情況下上一版本程序應該能夠正常引導成功。如果由于意外干擾導致上一版本程序仍然無法啟動成功,此時將再次進入異常處理程函數(shù)。在函數(shù)中先讀取更新位的值,如果更新位為2則將啟動點指向初版本區(qū),并把更新位置為3。重啟系統(tǒng)后bootloader便會引導最初版本的程序鏡像文件。最初版本的鏡像文件在前端模塊安裝后從未更改過,并在安裝前進行過驗證測試,具有非常高的可靠性。當新版本程序和上一版本程序都無法啟動成功時,系統(tǒng)嘗試啟動最初版本的鏡像文件,以保證系統(tǒng)基本功能的正常運行,并確保前端模塊與后臺控制模塊之間不會失去聯(lián)系。后臺控制模塊根據(jù)前端模塊啟動后報告的版本號來獲知軟件更新的信息并采取相應的措施。在異常處理函數(shù)中讀取啟動點值的時候,如果讀取值異常或讀取出錯,則對啟動點進行修復,異常處理函數(shù)的流程如圖4所示。通過利用啟動點、更新位和異常處理程序,當軟件更新過程中遇到了干擾和錯誤時,本機制能夠依次選擇啟動兩個備份的軟件版本,有效地提高了軟件更新的可靠性,防止了“孤立系統(tǒng)”的出現(xiàn)。
4 測試結果
linux操作系統(tǒng)文章專題:linux操作系統(tǒng)詳解(linux不再難懂)
評論