文獻標(biāo)識碼: A
文章編號: 0258-7998(2014)03-0025-04
快速啟動能力是衡量產(chǎn)品性能的一個重要指標(biāo)。無論是消費類電子產(chǎn)品(例如手機、電腦、電視機),還是專業(yè)的通信電子設(shè)備(例如示波器、網(wǎng)關(guān)、服務(wù)器),啟動速度快無疑能給用戶留下美好的第一印象。雖然電子設(shè)備的“心臟”越來越多地選用了多核處理器,但是目前大部分啟動代碼還停留在單內(nèi)核處理器的思維框架中,沒有能夠充分利用多內(nèi)核處理器的長處,而越來越多的外部器件卻在另一方面悄悄地延長了啟動時間。
為了彌補這一不足,突破傳統(tǒng)單核啟動的思維框架,本文以一個典型的嵌入式系統(tǒng)為例,對加快系統(tǒng)啟動速度進行了研究。
1 典型的系統(tǒng)架構(gòu)和啟動過程
1.1 系統(tǒng)架構(gòu)
智能通信電子產(chǎn)品的典型架構(gòu)是以CPU(中央處理器)為核心,根據(jù)產(chǎn)品需求輔以內(nèi)存、硬盤、網(wǎng)卡、USB、串口等各種外設(shè),如圖1所示。
系統(tǒng)的核心是飛思卡爾(FreeScale)公司開發(fā)的32位PowerPC架構(gòu)處理器MPC8572E[1],主頻最高可達1.333 GHz。芯片集成了2個完全相同的高性能e500內(nèi)核,每個內(nèi)核各包含32 KB一級指令緩存和32 KB一級數(shù)據(jù)緩存。芯片還集成了豐多彩富的內(nèi)部功能模塊和外設(shè)接口,包括:2個內(nèi)核共享的1 MB容量的二級緩存、2個64位DDR2/DDR3內(nèi)存控制器、1個可編程的中斷控制器、1個安全引擎、2個I2C總線控制器、2個異步串口控制器、1個增強型本地總線控制器、4個支持10/100/1 000 MB/s的以太網(wǎng)接口、3個符合PCIe 1.0a標(biāo)準(zhǔn)的PCIe接口等。
CPU、內(nèi)存、閃存、串口和網(wǎng)口組成了一個常見的最小系統(tǒng),其他模塊則是錦上添花。處理器通過PCIe接口連接SATA/SAS控制器(例如LSI公司的SAS2008芯片),再外接SATA/SAS硬盤。實時時鐘芯片(RTC)和溫度感應(yīng)器通過I2C總線與處理器相連。FPGA用于輔助CPU工作。這個系統(tǒng)具有強大的處理能力和靈活的可擴展性,適合于路由器、網(wǎng)關(guān)等多種應(yīng)用場合。其他智能電子設(shè)備的控制系統(tǒng)的架構(gòu)也大致如此,只是CPU可能替換成ARM、MIPS或x86等體現(xiàn)結(jié)構(gòu)的處理器,外圍器件有所增減,但是總體框架和啟動過程大同小異。
1.2 啟動過程
該系統(tǒng)由業(yè)界常用的U-BOOT[2]引導(dǎo)啟動。圖2顯示了多內(nèi)核處理器系統(tǒng)中啟動代碼的工作流程。上電或重啟后,內(nèi)核0根據(jù)配置引腳的設(shè)定,選擇從閃存中讀取啟動代碼。其他內(nèi)核保持Reset狀態(tài)。內(nèi)核0依次初始化了e500內(nèi)核、第一個串口、一級數(shù)據(jù)緩存和指令緩存、二級緩存、I2C總線設(shè)備、內(nèi)存。因為初始化內(nèi)存時CPU需要訪問內(nèi)存條上的SPD(SPD是存儲內(nèi)存條規(guī)格參數(shù)的EEPROM芯片),所以I2C總線的初始化必須在內(nèi)存初始化之前完成。之所以較早地初始化串口,是為了盡早建立人機交互的環(huán)境,以方便用戶判斷系統(tǒng)啟動到各個階段的狀態(tài)。然后,內(nèi)核從閃存中讀取FPGA配置文件并且下載到FPGA芯片中,再初始化PCIe設(shè)備、網(wǎng)口、SAS/SATA控制器、硬盤和文件系統(tǒng)。接著,內(nèi)核0釋放其他內(nèi)核的Reset信號。
其他內(nèi)核也從閃存中讀取啟動代碼,依次初始化e500內(nèi)核、一級數(shù)據(jù)緩存和指令緩存,然后通過共享內(nèi)存的方式(也可以通過內(nèi)部寄存器或者內(nèi)核間中斷等方式)通知內(nèi)核0“我準(zhǔn)備就緒了。”一旦內(nèi)核0發(fā)現(xiàn)其他內(nèi)核準(zhǔn)備就緒后,就從硬盤中讀取操作系統(tǒng)的鏡像文件,校驗正確后加載執(zhí)行。如果內(nèi)核0發(fā)現(xiàn)其他內(nèi)核啟動失敗,則重新發(fā)出Reset信號,要求其他內(nèi)核重復(fù)初始化的過程。
經(jīng)過測試,整個系統(tǒng)的啟動時間約9 s。表1列舉了耗時超過0.1 s的模塊,其他模塊的耗時微乎其微,可以忽略不計。從啟動過程可以看出,所有的初始化任務(wù)基本上都由內(nèi)核0承擔(dān),總的啟動時間是各模塊初始化時間的總和。顯然,這種傳統(tǒng)的多核啟動方式?jīng)]有利用多內(nèi)核的優(yōu)勢,還停留在單核啟動的框架中。
2 啟動過程的改進
在多核系統(tǒng)中,為了高效地利用多個核的并行工作,啟動代碼的設(shè)計需要從傳統(tǒng)意義上的任務(wù)串行機制轉(zhuǎn)換到任務(wù)并行機制,并且要注重多內(nèi)核間的協(xié)作。改進后的啟動方案不僅充分利用了多內(nèi)核的優(yōu)勢,將一些模塊的初始化任務(wù)分配給了其他內(nèi)核,而且優(yōu)化了一些模塊的初始化方法,建立了內(nèi)核間有效的通信機制。
如何將模塊分配給其他內(nèi)核初始化,分配原則之一是獨立性。如果該模塊和其他模塊沒有相互依賴關(guān)系,則可以將該模塊分配給其他內(nèi)核加載。原則之二是耗時的模塊盡量分配給不同的內(nèi)核加載,即每個核承擔(dān)模塊的總耗時盡量平均,盡可能減少等待時間。據(jù)此優(yōu)化為圖3所示的啟動流程。
啟動過程中,內(nèi)核0仍然扮演主力隊員的角色,首先初始化e500、串口、一級緩存和二級緩存,然后只初始化一部分內(nèi)存,而不是全部內(nèi)存。這一部分內(nèi)存姑且稱為基本內(nèi)存,即啟動代碼所要用到的內(nèi)存,本系統(tǒng)中是32 MB。因為內(nèi)存的初始化比較費時,主要時耗不在內(nèi)存控制器的初始化上,而在于將所有的4 GB內(nèi)存清零,所以把內(nèi)存劃分為一大一小兩部分初始化,將容量大的那部分內(nèi)存分配給其他內(nèi)核初始化,有利于提升整體的啟動速度。
完成內(nèi)核、串口1和基本內(nèi)存的初始化之后,內(nèi)核0先把啟動代碼從閃存復(fù)制到內(nèi)存中,再釋放其他內(nèi)核的Reset信號。其他內(nèi)核立刻初始化e500內(nèi)核和內(nèi)嵌的一級緩存,然后通知內(nèi)核0“我已經(jīng)準(zhǔn)備好了。”內(nèi)核0得知其他內(nèi)核準(zhǔn)備就緒了,就開始分配其余的初始化任務(wù)。其他內(nèi)核依次初始化剩余的大部分內(nèi)存,下載FPGA的配置文件,初始化網(wǎng)口,最后等待操作系統(tǒng)。與此同時,內(nèi)核0初始化PCIe設(shè)備、SAS/SATA控制器及磁盤,加載文件系統(tǒng),最后從磁盤中讀入操作系統(tǒng)文件,計算校驗和,引導(dǎo)操作系統(tǒng)的啟動。
除了改進啟動流程之外,充分利用硬件特性,優(yōu)化一些模塊的初始化方法和工作機制,設(shè)計高效的內(nèi)核間通信機制,也可以提升啟動速度。
(1)內(nèi)存初始化。內(nèi)存初始化的主要耗時動作是清零。目前主流的處理器都集成了DMA(直接存儲器訪問)引擎,DMA引擎就是為了降低CPU負載而設(shè)計的。測試發(fā)現(xiàn),與處理器直接清零內(nèi)存操作比較,采用DMA方式,速度可以提升一倍。并且,在DMA引擎清零的同時,CPU還可以承擔(dān)其他工作,例如下載FPGA配置文件。此外,如果內(nèi)存設(shè)置為交織模式,其吞吐量可以翻番,從而減少耗時,進一步提升啟動速度。
(2)PCIe初始化。PCIe[3]總線在軟件上兼容PCI、PCI-x總線,PCI或者PCI-x器件可以通過PCIe橋設(shè)備連接到PCIe的總線拓撲中。PCIe總線的拓撲結(jié)構(gòu)像一顆樹,最多允許擁有256條總線,每條總線上最多允許32個設(shè)備,每個設(shè)備上最多可集成8個功能模塊。一般采用深度遞歸算法,從根節(jié)點出發(fā),遍歷整棵樹,找到存在的有效設(shè)備并初始化。初始化的操作就是分配總線號、設(shè)備號、中斷號和地址空間等。其中,PCIe拓撲結(jié)構(gòu)的遍歷過程是比較耗時的一個操作。
實際上,對于電子產(chǎn)品而言,一旦電路板裝配好了,除了PCIe插槽上的設(shè)備未定之外,其他PCIe設(shè)備都固定了,是已知數(shù),所以對于已知設(shè)備可以省略掃描這個步驟。它的相關(guān)信息可以存儲在閃存的指定區(qū)域,啟動代碼直接從這個區(qū)域讀取。如果電路板上沒有PCIe插槽,則整個PCIe拓撲結(jié)構(gòu)的信息都可以保存在閃存中,徹底省略了遍歷過程,耗時微乎其微。對于插槽上的未定設(shè)備,深度遍歷的出發(fā)點可以從根節(jié)點出發(fā)改為從各個PCIe插槽出發(fā),大幅縮小遍歷范圍,從而節(jié)省了大量時間。
(3)簡單高效的基于共享內(nèi)存的內(nèi)核間通信機制。內(nèi)核之間為了緊密配合,相互間需要傳遞一些命令和數(shù)據(jù),雖然有些處理器擁有特別的內(nèi)核間的通信方式,例如博通公司XLR系統(tǒng)處理器的消息環(huán)機制[4](Message Ring),但是共享內(nèi)存是一個比較通用的方法,不僅適合于內(nèi)核之間,也適合于處理器之間以及處理器與外設(shè)之間的通信,可移植性較強。基于共享內(nèi)存,設(shè)計一個簡單高效的通信機制,有助于內(nèi)核0與其他內(nèi)核之間命令的上行下達。
因為啟動過程中內(nèi)核0起主導(dǎo)作用,所以在內(nèi)核0和其他每個內(nèi)核之間都創(chuàng)建了一條通信通道,組成一個星形結(jié)構(gòu):內(nèi)核0在中間,其他內(nèi)核在四周,如圖4所示。每條通道由收、發(fā)2個隊列組成:內(nèi)核0只能寫發(fā)送隊列,其他內(nèi)核只能讀發(fā)送隊列;接收隊列的操作相反,內(nèi)核0只能讀接收隊列,其他內(nèi)核只能寫接收隊列。
讀寫隊列的基本單位是數(shù)據(jù)塊,即每次從隊列中讀取一個或多個數(shù)據(jù)塊,或者往隊列中寫入一個或多個數(shù)據(jù)塊。數(shù)據(jù)塊由序列號、命令、數(shù)據(jù)長度、數(shù)據(jù)等域組成。發(fā)送隊列數(shù)據(jù)塊中的序列號是偶數(shù),而接收隊列數(shù)據(jù)塊的序列號是奇數(shù),每一個發(fā)送數(shù)據(jù)塊都對應(yīng)一個響應(yīng)的接收數(shù)據(jù)塊,它們的序列號相差1。發(fā)送隊列數(shù)據(jù)塊中的數(shù)據(jù)域是與命令相關(guān)的參數(shù),接收隊列數(shù)據(jù)塊中的數(shù)據(jù)域是命令的執(zhí)行結(jié)果。
借助這個收發(fā)隊列通信機制,內(nèi)核0可以便捷地把初始化等任務(wù)分派給其他內(nèi)核并得到反饋,有利于系統(tǒng)的可擴展性。例如系統(tǒng)中增加了一個新器件,內(nèi)核0可以把新器件的初始化工作分配給一個比較空閑的內(nèi)核,從而最大限度地減少對整個啟動時間的影響。
經(jīng)過啟動流程的改進、模塊加載和初始化方式的優(yōu)化、內(nèi)核間高效通信機制的設(shè)計等工作,系統(tǒng)的啟動時間大約縮短了50%,達到了比較滿意的結(jié)果。目前多處理器的發(fā)展和應(yīng)用如火如荼,希望本文所介紹的經(jīng)驗對各種體系結(jié)構(gòu)的多內(nèi)核處理器的啟動代碼設(shè)計都有所幫助。
參考文獻
[1] FreeScale Semiconductor.MPC8572E PowerQUICC III integrated processor hardware specifications,Rev.5[Z].2011.
[2] DENK W.The universal boot loader[EB/OL].[2013-07]. http://www.denx.de/wiki/DULG/WebHome.
[3] PCISIG.PCI Express base specification,revision 3.0[Z]. 2008.
[4] Broadcom Inc..XLR processor family data sheet,revision 2.00[Z].2008.