郭 俊,虞致國(guó),洪廣偉,顧曉峰
江南大學(xué) 電子工程系 物聯(lián)網(wǎng)技術(shù)應(yīng)用教育部工程研究中心,江蘇 無(wú)錫214122
RISC-V是由美國(guó)加州大學(xué)伯克利分校(UCB)設(shè)計(jì)并公布的一種基于精簡(jiǎn)指令集計(jì)算(reduced instruction set computing,RISC)原理的指令集架構(gòu),其目標(biāo)是成為一種完全開(kāi)放、適合硬件實(shí)現(xiàn)且穩(wěn)定的標(biāo)準(zhǔn)指令集架構(gòu)[1-2]。相比當(dāng)前發(fā)展相對(duì)成熟的商業(yè)架構(gòu),RISC-V 指令集架構(gòu)具有支持模塊化可配置的指令子集、極強(qiáng)的擴(kuò)展性、指令數(shù)目少、低功耗及低成本等突出優(yōu)點(diǎn)[3-4]。近年來(lái),其憑借自身優(yōu)勢(shì),已經(jīng)引起學(xué)術(shù)界的廣泛關(guān)注[5]。
通常,在嵌入式開(kāi)發(fā)人員開(kāi)發(fā)RISC-V處理器(如蜂鳥(niǎo)E200、Rocket Core 處理器等)的過(guò)程中,若需對(duì)處理器的固件進(jìn)行更新升級(jí),只能通過(guò)JTAG(joint test action group)調(diào)試器來(lái)燒錄新的固件程序[6]。JTAG 調(diào)試器信號(hào)線種類(lèi)繁多且配置流程復(fù)雜,給開(kāi)發(fā)人員帶來(lái)了很多不必要的麻煩。隨著嵌入式系統(tǒng)的飛速發(fā)展,在應(yīng)用中編程(in-application programming,IAP)技術(shù)在RISC 指令集架構(gòu)處理器中已經(jīng)得到廣泛的應(yīng)用,其能通過(guò)已有的通信接口對(duì)存儲(chǔ)在Flash中的數(shù)據(jù)進(jìn)行重新燒寫(xiě)[7],從而簡(jiǎn)化嵌入式開(kāi)發(fā)人員更新固件的操作流程。文獻(xiàn)[8-10]分別根據(jù)各自的應(yīng)用場(chǎng)景為ARM處理器實(shí)現(xiàn)了IAP設(shè)計(jì),但是都只能在Flash 中運(yùn)行IAP 程序,與在RAM 中運(yùn)行的速度相比,處理器每次都需從Flash中取指令,取指時(shí)間較長(zhǎng),影響了整個(gè)系統(tǒng)級(jí)芯片(system on chip,SoC)的啟動(dòng)速度。文獻(xiàn)[11]為其自主設(shè)計(jì)研發(fā)的RISC DSP實(shí)現(xiàn)了固件更新系統(tǒng)設(shè)計(jì),但是其實(shí)現(xiàn)的方法需要將固件更新代碼全部固化在BootROM中。若本文采用此種設(shè)計(jì)方法,則會(huì)占用更多的ROM資源,導(dǎo)致無(wú)法為RISC-V處理器設(shè)計(jì)出更多種可供開(kāi)發(fā)人員靈活選擇的啟動(dòng)模式。
針對(duì)IAP 技術(shù)的應(yīng)用需求和上述問(wèn)題,本文為RISC-V 指令集架構(gòu)處理器設(shè)計(jì)了一個(gè)易操作、高效且穩(wěn)定的固件更新系統(tǒng)。此系統(tǒng)主要設(shè)計(jì)成兩個(gè)啟動(dòng)階段:第一階段在BootROM 中進(jìn)行,主要執(zhí)行BootROM中固化的代碼以完成RISC-V 處理器內(nèi)核初始化,以及第二階段所需啟動(dòng)程序(例如,在固件更新系統(tǒng)中為IAP 程序)的參數(shù)再配置以及加載等;第二階段在主內(nèi)存(DDR3/4 SDRAM)中進(jìn)行,主要執(zhí)行IAP 程序以完成對(duì)片外Flash中固件的更新、片外Flash到主內(nèi)存的固件加載以及跳轉(zhuǎn)運(yùn)行新固件等。
圖1為本文所采用的RISC-V處理器及其SoC架構(gòu)。從圖中可看出,該系統(tǒng)由64位的RISC-V處理器(Rocket Core)、系統(tǒng)總線(System Bus)、設(shè)備總線(Device Bus)、存儲(chǔ)總線(Memory Bus)、AXI 總線以及各總線的相應(yīng)掛載模塊組成。其中,完成固件更新所需的BootROM模塊掛載在系統(tǒng)總線上,通用異步收發(fā)傳輸器(universal asynchronous receiver/transmitter,UART)和串行外設(shè)接口(serial peripheral interface,SPI)模塊掛載在設(shè)備總線上,DDR3/4控制器模塊掛載在存儲(chǔ)總線上。
圖1 RISC-V處理器及其SoC架構(gòu)Fig.1 Frame diagram of RISC-V processor and SoC
目前,公開(kāi)發(fā)布的開(kāi)源RISC-V處理器主要有BOOM Core、Rocket Core、蜂鳥(niǎo)E200 Core、PicoRV32 Core、SCR1 Core 及ORCA Core 等[6]。由于后三種處理器沒(méi)有與其配套的開(kāi)源SoC平臺(tái),不具備完成固件更新系統(tǒng)設(shè)計(jì)的條件;同時(shí)綜合考慮前三種處理器的性能、面積以及課題需求,最終選擇性能與面積都折中的Rocket Core作為固件更新系統(tǒng)的開(kāi)發(fā)平臺(tái)。
Rocket Core 是UCB 推出RISC-V 指令集架構(gòu)時(shí)同期發(fā)布的一款64 位的開(kāi)源處理器,可用SoC 生成器(Generator)Rocket-Chip 生成[12-13],其源代碼采用Chisel語(yǔ)言開(kāi)發(fā)[14]。Rocket Core具有如下特點(diǎn):支持多種RISC-V指令集擴(kuò)展組合,配備單發(fā)射順序執(zhí)行的五級(jí)流水線、無(wú)阻塞緩存、返回地址堆棧、分支預(yù)測(cè)機(jī)制、可擴(kuò)展指令接口以及內(nèi)存管理單元,集成浮點(diǎn)運(yùn)算單元(float point unit,F(xiàn)PU)等[15]。UCB 團(tuán)隊(duì)在5 年內(nèi)使用Rocket Core完成11次流片,并在其芯片原型上成功運(yùn)行了Linux操作系統(tǒng)[16]。
固件更新系統(tǒng)的硬件結(jié)構(gòu)如圖2 所示。首先為RISC-V SoC設(shè)計(jì)了一種BootROM引導(dǎo)方式,完成片外Flash 到主內(nèi)存的程序加載,并將程序指針跳轉(zhuǎn)到內(nèi)存中;之后,根據(jù)IAP 原理,采用UART 接口接收從PC 機(jī)發(fā)送過(guò)來(lái)的固件更新文件(采用Ymodem協(xié)議發(fā)送),采用SPI接口完成RISC-V處理器對(duì)片外Flash固件地址段的重新燒寫(xiě),以實(shí)現(xiàn)對(duì)系統(tǒng)固件的更新。
圖2 固件更新系統(tǒng)硬件結(jié)構(gòu)Fig.2 Hardware structure of firmware update system
為了更好地管理Flash空間及考慮到后續(xù)對(duì)IAP設(shè)計(jì)的升級(jí)優(yōu)化,需要對(duì)片外Flash 的存儲(chǔ)空間進(jìn)行合理規(guī)劃[10]。
在固件更新系統(tǒng)中,片外Flash 的存儲(chǔ)空間主要被分為兩個(gè)相互獨(dú)立的模塊,分別用來(lái)存儲(chǔ)IAP程序和固件程序。本設(shè)計(jì)所采用的片外Flash是華邦(WINBOND)公司的W25Q128JV,此Flash為Block 0(64 KB)分別提供了4 KB、8 KB、16 KB 和32 KB 的寫(xiě)保護(hù)設(shè)置。為給IAP 程序設(shè)置寫(xiě)保護(hù)功能,以防止用戶(hù)誤擦除,本設(shè)計(jì)給IAP 程序預(yù)留了16 KB 的存儲(chǔ)空間,即Block 0 內(nèi)的Sector 0~Sector 3,其余空間預(yù)留給固件使用。
在固件更新過(guò)程中,完成了片外Flash 與主內(nèi)存(DDR3/4)之間的程序流交互。為了匹配上述Flash 存儲(chǔ)空間的規(guī)劃,以及得到IAP 和固件程序的跳轉(zhuǎn)地址,需要確定片外Flash中的IAP和固件程序在主內(nèi)存中的地址映射關(guān)系。本設(shè)計(jì)的地址映射關(guān)系如圖3所示,片外Flash中的IAP程序在主內(nèi)存中所映射的地址范圍為0x80000000~0x80003FFF,固件程序在主內(nèi)存中所映射的地址范圍為0x80004000~0x80FFFFFF。
圖3 主內(nèi)存的地址空間映射Fig.3 Address space mapping of main memory
BootROM是掛載在RISC-V處理器系統(tǒng)總線上的一小塊片內(nèi)掩膜ROM[11],配置的容量大小為8 KB。Rocket Core的復(fù)位PC值為0x10000,指向BootROM的基地址,因此在RISC-V處理器上電后,首先會(huì)從BootROM中取出指令執(zhí)行[17]。為保證整個(gè)系統(tǒng)的啟動(dòng)速度,本設(shè)計(jì)在BootROM內(nèi)只進(jìn)行一些簡(jiǎn)單的內(nèi)核初始化配置和為下一階段啟動(dòng)做好準(zhǔn)備,共占用7.08 KB 的BootROM 資源,為總?cè)萘康?8.5%。
設(shè)計(jì)的BootROM引導(dǎo)流程如圖4所示。
圖4 BootROM引導(dǎo)流程Fig.4 Flow chart of BootROM boot
在處理器內(nèi)核初始化完成后,系統(tǒng)會(huì)根據(jù)第一類(lèi)啟動(dòng)引腳狀態(tài)完成第一階段啟動(dòng)參數(shù)的再配置,如第二階段所需啟動(dòng)程序(在固件更新系統(tǒng)中為IAP 程序)的內(nèi)存分配、進(jìn)程數(shù)、源地址、目標(biāo)地址以及代碼量等參數(shù)的再配置,從而達(dá)到兼容多種啟動(dòng)模式(如SRAM啟動(dòng)、主內(nèi)存啟動(dòng))的目的。在固件更新系統(tǒng)中,選用主內(nèi)存啟動(dòng)模式。在此模式下,處理器完成啟動(dòng)參數(shù)的再配置后,會(huì)執(zhí)行BootROM 中已固化的一段加載指令和跳轉(zhuǎn)指令,可通過(guò)SPI控制器將片外Flash中存儲(chǔ)的IAP程序段加載到主內(nèi)存中;之后,程序指針跳轉(zhuǎn)到內(nèi)存的相應(yīng)地址處運(yùn)行IAP程序,進(jìn)行第二階段啟動(dòng)。
為了對(duì)BootROM 設(shè)計(jì)進(jìn)行功能仿真驗(yàn)證,本系統(tǒng)采用WINBOND 公司提供的W25Q32JV Flash 仿真模型。圖5展示了在主內(nèi)存啟動(dòng)模式下從片外Flash中讀出的第一條需要被加載的指令0x04c0006f(對(duì)應(yīng)的匯編代碼為j 8000004c,即跳轉(zhuǎn)到固件程序的復(fù)位向量地址處),以及在BootROM 中固化的跳轉(zhuǎn)指令0x00048067(對(duì)應(yīng)的匯編代碼為jr s1,即跳轉(zhuǎn)到主內(nèi)存中的IAP 程序基地址0x80000000 處)。從仿真結(jié)果可證明此種啟動(dòng)模式工作正常。
圖5 主內(nèi)存啟動(dòng)模式的仿真波形Fig.5 Simulation waveforms of main memory boot mode
2.5.1 IAP程序設(shè)計(jì)
IAP 設(shè)計(jì)采用Ymodem 通信協(xié)議傳輸固件文件。此協(xié)議是Xmodem 的改進(jìn)版,每包數(shù)據(jù)可高達(dá)1 024 字節(jié),已廣泛應(yīng)用于串口通信中[18]。在文件傳輸過(guò)程中,其憑借完善的握手機(jī)制和出錯(cuò)管理機(jī)制,具有高效、穩(wěn)定及一次支持傳輸多個(gè)文件等優(yōu)點(diǎn)[9]。
IAP程序的功能是先通過(guò)UART接收從上位機(jī)發(fā)送來(lái)的二進(jìn)制固件文件,再通過(guò)SPI控制器對(duì)存儲(chǔ)在片外Flash中的固件進(jìn)行重新燒寫(xiě),最后待更新固件成功后,完成從IAP程序到固件的指針跳轉(zhuǎn)。在設(shè)計(jì)好IAP程序后,只需將其通過(guò)JTAG調(diào)試器燒寫(xiě)到片外Flash一次即可。
設(shè)計(jì)的IAP程序流程如圖6所示。在程序運(yùn)行過(guò)程中,難免會(huì)遇到一些諸如異常復(fù)位、掉電或傳輸出錯(cuò)等情況而導(dǎo)致系統(tǒng)崩潰[8]。為了保證系統(tǒng)運(yùn)行的穩(wěn)定性,本設(shè)計(jì)采用軟硬件聯(lián)合控制機(jī)制完成對(duì)固件程序的更新,若在程序運(yùn)行中出現(xiàn)上述異常情況,則系統(tǒng)會(huì)自動(dòng)根據(jù)啟動(dòng)引腳狀態(tài)重新進(jìn)行本次更新,直到更新完成。在第一階段啟動(dòng)完成后,程序指針會(huì)從BootROM 跳轉(zhuǎn)到主內(nèi)存中,之后再通過(guò)第二類(lèi)啟動(dòng)引腳狀態(tài)進(jìn)行第二階段啟動(dòng)模式的選擇,包括UPDATE模式和WORK模式。
圖6 IAP程序流程Fig.6 Flow chart of IAP program
UPDATE 模式的流程:(1)關(guān)閉所有中斷;(2)對(duì)UART和SPI模塊進(jìn)行配置;(3)根據(jù)用戶(hù)通過(guò)串行交互軟件(如超級(jí)終端)發(fā)送過(guò)來(lái)的指令完成對(duì)固件的更新或擦除,若超級(jí)終端界面上提示片外Flash 中的固件程序地址段被設(shè)置成寫(xiě)保護(hù),則必須先輸入指令“diswp”,關(guān)閉其寫(xiě)保護(hù),否則無(wú)法將接收到的新固件正確燒寫(xiě)至Flash;(4)接收新固件文件并對(duì)其進(jìn)行CRC16 校驗(yàn),將校驗(yàn)通過(guò)的數(shù)據(jù)燒寫(xiě)到片外Flash中;(5)待固件更新成功后,在超級(jí)終端界面上會(huì)顯示傳輸文件的名稱(chēng)和大小等信息。
WORK模式的流程:(1)完成固件程序從片外Flash到主內(nèi)存的加載;(2)判斷固件是否加載成功,若成功,則程序指針跳轉(zhuǎn)到內(nèi)存的固件程序地址段,運(yùn)行新固件,若失敗,則提示用戶(hù)固件的加載出現(xiàn)錯(cuò)誤,并重新加載固件。
2.5.2 IAP實(shí)現(xiàn)要點(diǎn)
(1)關(guān)閉所有中斷
在IAP程序執(zhí)行過(guò)程中不需要產(chǎn)生任何中斷,應(yīng)在IAP程序起始部分關(guān)閉所有中斷,否則當(dāng)系統(tǒng)產(chǎn)生某種中斷時(shí),例如計(jì)時(shí)器中斷、UART 中斷、SPI 中斷、GPIO中斷、I2C中斷和DMA中斷等,程序指針會(huì)跳轉(zhuǎn)到中斷服務(wù)系統(tǒng)定義的“弱(weak)屬性”中斷服務(wù)程序:
這是一個(gè)無(wú)限循環(huán)函數(shù),當(dāng)發(fā)生某種中斷時(shí),程序指針將無(wú)法正常返回到IAP程序中,從而導(dǎo)致固件更新失敗。
(2)IAP跳轉(zhuǎn)的實(shí)現(xiàn)
IAP 程序跳轉(zhuǎn)到固件程序的設(shè)計(jì)是通過(guò)GCC 內(nèi)聯(lián)匯編的方式實(shí)現(xiàn)的:
當(dāng)固件加載完成后會(huì)執(zhí)行這段匯編程序,將主內(nèi)存中固件程序的地址存儲(chǔ)在寄存器s1中,使用無(wú)條件跳轉(zhuǎn)指令jr實(shí)現(xiàn)程序指針的跳轉(zhuǎn),去執(zhí)行固件程序。
(3)設(shè)計(jì)CRC校驗(yàn)算法
在實(shí)際的應(yīng)用中,使用IAP技術(shù)處理的文件是要被RISC-V 處理器運(yùn)行的固件程序,因此任何細(xì)微的錯(cuò)誤傳輸都將導(dǎo)致固件無(wú)法正常運(yùn)行,可能會(huì)造成無(wú)法預(yù)估的損失。為了保證數(shù)據(jù)傳輸?shù)目煽啃?,在IAP程序中設(shè)計(jì)了CRC校驗(yàn)算法:
式(1)中T為n比特的傳輸幀,D為k比特的數(shù)據(jù),F(xiàn)為(n-k)比特的冗余位;式(2)中P為預(yù)先設(shè)定的(n-k+1)比特的整數(shù),mod 為模2除法(即按位異或)[19]。只有通過(guò)校驗(yàn)(即式(2)的運(yùn)算結(jié)果為0)的數(shù)據(jù)才會(huì)被燒寫(xiě)至Flash中。
本設(shè)計(jì)使用Xilinx公司的Kintex?-7 FPGA KC705開(kāi)發(fā)板進(jìn)行固件更新系統(tǒng)的原型驗(yàn)證,具體的操作流程如下。
(1)將設(shè)計(jì)好的第一階段啟動(dòng)代碼編譯成二進(jìn)制碼,固化于BootROM 中,并在KC705 開(kāi)發(fā)板上實(shí)現(xiàn)RISC-V處理器的硬件設(shè)計(jì)。
(2)通過(guò)JTAG 將事先編譯好的IAP 代碼文件下載到片外Flash的IAP地址段。
(3)選擇UPDATE模式并啟動(dòng)系統(tǒng)。
(4)通過(guò)超級(jí)終端輸入更新指令“update”,此時(shí)在超級(jí)終端界面上可發(fā)現(xiàn)下位機(jī)一直向上位機(jī)發(fā)送字符“C”,以請(qǐng)求數(shù)據(jù)包。
(5)在超級(jí)終端界面上選用Ymodem 通信協(xié)議傳輸.bin格式的固件文件。
(6)待固件更新成功后,選擇WORK 模式,重啟系統(tǒng)即可運(yùn)行更新后的固件程序。
嵌入式開(kāi)發(fā)人員在更新RISC-V 處理器的固件時(shí),需要執(zhí)行的步驟只有(3)~(6)。
圖7 展示了使用Ymodem 通信協(xié)議傳輸固件文件的過(guò)程。從圖中可看出,在UART波特率為115 200 bit/s時(shí),1 s內(nèi)即可完成約10 KB固件的更新,固件更新速率為10 KB/s。在文獻(xiàn)[10]中,UART 波特率為9 600 bit/s,在最理想情況下對(duì)其波特率進(jìn)行轉(zhuǎn)換計(jì)算,固件更新速率為7.5 KB/s。本設(shè)計(jì)方法與文獻(xiàn)[10]相比,固件更新速率提高了約1.33倍。
圖7 固件傳輸?shù)倪^(guò)程Fig.7 Process of firmware transfer
圖8是成功傳輸固件文件的結(jié)果,從串口打印出的信息可看出,系統(tǒng)運(yùn)行正常,且經(jīng)過(guò)連續(xù)20次重復(fù)實(shí)驗(yàn)驗(yàn)證,無(wú)系統(tǒng)異常情況發(fā)生,驗(yàn)證了此固件更新系統(tǒng)設(shè)計(jì)的可行性與穩(wěn)定性。此固件更新系統(tǒng)現(xiàn)已用于接下來(lái)的基于FPGA的RISC-V處理器應(yīng)用開(kāi)發(fā)課題中。
圖8 固件傳輸?shù)慕Y(jié)果Fig.8 Results of firmware transfer
RISC-V處理器的固件更新系統(tǒng)設(shè)計(jì)能給嵌入式開(kāi)發(fā)人員的使用帶來(lái)極大的便利。本文通過(guò)啟動(dòng)參數(shù)再配置的方法,為以Rocket Core為核心的RISC-VSoC設(shè)計(jì)了一種高效、靈活的BootROM引導(dǎo)流程,以及基于此種引導(dǎo)流程的IAP實(shí)現(xiàn)方法。經(jīng)過(guò)多次實(shí)驗(yàn)驗(yàn)證,此固件更新系統(tǒng)具有操作簡(jiǎn)單、運(yùn)行穩(wěn)定等優(yōu)點(diǎn)。未來(lái)可對(duì)IAP技術(shù)的實(shí)現(xiàn)方法進(jìn)行優(yōu)化,進(jìn)一步提高系統(tǒng)固件的更新效率。