王鋒,呂天志,楊明洋
(中電科思儀科技股份有限公司,山東青島,266555)
采用SPIFlash配置的FPGA程序通常都是通過(guò)FPGA廠家提供的程序下載器進(jìn)行更新,一般儀器FPGA程序的更新方式有兩種:
(1)打開(kāi)產(chǎn)品機(jī)箱用專用程序下載器通過(guò)JETAG接口更新FPGA程序,這種方式操作復(fù)雜且需要專業(yè)人員完成;
(2)把FPGA程序下載器的功能集成到電路板中,利用廠商提供的程序下載軟件更新程序,這種方案需要加入額外電路器件,增加了電路板器件的布局空間、功耗及設(shè)計(jì)成本。
鑒于一般儀器的CPU模塊與FPGA之間都有PCIe總線連接,并且FPGA和SPIFlash直接連接,因此在FPGA正常工作時(shí)可以讓CPU軟件通過(guò)PCIe總線將要更新的FPGA程序以文件形式先傳遞給FPGA,然后在FPGA內(nèi)設(shè)計(jì)SPIFlash芯片的燒寫控制邏輯,進(jìn)而實(shí)現(xiàn)SPIFlash內(nèi)FPGA程序的在線更新。
本文以7系列FPGA為例,7系列FPGA的配置過(guò)程具備MultiBoot和FallBack機(jī)制—FPGA在上電配置時(shí),MultiBoot機(jī)制允許FPGA選擇SPIFlash中指定區(qū)域的比特流來(lái)配置,此版本比特流稱為update鏡像,如果配置失敗,則觸發(fā)FallBack機(jī)制將另一個(gè)性能良好的固定版本配置到FPGA中,從而保證FPGA可以正常工作,此版本比特流稱為golden鏡像。golden和update這兩個(gè)鏡像會(huì)一起作為初始化鏡像用專用程序下載器下載到SPIFlash中,在線更新僅對(duì)SPIFlash的update鏡像區(qū)域進(jìn)行更新。本文在7系列FPGA的MultiBoot和FallBack機(jī)制的基礎(chǔ)上,闡述了一種在線更新Flash內(nèi)FPGA程序的方法,此方法不需要拆機(jī)連接程序下載器,更不需要增加額外硬件,在軟件界面上即可控制SPIFlash內(nèi)FPGA程序更新過(guò)程。
首先將golden和update鏡像一起作為SPIFlash初始化鏡像下載到SPIFlash中,然后需要更新FPGA程序時(shí),使用在線程序更新功能升級(jí)SPIFlash的update鏡像即可。總體數(shù)據(jù)處理流程如圖1所示。
圖1 SPIFlash內(nèi)FPGA程序在線更新的數(shù)據(jù)處理流程
如圖1所示,在VIVADO工程版本1.0時(shí)生成golden和update鏡像兩個(gè)FPGA程序bit文件;然后使用特定的tcl命令將golden和update鏡像合并成一個(gè)MCS文件作為Flash初始化鏡像,并使用專用程序下載器將此MCS文件下載到SPIFlash中。當(dāng)VIVADO工程版本升級(jí)為2.0時(shí)需要更新SPIFlash中FPGA程序,此時(shí)使用在線程序更新功能升級(jí)SPIFlash的update鏡像即可。由于SPIFlash內(nèi)存儲(chǔ)的FPGA程序的數(shù)據(jù)格式為bin文件,這里的bin文件不同于VIVADO生成的FPGA程序bit文件,因此CPU模塊可直接將2.0版update鏡像bin文件送到FPGA片內(nèi)RAM,然后在FPGA內(nèi)設(shè)計(jì)SPIFlash燒寫模塊從FPGA片內(nèi)RAM逐個(gè)字節(jié)讀取2.0版update鏡像bin數(shù)據(jù)并將其寫入update區(qū)域。
綜上所述,在7系列FPGA配置過(guò)程的MultiBoot和FallBack機(jī)制需要生成兩個(gè)版本的FPGA程序,在此基礎(chǔ)上,主要通過(guò)CPU軟件控制程序和FPGA燒寫控制程序?qū)崿F(xiàn)SPIFlash內(nèi)FPGA程序的在線更新功能。
在VIVADO工程約束文件中添加不同約束可編譯生成golden和update版FPGA程序文件。如圖2所示,在基本的SPI約束基礎(chǔ)上,選擇golden約束,假設(shè)編譯生成名為vision_golden.bit的golden鏡像bit文件;選擇update約束,假設(shè)編譯生成名為vision_update.bit的update鏡像的bit文件。
圖2 VIVADO工程中生成多版本FPGA程序的約束命令
在VIVADO使用下列tcl命令可生成SPIFlash初始化鏡像MCS文件,假設(shè)兩個(gè)版本的bit文件存在于計(jì)算機(jī)D盤根目錄下,此tcl命令如下:
write_cfgmem -force -format MCS -interface spix1-loadbit “up 0x0
D:/vision_golden.bit up 0x2000000D:/vision_update106.bit “D:/vision_golden_update.mcs
其中,此tcl命令指定了golden鏡像在SPIFlash內(nèi)存儲(chǔ)地址為0x00000000~0x01FFFFFF,update鏡像存儲(chǔ)起始地址為0x02000000。鏡像區(qū)域的地址分配根據(jù)鏡像規(guī)模而定,各型號(hào)FPGA的鏡像大小可查看UG470[10]文檔中的相關(guān)說(shuō)明。
CPU模塊將update鏡像bin文件送給FPGA。FPGA程序一般為十幾到幾十MB,F(xiàn)PGA片內(nèi)RAM難以一次性緩存,此時(shí)CPU模塊可以將update鏡像bin文件分包通過(guò)PCIe總線以DMA方式送給FPGA。設(shè)FPGA燒寫模塊的RAM為m字節(jié)大小,update鏡像bin文件為n字節(jié),則CPU模塊需要將bin文件拆分成N包數(shù)據(jù),N=[n/m],第N包數(shù)據(jù)不足m字節(jié)的話,需將第N包數(shù)據(jù)補(bǔ)充默認(rèn)字節(jié)“0xFF”到m字節(jié)。執(zhí)行在線程序更新時(shí),CPU模塊將第1包bin數(shù)據(jù)通過(guò)PCIe總線寫到FPGA的RAM后啟動(dòng)在線燒寫流程,同時(shí)監(jiān)測(cè)FLASH燒寫過(guò)程的各階段狀態(tài),正常燒狀態(tài)下FPGA程序每寫完1包數(shù)據(jù)就會(huì)通知CPU模塊發(fā)送下一包數(shù)據(jù),若發(fā)生異常,F(xiàn)PGA會(huì)將異常信息上傳至CPU模塊??刂屏鞒倘鐖D3所示。
圖3 SPIFlash內(nèi)FPGA程序在線更新CPU軟件控制流程圖
CPU模塊和FPGA通過(guò)PCIe進(jìn)行讀寫通信,如下所示:
首先,CPU模塊在啟動(dòng)程序更新之前首先標(biāo)記設(shè)置RAM為寫狀態(tài)、bin為未傳完?duì)顟B(tài);
然后,確認(rèn)啟動(dòng)程序更新之后,執(zhí)行一次寫RAM操作,并標(biāo)記RAM是否寫滿和bin數(shù)據(jù)是否傳完;
最后,CPU模塊等待RAM是否被讀空,若RAM為空時(shí)檢測(cè)到bin文件已送完則等待FLASH燒寫完畢后結(jié)束程序更新過(guò)程,否則再次執(zhí)行一次寫RAM操作。
首先需要根據(jù)update鏡像的bin文件大小和FPGA內(nèi)RAM資源情況開(kāi)辟一塊緩沖區(qū)來(lái)接收update鏡像bin數(shù)據(jù),緩沖區(qū)越大,CPU模塊向FPGA傳遞的bin數(shù)據(jù)包數(shù)就越少,F(xiàn)PGA資源占用越大。由于燒寫過(guò)程和FPGA正常功能不沖突,以及SPIFlash燒寫是臨時(shí)占用RAM資源,因此在線燒寫可以復(fù)用其他模塊的RAM,這塊RAM在FPGA正常工作時(shí)用于其他功能,這樣可實(shí)現(xiàn)RAM資源共享,節(jié)省RAM資源。
用戶通過(guò)界面啟動(dòng)在線燒寫功能后,首先執(zhí)行SPIFlash的update鏡像區(qū)域擦除,擦除完畢后,CPU模塊將update鏡像bin數(shù)據(jù)通過(guò)PCIe DMA分包送到FPGA的RAM,F(xiàn)PGA的燒寫模塊將bin數(shù)據(jù)逐個(gè)字節(jié)地傳遞給SPIFlash,并同時(shí)接收燒寫模塊輸出的過(guò)程標(biāo)記或異常信息。因此FPGA燒寫程序分為數(shù)據(jù)傳遞模塊和燒寫模塊。
1.4.1 數(shù)據(jù)傳遞模塊
FPGA負(fù)責(zé)接收每包update鏡像bin文件,并將燒寫過(guò)程中各階段完成或錯(cuò)誤標(biāo)記上傳給CPU模塊。每傳遞完1包bin數(shù)據(jù),F(xiàn)PGA通知CPU模塊繼續(xù)傳遞下一包bin數(shù)據(jù),直到所有bin數(shù)據(jù)包傳遞結(jié)束并且全部寫入SPIFlash。由于SPIFlash的update鏡像區(qū)域是事先分配的一塊區(qū)域,當(dāng)所有bin數(shù)據(jù)全部寫入FLASH時(shí),update鏡像區(qū)域一般沒(méi)有被寫滿,此時(shí)燒寫模塊并不會(huì)返回FLASH燒錄完成的標(biāo)志;因此FPGA需要再向update鏡像區(qū)域剩下的空間中寫填充字0xFF,直到update鏡像區(qū)域末尾燒寫模塊才會(huì)返回FLASH更新完成標(biāo)記。
每當(dāng)一包bin數(shù)據(jù)寫入RAM,F(xiàn)PGA捕獲RAM寫完標(biāo)記后使能讀狀態(tài)標(biāo)記,在RAM讀空之后清零RAM讀狀態(tài)標(biāo)記。在SPIFlash的update鏡像區(qū)擦除成功后,若讀狀態(tài)標(biāo)記有效并且bin文件的數(shù)據(jù)未傳遞結(jié)束,則逐個(gè)讀取RAM數(shù)據(jù)送給SPIFlash,當(dāng)RAM讀空時(shí)清零讀標(biāo)志。當(dāng)讀狀態(tài)標(biāo)記有效并且bin文件數(shù)據(jù)傳遞結(jié)束時(shí),說(shuō)明RAM中存儲(chǔ)的是bin文件的最后一包數(shù)據(jù),然后進(jìn)入寫填充字階段,直到SPIFlash燒寫完成。編制數(shù)據(jù)傳遞狀態(tài)機(jī),如圖4所示。
圖4 SPIFlash內(nèi)FPGA程序在線更新FPGA數(shù)據(jù)傳遞控制狀態(tài)機(jī)
其中,在 flash_programm_wait狀態(tài)等待SPIFlash的ID校驗(yàn)和存儲(chǔ)區(qū)擦除;針對(duì)CPU模塊傳遞來(lái)的N幀數(shù)據(jù)包,第1到N-1幀的字節(jié)是在 flash_programm_write狀態(tài)傳遞;第N幀的字節(jié)是在 flash_programm_write_ex狀態(tài)傳遞;update區(qū)域剩余空間的默認(rèn)字節(jié)“0xFF”在flash_programm_write_ex1狀態(tài)傳遞;在這四種狀態(tài)中,如果發(fā)生ID校驗(yàn)、或燒寫錯(cuò)誤,就停止?fàn)顟B(tài)機(jī),并將相應(yīng)錯(cuò)誤標(biāo)記傳遞給CPU模塊。
1.4.2 燒寫模塊
燒寫模塊實(shí)現(xiàn)FPGA和SPIFlash的通信,此模塊將SPIFlash控制指令或數(shù)據(jù)通過(guò)并串轉(zhuǎn)換后經(jīng)SPI訪問(wèn)FLASH,實(shí)現(xiàn)SPI FLASH的ID檢測(cè),F(xiàn)LASH存儲(chǔ)區(qū)擦除、數(shù)據(jù)傳遞以及異常檢測(cè)等功能。燒寫模塊內(nèi)部接口如圖5所示,燒寫模塊完全由FPGA實(shí)現(xiàn)。
圖5 SPIFlash內(nèi)FPGA程序在線更新FPGA程序燒寫模塊接口圖
其中燒寫控制模塊SpiFlashProgrammer的操作邏輯為:
(1) 初始化;
(2) 檢測(cè)ID,讀取并檢驗(yàn)FLASH存儲(chǔ)設(shè)備標(biāo)志;
(3) 刪除包含update鏡像的FLASH扇區(qū);
(4) 編碼update區(qū)域。對(duì)于update鏡像區(qū)域每一頁(yè):
a.發(fā)送頁(yè)編碼命令,
b.發(fā)送當(dāng)前頁(yè)的每個(gè)字,如果處于當(dāng)前頁(yè)的末尾,則進(jìn)入c步驟,
c.使能內(nèi)部FLASH頁(yè)編碼操作,
d.等待直到FLASH 狀態(tài)準(zhǔn)備好,即內(nèi)部頁(yè)編碼已完成。
(5)設(shè)置鏡像升級(jí)完成標(biāo)志。
燒寫成功時(shí)會(huì)設(shè)置升級(jí)完成標(biāo)志,在任何步驟發(fā)生錯(cuò)誤時(shí),也會(huì)設(shè)置升級(jí)完成標(biāo)志,此時(shí)CPU模塊應(yīng)根據(jù)燒寫過(guò)程返回的狀態(tài)檢測(cè)是否有錯(cuò)誤發(fā)生,若有則顯示錯(cuò)誤信息,否則顯示各階段的完成標(biāo)志。
SPIFlash內(nèi)FPGA程序更新過(guò)程需要考慮并串轉(zhuǎn)換模塊SpiSerDes,此模塊和燒寫控制模塊連接。SPI總線有兩個(gè)雙向串行數(shù)據(jù)線,SpiSerDes模塊在向SPI總線串行化1字節(jié)的同時(shí),將SPI總線發(fā)來(lái)的1字節(jié)輸入數(shù)據(jù)并行化。SpiSerDes模塊的4個(gè)引腳必須連接到已連接SPIFlash的FPGA引腳上。其中CCLK引腳作為在線燒寫時(shí)鐘,默認(rèn)為FPGA配置時(shí)鐘專用管腳,在上電配置完成后默認(rèn)不能作為普通管腳使用,如果想在配置之后將CCLK用作在線燒寫時(shí)鐘,即用作普通管腳,則需要將連向SPI時(shí)鐘的時(shí)鐘信號(hào)輸入到STARTUPE原語(yǔ)中,并且不需要對(duì)CCLK做額外的約束。
圖6展示了FPGA程序燒寫模塊仿真時(shí)序圖,update的bin數(shù)據(jù)分三幀傳遞給FPGA的RAM,F(xiàn)PGA將每幀數(shù)據(jù)燒寫到SPIFlash的update鏡像區(qū)域,并且在第三幀數(shù)據(jù)送進(jìn)SPIFlash之后繼續(xù)傳遞默認(rèn)字節(jié)“0xFF”,當(dāng)寫滿SPIFlash的update鏡像區(qū)域時(shí),在線更新結(jié)束。
圖6 FPGA程序燒寫模塊仿真時(shí)序圖
在整機(jī)軟件界面上開(kāi)辟一個(gè)程序更新界面,如圖7所示。界面顯示有當(dāng)前版本號(hào)、更新版本號(hào)、提示信息和可能錯(cuò)誤信息以及更新檢測(cè)和開(kāi)始更新兩個(gè)按鈕。當(dāng)保存著待更新update鏡像bin文件的U盤或SD卡連接儀器設(shè)備后,點(diǎn)擊更新檢測(cè)按鈕,軟件會(huì)檢測(cè)并顯示待更新update鏡像bin文件的版本,點(diǎn)擊開(kāi)始更新按鈕即可執(zhí)行在線更新。在更新過(guò)程中若發(fā)生錯(cuò)誤,則更新過(guò)程立即停止,并在界面上顯示錯(cuò)誤信息,否則更新結(jié)束時(shí),界面會(huì)提示更新成功。
圖7 SPIFlash內(nèi)FPGA程序在線更新用戶界面
在某已投產(chǎn)的項(xiàng)目中,在線更新功能取得良好的應(yīng)用效果,得到技術(shù)人員的肯定。項(xiàng)目FPGA程序編譯文件大小約為10MB,一次完整的在線更新時(shí)間不到2分鐘,如表1所示。
表1 SPIFlash內(nèi)FPGA程序在線更新運(yùn)行時(shí)間
本文在7系列FPGA配置過(guò)程具備MultiBoot和FallBack機(jī)制的基礎(chǔ)上,設(shè)計(jì)一種通過(guò)主機(jī)界面即可操作的SPIFlash內(nèi)FPGA程序在線程序更新方案。本方案充分利用一般儀器上CPU模塊與FPGA之間有PCIe總線連接,并且FPGA和SPIFlash直接連接的特點(diǎn),讓CPU模塊通過(guò)PCIe總線將FPGA程序數(shù)據(jù)分包傳遞給FPGA,然后由FPGA燒寫進(jìn)SPIFlash,這樣使用較小的RAM空間即可實(shí)現(xiàn)SPIFlash內(nèi)較大update程序鏡像更新。并且本方法不影響設(shè)備正常工作,不增加額外硬件電路,不需要連接程序燒寫器,僅僅需要裝載FPGA程序的U盤等存儲(chǔ)設(shè)備即可在通過(guò)操作燒寫界面執(zhí)行SPIFlash內(nèi)FPGA程序更新,非常便于用戶遠(yuǎn)程更新設(shè)備程序,并大大降低了儀器設(shè)備FPGA程序升級(jí)的工作量。