ARM在線(xiàn)升級FPGA程序方法(逆向工程)
公司有款產(chǎn)品采用FPGA做處理器,需要 遠程升級 —— 不使用燒寫(xiě)器,通過(guò)網(wǎng)絡(luò )對其升級。領(lǐng)導提議既然程序是存儲在外部存儲器上的,那么能否通過(guò)EPCS4與ARM SPI 總線(xiàn)通信連接刷新FPGA程序呢?于是就有了下文的實(shí)踐。
要實(shí)現該功能有幾種方式:
1. 解析編譯出的FPGA下載文件jic、pof,將解析后的內容燒錄到EPCS4中。但是否這兩種文件格式公開(kāi)存儲結構呢?芯片廠(chǎng)商是否對此保密?
2. 直接讀取EPCS4的程序,燒錄到另一塊EPCS4中。但是否讀取的EPCS4內容以及根據FPGA序列號做了加密呢?
權衡任務(wù)安排時(shí)間,選擇第二種方案,畢竟就算第一種方案可行,也需要設計第二方案的讀寫(xiě)操作。 可喜的是這次逆向工程就這么搞定了。
具體實(shí)現
ARM用IO模擬SPI總線(xiàn)燒FPGA配置芯片EPCS4完成軟件升級,在TQ2440上測試,工程可以通過(guò)下面的 github連接獲得。該工程與TQ2440平臺定制,在其他平臺未必能運行,建議只看 BitOpt.h,EPCS4.c,EPCSxx.h,mainboot.c 幾個(gè)文件,其他無(wú)關(guān)代碼不必多看。
升級步驟:
1、 一塊已經(jīng)用下載器燒錄FPGA程序的EPCS4與ARM連接,ARM讀出EPCS4“所有扇區”數據保存到NandFlash中,然后拷貝到電腦備份。
2、 另一塊待燒錄的FPGA與ARM連接,將剛讀出的數據燒寫(xiě)進(jìn)去。
讀取的數據是最終執行的二進(jìn)制Bin文件,因為Altera開(kāi)發(fā)環(huán)境所生成的jic、pof與最終EPCS4內的內容不一樣(除非找到生成Bin的方法)。之所以讀取“所有扇區”數據是因為不知道實(shí)際Bin文件大小,干脆全部讀出。EPCS4存儲空間是512KB。IO模擬SPI時(shí)序的方式速度有限,讀/寫(xiě)512KB各需要40S,用SPI總線(xiàn)速度會(huì )快不少。該方法已經(jīng)在2塊FPGA里運行沒(méi)問(wèn)題,證明Bin文件并沒(méi)有在燒寫(xiě)過(guò)程中綁定FPGA芯片序列號。
演示:
啟動(dòng)后按“5”進(jìn)入EPCS4測試代碼。

按“N”將Bin文件從Nand拷貝到SDRAM的0x30200000,長(cháng)度512KB。

按“W”將0x30200000的數據燒錄到EPCS4中,寫(xiě)入后計算寫(xiě)入前數據校驗碼得0x00000039,然后再讀出EPCS4中“所有”數據,計算讀出內容的校驗碼也是0x00000039,比較校驗移植返回“Success?。?!”,否則返回“Check sum Error!!!”。

硬件連接:
升級過(guò)程中FPGA需要掉電,或者將FPGA與EPCSxx連接的引腳斷開(kāi),否則3個(gè)設備連接到共用信號線(xiàn)無(wú)法通信。
EPCS4驅動(dòng)編寫(xiě)、移植注意事項:
1、 演示代碼驅動(dòng)部分EPCS4.c、EPCSxx.h采用的是IO模擬SPI總線(xiàn)協(xié)議,不能直接使用,需要看的是各函數實(shí)現的邏輯,照搬到WinCE上。該代碼可以直接兼容EPCS4、EPCS16、EPCS64。對于EPCS1、EPCS128只要修改頁(yè)面大小、扇區大小相關(guān)宏。EPCS1、EPCS128不支持epcs_read_silicon_id(具體查看EPCSxx芯片手冊)。
2、 Mainboot.c文件只需要看3個(gè)函數:epcs4_write_file()、epcs4_read_file()、check_sum(),其中讀寫(xiě)函數必須根據具體芯片容量而定,可以通過(guò)讀取芯片ID而獲得芯片類(lèi)型,動(dòng)態(tài)修改燒寫(xiě)代碼容量。
3、 SPI時(shí)序CLK脈沖寬度“能寬不能窄”,芯片手冊建議脈沖跨度大于20nS,演示代碼中IO模擬SPI速率很低,脈沖寬度3uS,所以未加任何延時(shí)。據說(shuō)2440SPI總線(xiàn)速率能達到20MB,所以有必要適當添加延時(shí),或配置脈沖寬度,
4、 Read Status命令可以再任何時(shí)候發(fā)送,返回0表示處于空閑狀態(tài)(具體狀態(tài)意義查看芯片手冊),發(fā)送Read Status以外的命令必須確定芯片處于空閑狀態(tài),否則命令被拋棄。
5、 “每次”發(fā)送寫(xiě)、擦除命令前必須發(fā)送寫(xiě)使能命令
6、 發(fā)送“連續”讀、寫(xiě)字節命令最大長(cháng)度只能在一個(gè)Page范圍之內,讀寫(xiě)到Page末地址若還有數據請求,多余的部分被芯片拋棄。
7、 不允許在一個(gè)CS周期內發(fā)送兩個(gè)命令
正確的命令是:CS拉低——發(fā)送命令1——CS拉高;CS拉低——發(fā)送命令2——CS拉高;
不允許:CS拉低——發(fā)送命令1——發(fā)送命令2——CS拉高;
建議移植代碼測試步驟
1、讀取芯片ID號(silicon ID或Device Identification)
2、如果讀取錯誤的話(huà)用示波表查看時(shí)序,保證CLK脈沖周期大于40ns,以及MOSI發(fā)送的內容正確(Read silicon ID——0xAB或Read silicon ID——0x 9F)。
3、讀取扇區內容。
4、擦除、寫(xiě)入(寫(xiě)入前必須先擦除)所有扇區,并讀出寫(xiě)入數據。
5、讀取EPCSxx數據在NandFlash里建立bin文件,最后燒寫(xiě)到EPCSxx能運行
6、與節點(diǎn)管理器添加更新FPGA通信協(xié)議
評論