孫伶俐 張睿 方峰 李露銘 喬梁
(1 中國空間技術研究院衛星應用總體部,北京 100094)(2 北京空間飛行器總體設計部,北京 100094)
星載計算機是衛星上的嵌入式計算設備,隨著衛星功能復雜程度的增加,衛星上裝備了越來越多的計算機,如控制計算機[1]、星務計算機[2-3]和星載路由器。星載軟件是運行在星載計算機上的嵌入式軟件,其存儲和運行介質包括ROM(如PROM、FLASH、EEPROM等)和RAM(也叫內存,如SRAM等)。星載軟件是完成衛星大部分功能的保障,其可靠安全的運行對衛星在軌運行至關重要。然而,空間環境單粒子翻轉問題,造成軟件運行所依賴的內存經常發生單比特、雙比特錯誤。據2020年上半年統計數據,北斗二號中地球軌道(MEO)衛星某星載計算機平均發生5次單比特錯誤恢復事件。空間環境造成的異常,嚴重時會造成內存的部分地址發生損壞[4-5],如2015年9月某遙感衛星在軌發生計算單元切機動作,經分析,最終問題定位于空間環境效應造成內存區域性損壞。內存部分地址失效,導致星載軟件無法運行,經多次“狗咬”復位后系統自動切換至備份計算機工作[6]。盡管是內存的一小塊區域發生故障,但實際造成了星載計算機單份失效,嚴重時會影響衛星在軌壽命,致使衛星不能完成任務期內的既定工作,最終造成無法挽回的損失。
目前,針對空間環境引發星載計算機內存故障的容錯方案主要有以下3種,即產品級容錯、硬件級容錯和軟件級容錯。產品級容錯[7]沒有對內存故障進行針對性設計,僅依賴星載計算機主備份硬件設計,主備份硬件通過“狗咬”的方式進行切換。硬件級容錯主要對內存芯片進行冗余備份設計,如1片SRAM芯片空間為2 MByte,計算機共使用4 MByte,則在CPU板上布3片SRAM,其中1片作為備份使用,通過切換片選信號的方式,將健康的SRAM通過組合,使得內存物理空間保持不變。軟件級容錯主要是在ROM中存儲多份程序,這些程序的功能可以相同,也可以不同[8],但最重要的是在編譯鏈接時使用內存不同的地址空間,以期在某區域內存損壞時ROM中存在不使用該區域內存的程序版本??梢?,目前針對內存故障的容錯設計最大的特點就是冗余備份,通過冗余備份產品、多個芯片、多份軟件來應對內存故障。無論采用何種冗余備份策略都需要增加資源消耗,如增加電路板數量、功能電路或芯片。
一般的星載計算機上都裝載有一個最小模式軟件,也叫在軌維護軟件或引導維護軟件[9],該軟件在使用最少的外設資源情況下可以對在軌運行的星載軟件進行修改、替換等維護工作。例如:星載計算機的某個物理接口在軌發生損壞,可通過最小模式軟件修改星載軟件功能,對故障進行隔離、替換等恢復設計,進而保證航天器在軌功能完整。然而,當內存部分地址損壞時,極有可能造成最小模式軟件也無法正常運行,因此本文選擇最小模式軟件作為設計對象。之所以不是直接針對星務軟件或控制軟件等業務軟件,是因為本身業務軟件邏輯較為復雜,體量較大,內存故障時被損壞的區域大小是隨機的,導致業務軟件有可能不容易找到連續的大片空間支持其運行,此時,所需內存資源越少的軟件其生存概率越大。綜上,本文從軟件編譯鏈接和內存地址的關系角度出發,對星載最小模式軟件提出了一種支持地址重定向的軟件方案。該方案采用軟件構件的思想,將最小模式軟件的全局屬性打包封裝,通過構件實例化的過程將原來軟件編譯鏈接后使用的物理地址轉變為邏輯地址,從而實現動態地址映射,使得軟件可以動態適應發生故障的內存區域,在啟動運行后不受任何影響。
目前,應對內存區域故障的方案,其中產品級容錯方案成本最高,代價最大,軟件級代價最小,但只能降低故障影響系統的概率,不能百分之百隔離故障。這是因為衛星在軌運行時,內存發生故障的區域是隨機的,不可預期的,若軟件不能自主地跳過故障區域,就無法有效地排除此類故障。本文方案是一種軟件級容錯方案,其和傳統方案相比,最大的特點在于軟件可以運行在內存區域的任何物理地址上,因此可以適應隨機的內存區域故障,僅要求內存故障發生后,內存物理空間仍然存在大小符合軟件使用要求的健康連續空間。其核心思想是:在不改變編譯鏈接環境的條件下,利用面向對象封裝、實例化的思想,將軟件編碼過程中定義的全局屬性(全局變量)進行封裝,變為構件的屬性;然后,通過實例化的思想將構件實例化,其實例化的起始地址為通過內存健康檢查找到的連續健康內存空間的首地址,這樣就實現了軟件動態內存地址映射的過程,使得軟件和內存物理地址完全脫離。
1.2.1 程序地址空間分配
一般地,星載軟件的地址空間劃分為代碼段、數據段、以符號開始的塊(BSS)段、堆空間、棧空間5段結構[10],如圖1所示。其中:代碼段可以置于ROM空間和RAM空間中,除代碼段外,其他一般都指定到RAM空間中。代碼段、數據段和BSS段在鏈接時確定起始地址,堆空間和??臻g都是根據剩余的空閑內存空間指定和分配的。本文方案中,為了規避內存損壞的風險,將代碼段的地址空間分配在ROM空間中,一般星載計算機都會配置PROM存儲最小模式軟件,PROM抗輻射指標較RAM高很多,因此將代碼段地址空間置于PROM中。
對于數據段和BSS段,一般位于RAM空間中,程序中對位于這兩個段的變量采用物理地址進行訪問,本文方案中,將數據段分為常量和變量兩部分。常量部分置于ROM中,因為其值不會被程序修改;變量部分和BSS段全部被封裝成程序構件的屬性。堆空間和棧空間的起始地址本身就是動態分配的,因此仍然位于RAM中。本文方案的地址空間布局如圖2所示。

圖1 星載軟件地址空間劃分Fig.1 On-board software address space division

圖2 地址空間分配Fig.2 Address space distribution
1.2.2 啟動時健康內存檢查
由于程序啟動時在內存健康檢查之前不能確定是否使用內存,此時不能使用C語言編寫內存健康檢查程序(因為函數調用需要使用堆棧),因此內存健康檢查程序只能使用匯編語言編寫,上電整個程序啟動運行,完成CPU初始化后運行內存健康檢查。檢測過程比較簡單,從內存起始地址開始檢測,尋找一段連續的足夠程序使用的地址空間。如程序需要使用128 Kbyte空間,則從起始地址開始的128 Kbyte空間分別寫入0x55555555和0xAAAAAAAA特征碼并讀取進行判斷,當該空間檢測正確后,將該空間的內存刷為0,并將本次檢測正確空間的起始地址保存在全局寄存器中。如果該空間某個地址出現錯誤,則跳過該錯誤地址,從下一個1 Kbyte對齊的地址開始,繼續檢測128 Kbyte的空間。如此循環,直到找到一段連續的正確的128 Kbyte空間,當檢測起始地址加檢測長度超出了RAM的最大地址時,表示無法提供足夠的健康內存供最小模式程序使用,此時程序需要進入死循環等待狗咬切機。檢測流程如圖3所示。
經過健康檢查獲得的內存首地址非常重要,是本文方案的關鍵。該地址需要存儲在CPU的某個空閑寄存器中(可以是內部寄存器,也可以是接口類寄存器),一旦選取了存儲該地址的寄存器,該寄存器就成為了保存這個地址的專用寄存器,需要確保在最小模式軟件中不會用到這個寄存器。本文后續示例選用SPARC系列處理器BM3803的%g7寄存器,文獻[10]中寄存器%g5~%g7是保留使用,因此可以確保編譯器在程序編譯時不會使用該寄存器。本文給出的所有存儲空間地址、寄存器定義等示例均以BM3803處理器為例。健康檢查后的內存塊首地址存入選定的寄存器,尾地址寫入堆棧指針。

圖3 內存檢測流程Fig.3 Memory detection flow
1.2.3 程序全局屬性構件化及實例化
本文采用面向對象的思想,將原來程序中的全局變量進行封裝,并設計發布構件的訪問接口和構件初始化接口,具體過程如下。
(1)封裝全局屬性。將原來軟件代碼中所有的全局屬性(會發生變化的變量,包括有初值(位于原數據段)和無初值(位于原BSS段)的變量),如全局變量、全局數組、全局指針、全局結構體實例等均封裝成一個構件的屬性。例如:定義為struct AppComponent,其中包含n個屬性,如32 bit整型變量a、單精度浮點變量b、雙精度浮點變量c、無符號整型指針變量d和無符號整型數組e(100個元素)等。
(2)發布構件訪問接口。通過該接口獲得內存健康檢查得到的可用內存首地址。通過該接口將定義的構件實例化,也就是完成地址重定向,使用時只需要定義一個程序構件AppComponent類型的指針ptrAppComponent,并將其指向一段連續的內存空間(空間大小需要大于程序構件AppComponent的大小)。這里指向的內存空間是星載最小模式軟件啟動后通過健康檢查的內存塊,就像編寫C語言時定義了一個指針,為指針分配空間時使用new操作,new操作返回的空間首地址就是通過健康檢查的內存塊的首地址。通過程序構件指針,就可以訪問構件中封裝的所有全局屬性。
(3)設計程序構件初始化接口。(1)中a,b,c,d是有初值要求的,需要在初始化接口中對其進行初始賦值操作。該接口需要在程序主體運行之前被調用,實現程序構件的初始化功能。這樣,原來程序編碼時在函數體外定義的全局有初值變量,通過初始化接口完成初值的賦值操作。該接口需要在調用主程序main函數之前被調用,確保調用功能函數之前完成全局屬性的初始化工作。
1.2.4 運行時內存健康檢查
本文方案需要在最小模式軟件運行時對全部內存進行健康檢查,并給出詳細的檢查結果,這樣地面才可以針對故障的部分進行有針對性的軟件設計,采用跳躍、隔離等方法避免軟件訪問故障內存區域。否則,地面沒有內存故障區域的詳細信息,很難分析出故障的具體地址范圍,也就無法進行針對性的軟件設計。檢查時需要跳過程序運行使用的內存,該部分內存在程序啟動時已經檢查過,可以確保軟件能夠正常使用。
測試目標機使用星載計算機,處理器為BM3803,內存為8 Mbyte(4片SRAM芯片,每片2 Mbyte)。由于無法物理模擬芯片內部區域損壞情況,測試時采用斷開第1片SRAM的片選信號CS1,這樣原內存空間0x40000000~0x407FFFFF中,0x40000000~0x401FFFFF的地址全部無法正常訪問。經測試,全局構件首地址自動從0x40000000調整至0x40200000,完整跳過了第1片SRAM的地址空間,其功能得以穩定運行。圖4是運行效果示意。

圖4 運行效果示意Fig.4 Operation effect diagram
性能方面,在每個需要使用全局屬性的函數起始處,都需要首先調用構件訪問接口,以獲得全局構件首地址。根據SPARC編譯器反匯編出的程序進行分析,調用該接口占用4條匯編語句。另外,對全局屬性的訪問相較原來都變為了指針訪問的方式;從反匯編可以看出,每次訪問變量都需要先獲取指針,再訪問對應變量,這樣每個全局變量的訪問較原來都增加了2條匯編語句??傮w上來看,經過編譯后的機器碼存儲占用空間較原來增加不足5%(不同編程風格變化不同)。在運算速度上,將代碼放置在ROM中運行,速度較在RAM中運行下降較多,但最小模式軟件功能較為簡單,運算速度下降對軟件功能幾乎沒有影響。另外,由機器碼增多帶來的運行速度下降幾乎可以忽略。
從效果上分析,采用本文方案實現的星載最小模式軟件,以4096 Kbyte內存為例,使用128 Kbyte連續空間,以1 Kbyte為最小劃分,按照本文設計的程序,可以有3968種不同的啟動地址,較多分區等設計中僅能存放個位數的不同版本的最小模式軟件,大幅提升了生存能力。
為了能夠使本文提出的軟件方案發揮最大功效,對硬件設計提出以下建議。
(1)內存芯片盡量使用多片構成運行空間,而不是選擇容量大的1片,避免整片失效后造成運行空間全部無法使用的情況。
(2)多片內存采用字擴展,而不是位擴展設計,避免某片失效,造成運行空間間隔故障,間隔的寬度是該片內存的位寬,這樣整個運行空間也是無法使用的。
需要說明的是,即使星載計算機采用本文方案,也不是萬無一失的。因為即便在內存大部分損壞的極端情況下,最小模式軟件能夠生存,不代表剩余空間能夠維持業務軟件運行。因此在硬件設計時,內存芯片的數量及內存空間的余量需要進行針對性設計,這樣才可以發揮本文方案的最大效能,確保系統可靠性。
本文設計了一種支持內存區域故障自適應的星載最小模式軟件方案,使用軟件構件技術,利用嵌入式軟件編譯鏈接的規則,使軟件具備在內存某個地址或某區域地址的物理損壞場景下仍可以正常運行的能力。采用本文方案開發的最小模式軟件,成本低,效率高,可靠性強,可大幅提高軟件在SRAM部分損壞場景下的生存幾率,進而提高星載計算機在軌應用的可靠性。采用該方案的最小模式軟件已經在北斗三號多個軌道的20多顆衛星上得到應用,為北斗三號在軌10~12年的設計壽命提供了重要保障。