1. 程式人生 > >【swupdate文檔 一】嵌入式系統的軟件管理

【swupdate文檔 一】嵌入式系統的軟件管理

sin 串行 其他 什麽 裝載 選擇 通信問題 發送 一般來說

嵌入式系統的軟件管理

嵌入式系統變得越來越復雜, 它們的軟件也反映了這種復雜性的增加。
為了支持新的特性和修復,很有必要讓嵌入式系統上的軟件
能夠以絕對可靠的方式更新。
在基於linux的系統上,我們可以在大多數情況下找到以下元素:

  • 引導裝載程序
  • 內核和設備樹
  • 根文件系統
  • 其他在後續掛載的文件系統
  • 用戶資料,以裸數據格式存在或者保存在文件系統中
  • 特定用途的軟件. 如,用於下載到相連接的微控制器的固件等

一般來說,在大多數情況下是需要更新
內核和根文件系統,保存用戶數據-但實際情況各不相同。

僅在少數情況下,還需要更新引導加載程序,
事實上,更新引導加載程序總是很危險的, 因為更新中的失敗會破壞設備。

在某些情況下,從損壞狀態中恢復是可能的,
但這通常無法由最終用戶完成,即設備需要返廠維修。

關於軟件更新有很多不同的概念。我將解釋其中的一些概念,
然後解釋為什麽我實施了這個項目。

通過引導加載程序完成更新

引導加載程序所做的工作遠不止啟動內核那麽簡單。
它們有自己的shell,且可以使用處理器的外圍設備
進行管理,在大多數情況下是通過串行通訊。 它們通常是可執行腳本的,這使得
實現某種軟件更新機制成為了可能。

然而,我發現這種方法有一些缺點,
這讓我另行尋找基於運行在Linux上的應用程序的解決方案。

引導加載程序對外圍設備的使用有局限性

並不是所有內核中支持的設備都可以在引導加載程序使用。

向內核添加設備支持是有意義的,因為這可以讓外圍設備對主應用程序可用,
但將驅動程序移植到引導加載程序中,就並不總是有意義的了。

引導加載程序的驅動程序不會被更新

引導加載程序的驅動程序大多是從Linux內核移植過來的,
但是由於經過調整的原因,它們以後不會被修復或與內核同步,
而bug修復則會定期在Linux內核中進行。

一些外圍設備可能以不可靠的方式工作,
並且修復問題可能並不容易。引導加載程序中的驅動程序
或多或少是內核中相應驅動程序的復刻(fork)。

例如,用於NAND設備的UBI/UBIFS在內核中包含
了許多修復程序,這些修復程序並沒有移植回引導加載程序。

USB協議棧也可以找到相同的情況。支持新外圍設備或協議的工作,

在內核中進行得更好,而不是在引導加載程序中。

簡化版的文件系統

支持的文件系統的數量是有限的。
將文件系統支持移植到引導加載程序需要付出很大的努力。

網絡支持有限

網絡協議棧是有限的,通常通過一個更新只能通過 UDP但不能通過TCP完成。

與操作人員交互

很難將接口暴露給操作員, 比如瀏覽器中的GUI或顯示器上的GUI。

比起在引導加載程序中,復雜的邏輯可以在應用程序內部更容易實現。
擴展引導加載程序是復雜的,因為所有的服務和庫都不可用。

引導加載程序更新的優點

然而,這種方法也有一些優點:

-更新軟件通常更簡單。
-占用空間更小:即使是一個僅用於軟件管理的獨立應用程序
也需要自己的內核和根文件系統。即使它們的大小能夠被裁剪,
將更新軟件不需要的部分去掉,它們的大小也是不可忽略的。

通過包管理器更新

所有的Linux發行版都使用包管理器做更新, 為什麽這不適用於嵌入式系統?

我不能說它不能被使用,但是使用這種方法有一個重要的缺點。
嵌入式系統是使用特定的軟件進行過良好測試的。
使用包管理器可能會讓人覺得奇怪,因為軟件本身不再是 原子的
而是分裂成一系列包。
我們怎樣才能保證一個能基於庫版本x.y正常工作的應用程序,
同樣也能基於同一個庫的不同版本工作呢?如何才能成功地做好測試?

對於制造商來說,通常更好的說法是發布了一個新的軟件版本
(經過測試工程師的良好測試),並且可以更新新的軟件(或固件)。
對測試人員來說,在包中進行拆分可能會產生噩夢和巨大的工作量。

簡單地替換單個文件可以加快開發速度,
但是對於客戶站點來說,這是一個軟件版本的噩夢。
如果客戶報告了一個bug,那麽在之前已經向客戶發送過
一些文件的補丁時,軟件怎麽可能還算是“2.5版本”呢?

原子更新通常是嵌入式系統的必備特性。

應用程序進行軟件升級的策略

應用程序也可以用於升級系統,而不是使用引導加載程序。
應用程序可以使用操作系統提供的所有服務。
建議的解決方案是一個獨立的軟件,
它遵循客戶規則,執行檢查以確定軟件是否可安裝,
然後將軟件安裝到所需的存儲上。

應用程序可以檢測所提供的新軟件是否適合硬件,
也可以檢查軟件是否由經過驗證的權威機構發布。
支持的特性範圍可以從小型系統擴展到復雜系統,
包括安裝前和安裝後腳本等等。

根據系統的資源,可以使用不同的策略。 下面我將列出其中一些。

雙備份系統 - 支持回退

如果存儲空間足夠保存整個軟件的兩個副本,
那麽即使軟件更新被中斷或斷電,也可以保證始終有一個可用的副本。

每個副本必須包含內核、根文件系統和每個可以更新的組件。
需要一種機制來識別正在運行的版本。

SWUpdate應該集成到應用程序軟件中, 當需要更新時,應用程序軟件將觸發它。
SWUpdate的職責是更新備用副本, 不修改正在運行的軟件副本。

與引導加載程序的協作通常是必要的,
因為引導加載程序必須決定應該啟動哪個副本。
同樣,必須能夠在兩個副本之間進行切換。

重新啟動後,引導加載程序決定應該運行哪個副本。

技術分享圖片

請參閱有關引導加載程序的章節,
了解可以實現哪些機制來確保更新後目標不會被破壞。

最明顯的缺點是所需的空間量。 每個副本的可用空間小於存儲空間的一半。
然而,即使在斷電的情況下,更新也總是安全的。

這個項目支持這個策略。
作為該項目一部分的應用程序應該安裝在根文件系統中,
並根據需要啟動或觸發。不需要額外的內核,
因為這兩個副本保證總是可以升級不運行的副本。

SWUpdate將設置bootloader變量以通知新映像已成功安裝。

單系統 - 以獨立鏡像形式運行

軟件升級應用程序由內核(可裁剪掉不必要的驅動等)
和一個小的根文件系統以及應用程序及其庫組成。
整個大小遠遠小於系統軟件的一個副本。
根據設置,這個獨立根文件系統的大小從 2.5MB 到 8MB 不等。
如果說大小對於小型系統非常重要,
那麽對於具有大量存儲或大容量NAND的系統, 其大小則可以忽略不計。

系統可以進入 "升級" 模式,只需向引導加載程序發出必須啟動升級軟件的信號。
具體方法可能有所不同,例如設置引導加載程序環境或使用和外部GPIO。

引導加載程序啟動“SWUpdate”,
引導SWUpdate內核並將initrd映像作為根文件系統。
因為它在RAM中運行,所以可以升級整個存儲。
與雙拷貝策略不同,系統必須重新啟動以將其自身置於更新模式。

這個方案比起使用兩個副本,占用的存儲空間更少,
但是它不能保證在不再次更新軟件的情況下進行回退。
不過,至少它可以保證,當主應用不存在或損壞時,
以及當升級過程由於某種原因而中斷時,系統自動進入升級模式。

技術分享圖片

事實上,可以將升級過程視為事務,
只有成功升級後,新軟件才設置為“可引導”。
考慮到這些因素,使用此策略進行升級是安全的: 如果舊軟件損壞或無法運行,
始終確保系統啟動並準備好獲得新軟件。

使用U-Boot作為引導加載程序, SWUpdate能夠管理U-Boot的環境設置變量,
以指示事務的開始和結束,以及包含有效的軟件的存儲區域。
針對GRUB環境塊修改和EFI引導保護的類似特性也已被引入。

SWUpdate主要以如下配置的方式使用。
Yocto生成包含SWUpdate應用程序的initrd映像,
該映像在掛載根文件系統之後自動啟動。

技術分享圖片

有些事情出錯了 ?

許多事情都可能出錯,必須保證系統能夠再次運行,
並且可能能夠重新加載新的軟件來修復損壞的映像。
SWUpdate與引導加載程序一起工作,以識別失敗的可能原因。
目前支持U-Boot、GRUB和EFI引導保護。

我們至少可以列出一些常見的原因:

-安裝過程中鏡像損壞。
: SWUpdate能夠識別它,並且更新過程會被中止。
舊的軟件被保存下來,沒有任何東西被真正復制到目標的存儲中

  • 存儲(flash)中損壞的鏡像
  • 遠程更新由於通信問題而中斷
  • 意外掉電

SWUpdate的工作流程是事務性的。引導加載程序的環境變量“recovery_status”
被設置為向引導加載程序發出更新狀態的信號。
當然,還可以添加更多變量,用於微調和報告錯誤原因。
recovery_status可以取值為“progress”,“failed”,或者它也可以被取消設置。

當SWUpdate啟動時,它將recovery_status設置為“progress”。
更新成功完成後,變量將被刪除。如果更新以錯誤結束,
recovery_status的值為“failed”。

當更新被中斷時,不管什麽原因,引導加載程序都能識別到,
因為recovery_status變量處於“progress”或“failed”狀態。
然後,引導加載程序可以再次啟動SWUpdate,以再次
加載軟件(單副本情況)或運行應用程序的舊副本(雙副本情況)。

意外掉電

如果發生斷電,必須保證系統能夠再次工作 —— 重新
啟動SWUpdate或恢復軟件的舊副本。

一般情況下,行為可以根據所選擇的場景進行劃分:

  • 單拷貝:SWUpdate被中斷,更新事務沒有以成功結束。
    引導加載程序能夠再次啟動SWUpdate,從而有可能再次更新軟件。

  • 雙拷貝:SWUpdate沒有在備份系統和當前系統之間做切換。
    當前版本的軟件,並沒有被更新觸及到,會再次啟動。

為了完全安全,SWUpdate和引導加載程序需要交換一些信息。
引導加載程序必須檢測更新是否由於斷電而中斷,
並重新啟動SWUpdate,直到更新成功。

SWUpdate支持U-Boot、GRUB和EFI Boot Guard引導加載程序。 U-Boot和EFI Boot
Guard有用於保證掉電安全的環境變量,
SWUpdate能夠讀取和更改這些變量,以此與引導加載程序通信。
對於GRUB,則使用固定的1024字節環境變量塊文件。
SWUpdate在開始更新系統時設置一個變量作為標誌,
並在完成之後重置同一變量。引導加載程序可以讀取此標誌,
以檢查在上次關機之前是否正在運行更新。

技術分享圖片

升級SWUpdate本身會如何?

SWUpdate被認為用於整個開發過程,代替定制過程以在開發過程中更新軟件。
在投產前,SWUpdate被針對這個項目進行過很好的測試。

如果SWUpdate本身應該被更新,那麽當存儲中只有一個SWUpdate副本時,
更新就不是安全的。只有當SWUpdate擁有兩個副本時,才能保證安全更新。

如果SWUpdate是升級映像的一部分,則有一些方法可以避免這個問題:

  • 有兩份SWUpdate
  • 承擔風險,但準備一個在引導加載程序中可使用的救援程序。

升級引導加載程序會如何?

更新引導加載程序在大多數情況下無法做到的。
在大多數SOC上,不存在多個引導加載程序的副本,
當引導加載程序被破壞時,板子就無法引導啟動了。

一些soc允許擁有多個引導加載程序副本。
但同樣,沒有通用的解決方案,因為它是 非常 特定於硬件的。

根據我的經驗,大多數產品不允許更新引導加載程序。
當產品準備好量產時,還必須要更新引導加載程序,這種情況是非常少見的。

以上結論不適用於更新U-Boot環境變量,這是一種常見的情況。
U-Boot提供整個環境變量的兩個副本,從SWUpdate中更新環境是
掉電安全的。其他引導加載程序則不一定具有此功能。

註:

本文地址 https://www.cnblogs.com/zqb-all/p/10090280.html

譯自 swupdate 文檔 https://sbabic.github.io/swupdate/overview.html

有更新會在github上發布 https://zqb-all.github.io/swupdate/overview.html

【swupdate文檔 一】嵌入式系統的軟件管理