1. FPGA固件升級方案
FPGA的硬件可編程性給設計帶來了很高的靈活性,基于FPGA的產品也會有更新或升級的需求,而且大多數情況下由于現場環境、人力物力成本的限制,無法通過下載器JTAG方式進行刷新程序,比如機房服務器中的FPGA加速卡或采集卡,無法隨便出入機房進行升級,FPGA部署在偏遠山區的基站或高高的通信塔臺等等場景,現場通過下載器JTAG方式升級固件,一方面影響用戶體驗和滿意度,另一方面又要耗費大量的人力物力。所以就有了FPGA遠程更新固件的需求,要滿足以下升級要求:
基本的固件升級功能,傳輸方式可基于常見的通訊協議,如串口、USB、CAN、網口、WiFi、藍牙、PCIe等協議來實現升級。
基本的防止變磚功能,即在升級過程中任何時刻,出現異常情況,如斷電,線纜斷開等,都應該能保證重新上電后,還可以再次完成升級流程,防止芯片變磚。
升級流程的優化,可靠的通訊協議,例如握手、校驗、應答等等,在滿足基本功能的情況下,更高的升級效率。
對于單片機來說,IAP固件升級有非常成熟的應用方案,升級方式也很豐富,尤其是在當前日益豐富的ARM芯片環境下,不同廠家的單片機升級程序之間進行移植也非常方便。
但是對于FPGA來說,IAP升級就比較復雜。目前Xilinx和Altera的FPGA都是基于RAM結構,內部沒有Flash存儲器,固件程序一般都存儲在外置的SPI Flash中,芯片上電之后,會先從Flash中讀取數據,并加載到FPGA內部RAM。
在程序加載完成之后,SPI Flash就可以被用戶執行讀寫操作,所以我們只需要在程序中實現對SPI Flash讀寫控制器就可以達到升級固件的目的。
固件通過串口或網口等傳輸協議發送到FPGA,FPGA將此數據寫入到SPI Flash,當完全寫入之后,重新上電執行的就是更新之后的程序。
這種方案理論上是可行的,但是有一個很大的風險,一旦在數據寫入的過程中斷電,或者線纜松動等異常情況發生,就會導致固件程序寫入不完整,那么在下次啟動時,程序就無法運行,FPGA變磚,拯救的辦法還是要通過最原始的下載器JTAG方式來恢復。
那可不可以像單片機那樣存儲兩套固件程序:Bootloader和Application,Bootloader程序永遠不會被破壞,從而保證不會變磚。
答案是肯定的,FPGA廠商也考慮到了這個問題,Xilinx 6和7系列FPGA上都提供了雙鏡像方案,即:Golden鏡像和Multiboot鏡像,簡稱為G鏡像和M鏡像,可以簡單理解為單片機的Bootloader和Application程序。
M鏡像就是用戶程序,G鏡像就是為了防止變磚而存在的備用固件,無論出現任何異常情況,都不會破壞G鏡像的數據內容,從而可以實現即使升級失敗,也不會變磚。
Xilinx FPGA還支持被動加載,即通過外置MCU來提供數據,從而實現程序升級,所以FPGA固件升級問題就轉換為單片機的程序文件升級,這種方式無需FPGA設計做任何修改,需要外部增加一顆MCU硬件支持,本文不做介紹。
本文介紹如何創建Golden鏡像和Multiboot鏡像,以及加載失敗Fallback回退的原理。
2. Golden鏡像和Multiboot鏡像簡介
Multiboot鏡像是用戶應用程序,Golden鏡像是用來保證升級過程中出現錯誤,設備不會變磚。
那么這兩個鏡像是如何啟動的呢?
首先Golden鏡像的最前面是Header部分,為了方便介紹,還是分為三個部分來介紹:Header、Golden和Multiboot,我們先來看看它們在SPI Flash中的存儲順序,以SPI Flash M25P16為例,存儲空間大小是16Mbit(2MByte),地址范圍是:0x0-0x1FFFFF
Header位于存儲器的頭部分,地址范圍是0-0x43,其中包括了G鏡像和M鏡像的24位起始地址。
G鏡像位于Header之后,地址范圍是:0x44-0xFFFFF
M鏡像位于Flash后半部分,地址范圍是:0x100000-0x1FFFFF
上電后的啟動順序是:
1.執行Header中的命令,Header中指定了Multiboot鏡像地址(0x100000),以及Multiboot加載失敗后回退地址,即Golden地址(0x44)。
2.跳轉到M鏡像地址,開始加載M鏡像,如果加載成功,則直接運行M鏡像
3.如果加載M鏡像地址遇到錯誤,比如沒有找到同步字、IDCODE或CRC校驗錯誤,則跳轉到Golden鏡像地址開始運行。
下圖介紹了Xilinx雙鏡像方案的啟動過程:
所以一般的應用方案是:
G鏡像實現對M鏡像所在的存儲區域寫操作
M鏡像的功能,除了用戶邏輯之后,也包括對M鏡像自身所在的存儲區域進行更新,即自更新。
Golden鏡像一旦確定,就不會更改,升級過程中也不會操作G鏡像所在的存儲區域,這樣就可以保證在M鏡像加載出錯時,G鏡像能夠正常加載。
下面以正常升級和升級出錯,來介紹兩個鏡像的加載過程:
正常升級:上電后會直接運行M鏡像程序,在程序運行過程中,接收到升級指令后,執行對M鏡像區域的更新,更新完成后,重新上電,因為此時M鏡像存儲區的數據已經被更新,所以重新上電后執行的是新的M鏡像程序,即可以達到程序升級的功能。
升級出錯:當M鏡像升級過程中出錯時,比如在執行數據寫入時斷電,此時會導致更新后的M鏡像區域不完整,那么在下次重新上電后,M鏡像加載失敗,會回退到G鏡像運行,因為G鏡像同樣包括更新功能,所以可以對M鏡像存儲區進行升級,即使升級過程中出錯,也不會對G鏡像造成影響,下次上電啟動仍然可以通過運行G鏡像來實現M鏡像更新。
接下來分別以XC6SLX9和XC7K325,演示在ISE和Vivado環境下,Golden鏡像和Multiboot鏡像如何生成。
3. ISE環境下實現(XC6SLX9)
為了區分G鏡像和M鏡像運行現象,分別新建兩個ISE工程,bit流生成選項都先保持默認配置,G鏡像功能為1個LED閃爍,M鏡像功能為4個LED閃爍,可以通過觀察LED閃爍的個數來區分當前運行的是哪個鏡像程序。
下面我們分別針對G鏡像和M鏡像進行bit流生成選項配置。
為了保證加載失敗時,重新執行配置過程,無論是G鏡像還是M鏡像都需要使能General Options->Retry Configuration if CRC Error Occurs:
G鏡像還需要配置以下兩個地方,M鏡像的地址需要根據所使用SPI Flash型號進行設置。
我所使用的是M25P16,整個存儲區域分為兩部分,前半部分存放Header和G鏡像(0x44),后半部分存放M鏡像,起始地址0x100000。
為什么前面有0x03呢?這是SPI Flash的讀操作命令,G鏡像的偏移量為什么是0x44呢?因為Header部分數據長度是0x44,G鏡像位于Header之后,G鏡像的起始地址就是0x44。
M鏡像需要配置以下兩個地方:
M鏡像還要加上一條配置參數:
-gnext_config_register_write:Disable
分別編譯生成G鏡像bit文件和M鏡像bit文件。
使用iMPACT合成mcs文件,以M25P16為例,G鏡像中已經包含了Header部分,所以選擇從0地址開始存儲,M鏡像從0x100000開始存儲。
分別加載對應的bit文件:
mcs文件燒錄到FPGA外部Flash之后,通電運行,會發現4顆在LED閃爍,說明當前是M鏡像在運行。
也可以通過人為修改M鏡像的內容來觸發G鏡像啟動,比如修改G鏡像中的IDCODE,或中間的數據部分導致CRC校驗錯誤觸發回退。
把修改之后錯誤的M鏡像bit文件和G鏡像bit文件重新合并成mcs,燒錄到FPGA,再次運行,會發現1個LED在閃爍,說明啟動M鏡像時遇到錯誤,回退到G鏡像運行。
啟動之后,也可以通過iMPACT讀取狀態寄存器來判斷是哪種方式觸發的回退。
正常的M鏡像啟動流程:
加載M鏡像時遇到CRC錯誤,啟動G鏡像:
4. Vivado環境下實現(XC7K325T)
Vivado和ISE環境略有不同,是在xdc約束文件中分別配置M鏡像和G鏡像,同樣,先建立兩個工程,M鏡像的功能是4個LED閃爍,G鏡像的功能是1個LED閃爍。
無論是G鏡像還是M鏡像,都需要添加以下QSPI總線寬度、加載時鐘頻率約束:
#bitstreamcompressionenable set_propertyBITSTREAM.GENERAL.COMPRESSTRUE[current_design] set_propertyCONFIG_VOLTAGE3.3[current_design] set_propertyCFGBVSVCCO[current_design] #qspiflashbuswidth=4 set_propertyBITSTREAM.CONFIG.SPI_BUSWIDTH4[current_design] set_propertyBITSTREAM.CONFIG.CONFIGRATE50[current_design]
G鏡像工程要單獨添加以下約束,指定M鏡像的存儲地址0x800000:
# golden工程需要配置以下Multiboot加載的地址:128Mbit/2 set_propertyBITSTREAM.CONFIG.NEXT_CONFIG_ADDR32'h00800000[current_design] set_propertyBITSTREAM.CONFIG.NEXT_CONFIG_REBOOTENABLE[current_design]
M鏡像工程要單獨添加以下約束:
#multiboot使能fallback功能 set_propertyBITSTREAM.CONFIG.CONFIGFALLBACKENABLE[current_design]
G鏡像和M鏡像bit文件合并成一個mcs:
燒錄之后會發現4顆LED閃爍,即當前是M鏡像運行。
M鏡像加載成功的狀態寄存器值:
修改M鏡像的數據部分,人為造成CRC錯誤啟動G鏡像,狀態寄存器的值:
5. Golden鏡像Header分析
下面對ISE環境下生成的G鏡像bin文件進行解析,看看G鏡像是怎么啟動的,Vivado生成的G鏡像命令略有不同。
G鏡像其實已經包含了Header部分,位于G鏡像的前面44個字節,之后才是G鏡像部分。
Header部分解析:
/*原始Header數據*/ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFAA99556631E1FFFF326100003281031032A1004432C1030032E1000030A10000330121003201005F30A1000E2000200020002000 /*Header數據解析*/ FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF AA995566//SyncWord 31E1//WRITE:ConfigurationWatchdogTimer. FFFF//0xFFFF 3261//WRITEM鏡像起始地址低16位=0x0000 0000 3281//WRITESPI操作命令0x03(READ),M鏡像起始地址高8位=0x10 0310 32A1//WRITEG鏡像起始地址低16位=0x0044 0044 32C1//WRITESPI操作命令0x03(READ),G鏡像起始地址高8位=0x00 0300 32E1//WRITE:User-definedregisterforfail-safescheme. 0000 30A1//WRITE:Type1Write1WordtoCMD 0000 3301//WRITE:Rebootmode. 2100 3201//WRITE:HouseCleanOptionregister. 005F 30A1//WRITE:IPROGCommand 000E//執行完此命令后,跳轉到M鏡像起始地址開始加載 2000//NOP 2000//NOP 2000//NOP 2000//NOP
關于Header部分命令的說明,可以參考文末的官方文檔,6系列對應UG380,7系列對應UG470。
可以看出,我們在ISE中G鏡像bit生成選項中的配置,比如M鏡像地址和G鏡像地址,最終體現在G鏡像bit文件的Header部分。
審核編輯:湯梓紅
-
FPGA
+關注
關注
1626文章
21665瀏覽量
601805 -
ARM
+關注
關注
134文章
9045瀏覽量
366806 -
FlaSh
+關注
關注
10文章
1621瀏覽量
147745 -
存儲器
+關注
關注
38文章
7452瀏覽量
163598 -
Xilinx
+關注
關注
71文章
2163瀏覽量
121004
原文標題:Xilinx FPGA Multiboot設計與實現(Spartan-6和Kintex-7示例)
文章出處:【微信號:mcu149,微信公眾號:電子電路開發學習】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論