張梅娟,張明月,楊楚瑋,朱心杰
(中國電子科技集團公司第五十八研究所,江蘇無錫 214035)
近年來,隨著移動設備的爆發(fā)式需求以及信息化產業(yè)的推動,帶來了巨大的電子信息類產品的功能和服務需求[1]。嵌入式處理器作為移動設備的心臟,其應用場景更加豐富的同時,對其各項指標也提出了新的需求[2-3],這也對嵌入式處理器的集成電路設計提出了新的挑戰(zhàn)。集成電路的設計為了更加完美地滿足以上需求,需要有更多的設計思考以及更豐富的驗證方法,而作為處理器關鍵組成部分的RomCode 亦如此[4]。
RomCode 在芯片上電復位后運行,其核心目標是使得處理器可正常加載、運行位于外部存儲介質中的用戶級程序[5-6]?,F(xiàn)代處理器的基本技術指標是多核特性,基于多級Cache 結構,在硬件層面提高CPU 指令的執(zhí)行、調度效率[7],而RomCode 作為處理器的一部分必須要支持處理器多核啟動功能。
由于ARM 內核具有高性能、低功耗、高可靠性、定制性強以及生態(tài)完整等特點,已成為嵌入式領域處理器SoC 芯片的不二之選[8]。該文提出的基于ARM 多核處理器SoC 芯片的RomCode,可對芯片上電后的時鐘進行管理,同時具備從芯片外接的TF卡、SD卡、emmc 等存儲介質中加載用戶級程序,支持常見的多核操作系統(tǒng),如Linux、Vxworks 等。同時,為了保證集成電路設計階段RomCode 設計的正確性,在Palladium 與Haps 兩種FPGA 環(huán)境下進行充分的芯片原型驗證。
設計的RomCode 架構框圖如圖1 所示,其中CPU0 為主核、CPU1 為從核,后文不再贅述。主核加載引導包括處理器內核初始化、最小系統(tǒng)外設初始化以及用戶級程序加載引導等;多核初始化由主核初始化和從核初始化組成;多核引導設計首先對多核啟動所存在的技術問題進行了討論,并提出了解決方案,然后給出了主核引導從核啟動的具體實現(xiàn)。
圖1 RomCode架構框圖
地址空間分配是RomCode 架構設計的重要組成部分,它決定了RomCode 程序的存儲結構劃分和加載的用戶級程序在內存中的存放位置[9]。
地址空間由ROM區(qū)、SRAM 頂部區(qū)、SRAM 底部區(qū)三部分構成:
1)ROM 區(qū):text 段用于存儲RomCode 程序對應的機器指令,該部分是固定的,程序存儲地址和CPU的運行地址保持一致,rodata 段用于存儲只讀數(shù)據(jù),如程序中使用的宏定義。
2)SRAM 頂部區(qū):用于存儲多核運行的堆棧區(qū)、bss 段區(qū)、data 段區(qū)。
3)SRAM 底部區(qū),用于存放從外部存儲介質中加載的用戶代碼頭部信息和用戶代碼。具體空間分配如圖2 所示。
圖2 RomCode空間分配框圖
對用戶級程序完成正確的加載和引導是RomCode 實現(xiàn)的核心功能,該段程序負責從不同類型的外部存儲介質中加載用戶級程序到RAM 中并引導運行[10]。
用戶級程序的加載階段,RomCode 將其從外部存儲介質中加載到對應的內存位置,并進行數(shù)據(jù)正確性校驗[11],如圖3 所示。
具體步驟如下:
1)該系統(tǒng)支持三種類型的存儲介質,分別是TF卡、SD卡、emmc,RomCode 按此順序依次掃描。
2)從相應的存儲介質中讀取用戶代碼的配置區(qū)信息,并對配置區(qū)的有效性進行校驗,信息正確性由密鑰和信息摘要算法保證,配置區(qū)正確,則進入步驟3),反之,則進入通信模式,并反饋錯誤位置。
3)從相應的存儲介質中讀取用戶級程序,根據(jù)配置區(qū)的源地址、目的地址、用戶代碼大小等信息,將用戶代碼加載到SRAM 中,對用戶代碼進行循環(huán)冗余校驗CRC,用戶代碼正確則進入引導階段,反之,則進入通信模式,并反饋錯誤位置。
用戶級程序的引導是在正確加載用戶配置區(qū)和程序后,如圖4 所示。
圖4 引導階段框圖
具體步驟如下:
1)讀取用戶代碼配置區(qū)中的程序執(zhí)行地址參數(shù)。
2)對該地址參數(shù)進行有效性判斷,檢查該參數(shù)是否處于RAM 的有效地址區(qū)間,即用戶代碼存儲區(qū)。
3)設置程序計數(shù)寄存器PC,運行用戶級程序。
多核初始化包括了CPUID 判斷、內核基礎初始化、主核和從核初始化路徑選擇、最小系統(tǒng)外設初始化等部分。
內核基礎初始化是配置內核模塊的過程,為RomCode 中C 代碼準備安全可靠的運行環(huán)境。初始化步驟包括異常處理配置、特權模式配置、關閉MMU、關閉L1 Cache,如圖5 所示。異常處理配置為該ARM 處理器的七種異常提供異常處理;處理器模式配置將CPU 配置成特權模式;內存管理MMU和L1 Cache 通過系統(tǒng)協(xié)處理器CP15 將MMU 和L1 Cache 設置為禁止狀態(tài),減少異常的發(fā)生。
圖5 內核基礎初始化
根據(jù)CPUID 信息區(qū)分出主核與從核,并跳轉至不同的內核初始化分支,若為主核,則進行最小系統(tǒng)外設初始化,若為從核,則進入到低功耗等待模式,如圖6 所示。
圖6 多核初始化流程圖
1.4.1 關鍵問題
多核處理器架構主要包括對稱多核處理器(SMP) 和非對稱多核處理器(AMP)兩種。該文所述的處理器SoC 芯片為SMP 模式,其最大的特點是處理器的所有資源均共享,如操作系統(tǒng)、總線、內存以及外設資源等[12]。另外,用戶級程序的加載引導由主核完成[13]。
SMP 模式下,多核啟動時會引發(fā)資源搶占[14],從而導致程序的亂序執(zhí)行。為解決該問題,該文所述RomCode 設計了一套多核啟動復位系統(tǒng),如圖7所示。
圖7 多核順序啟動過程
首先,系統(tǒng)上電后,復位系統(tǒng)直接對CPU0 進行硬件解復位,而將CPU1 強制處于復位狀態(tài),操作系統(tǒng)啟動后由CPU0 完成對CPU1 的解復位操作,以此決定各CPU 的啟動順序。
其次,各CPU 運行同樣的用戶級程序,勢必導致共享資源的重復初始化,引起程序異常,常見問題諸如共享的L2 Cache 被CPU0 初始化并使用,CPU1 再次初始化L2 Cache,會導致嚴重的Cache 一致性問題,引發(fā)系統(tǒng)崩潰。為此,該RomCode 將CPU0 和CPU1 的初始化區(qū)分開來,避免對同一資源的重復初始化。具體的措施包括:
1)通過查詢CPUID寄存器確定當前運行RomCode程序的CPU 核心,以此區(qū)別各CPU 初始化的引導路徑,以實現(xiàn)主、從核的特定功能。
2)提供CPU1 的操作系統(tǒng)入口地址寄存器,由CPU0 配置該寄存器。CPU1 完成初始化配置后,則加載入口地址寄存器,獲取CPU1 下一步運行的代碼;此時,CPU1 即將運行的代碼已跳過了資源初始化部分,避免了緩存重復初始化導致的Cache 一致性問題。
3)提供CPU0 軟中斷喚醒(SGI)和CPU1 等待中斷喚醒(WFI)功能,CPU1 進入WFI 模式后,處于低功耗模式,等待CPU0 發(fā)送SGI 進行核間喚醒,有利于CPU0 對CPU1 進行喚醒安排,保證各CPU 有序執(zhí)行。
1.4.2 多核啟動流程設計
相對于單核RomCode 程序,SMP 模式的多核處理器的RomCode 需要結合芯片設計,解決多核啟動的順序和CPU 重復初始化共享資源兩大問題。該節(jié)將詳細介紹RomCode 如何結合硬件設計解決以上問題,順利完成主核CPU0 對從核CPU1 的啟動引導流程。
具體啟動引導過程如下:
第一階段:系統(tǒng)上電后,CPU0 硬件解復位,RomCode 查詢CPUID 以判斷當前運行核心是否為CPU0,然后順序執(zhí)行CPU0 的初始化程序和共享資源的初始化,最后CPU0 配置復位寄存器對CPU1 進行解復位。
第二階段:CPU1 釋放復位后,查詢CPUID 判斷當前運行核心,若為CPU1,則跳轉至CPU1 的初始化程序,進行內核初始化,之后CPU1 進入WFI 狀態(tài),此時,CPU1 處于上電、無時鐘的低功耗狀態(tài)。該階段CPU0 的主要工作為配置CPU1 系統(tǒng)入口地址寄存器,為真正進入用戶級程序做準備,并發(fā)送SGI 軟中斷到CPU1。
第 三階 段:CPU1 接收到CPU0 發(fā)送 的SGI喚醒指令后,讀取入口地址寄存器的值,RomCode 檢查該值是否處于有效的地址區(qū)間,如SRAM 或DDR 內存等,若有效,則設置PC 值并跳轉至入口地址處運行用戶級程序。
具體啟動引導流程如圖8 所示,圖中左側為主核對從核啟動的配置,右側為從核的啟動流程。
圖8 多核引導流程
基于Palladium FPGA 對RomCode 進行的原型驗證,可獲取到RTL 級別的調試手段,并同芯片RTL 設計保持同步,通過時序波形圖準確地分析芯片的運行狀態(tài)[15]。驗證環(huán)境如圖9 所示。
圖9 Pallidium FPGA原型驗證環(huán)境框圖
其中,RomCode 存儲于芯片內部的Rom 空間,用戶級程序U-Boot 和Linux 操作系統(tǒng)鏡像存儲于TF/SD/emmc 中,由RomCode 將U-Boot搬移到SRAM 中運行,再由U-Boot 將Linux 操作系統(tǒng)鏡像搬移到DDR 中運行,在Linux 操作系統(tǒng)中使能處理器多核功能,由RomCode 支撐處理器運行于多核狀態(tài)。
基于芯片驗證EDA 工具verdi 分析RomCode的運行情況,從XeDebug 的終端可觀察到U-Boot的啟動信息,通過verdi 時序分析圖可查看到TF 卡工作時鐘被分頻控制為10 MHz;UART 總線時鐘為200 MHz,基于此進行時鐘分頻,設置UART 波特率為115 200 bps。通過verdi EDA 可看出主核、從核均從PC 為0 處正常啟動。
Haps 作為先進的FPGA 原型驗證工具,提供了更為真實的硬件環(huán)境[16],極大地豐富了調試手段,可以加快軟件的開發(fā)、迭代周期[17]。而該文基于Haps驗證RomCode的CPU 啟動、多核等功能。Haps FPGA原型驗證環(huán)境如圖10 所示。
圖10 Haps原型驗證環(huán)境框圖
硬件環(huán)境如圖11 所示,其中,RomCode 固化于bitfile 中,U-Boot 及Linux 操作系統(tǒng)鏡像存儲于圖中標示1 的TF 卡,由RomCode 將U-Boot 搬移到標示3的DDR 內存中運行,基于標示2 的串口將CPU 信息輸出到上位機用以查看其內部運行狀態(tài)。同時,輔之以標示4 的JTAG 調試工具可快速定位CPU 異常。
圖11 驗證硬件環(huán)境
芯片上電解復位后,由主核運行程序,從TF 卡中獲取鏡像文件并進行文件正確性檢查,若文件鏡像正確,則進行鏡像文件搬移,反之丟棄。在該實驗中,正確的識別到U-Boot 鏡像且文件正確,串口輸出的打印信息如圖12 所示。
圖12 CPU0加載U-Boot程序打印
文件正確性校驗通過后,由RomCode 負責將UBoot 搬移至DDR 中運行,若搬移正確,則U-Boot 會引導Linux 操作系統(tǒng)的啟動,反之,啟動失敗。在該實驗中,U-Boot 運行正常且完成了系統(tǒng)的加載,串口輸出的打印信息如圖13 所示。
圖13 主核程序運行狀態(tài)打印
該文加載的Linux 操作系統(tǒng)具備多核特性,當其進入到處理器多核啟動流程時,RomCode 實現(xiàn)的多核功能被激活[18-19]。若多核啟動成功,則通過串口可查看到從核的啟動信息,如圖14 所示。
圖14 kernel從核啟動信息
針對該文所述的RomCode 功能點,重點分析了其實現(xiàn)原理,同時,該RomCode 提供了多種外部存儲介質接口,保證了用戶級程序的存儲多樣性和安全性?;赑allidium 與Haps 的FPGA 原型驗證體現(xiàn)出該多核RomCode 設計的可行性和功能的正確性,針對多核嵌入式處理器的啟動,提供了高效可靠的設計方案和驗證方法。