ARM在線升級FPGA程序方法(逆向工程)
公司有款產(chǎn)品采用FPGA做處理器,需要 遠(yuǎn)程升級 —— 不使用燒寫器,通過網(wǎng)絡(luò)對其升級。領(lǐng)導(dǎo)提議既然程序是存儲(chǔ)在外部存儲(chǔ)器上的,那么能否通過EPCS4與ARM SPI 總線通信連接刷新FPGA程序呢?于是就有了下文的實(shí)踐。
要實(shí)現(xiàn)該功能有幾種方式:
1. 解析編譯出的FPGA下載文件jic、pof,將解析后的內(nèi)容燒錄到EPCS4中。但是否這兩種文件格式公開存儲(chǔ)結(jié)構(gòu)呢?芯片廠商是否對此保密?
2. 直接讀取EPCS4的程序,燒錄到另一塊EPCS4中。但是否讀取的EPCS4內(nèi)容以及根據(jù)FPGA序列號做了加密呢?
權(quán)衡任務(wù)安排時(shí)間,選擇第二種方案,畢竟就算第一種方案可行,也需要設(shè)計(jì)第二方案的讀寫操作。 可喜的是這次逆向工程就這么搞定了。
具體實(shí)現(xiàn)
ARM用IO模擬SPI總線燒FPGA配置芯片EPCS4完成軟件升級,在TQ2440上測試,工程可以通過下面的 github連接獲得。該工程與TQ2440平臺(tái)定制,在其他平臺(tái)未必能運(yùn)行,建議只看 BitOpt.h,EPCS4.c,EPCSxx.h,mainboot.c 幾個(gè)文件,其他無關(guān)代碼不必多看。
升級步驟:
1、 一塊已經(jīng)用下載器燒錄FPGA程序的EPCS4與ARM連接,ARM讀出EPCS4“所有扇區(qū)”數(shù)據(jù)保存到NandFlash中,然后拷貝到電腦備份。
2、 另一塊待燒錄的FPGA與ARM連接,將剛讀出的數(shù)據(jù)燒寫進(jìn)去。
讀取的數(shù)據(jù)是最終執(zhí)行的二進(jìn)制Bin文件,因?yàn)锳ltera開發(fā)環(huán)境所生成的jic、pof與最終EPCS4內(nèi)的內(nèi)容不一樣(除非找到生成Bin的方法)。之所以讀取“所有扇區(qū)”數(shù)據(jù)是因?yàn)椴恢缹?shí)際Bin文件大小,干脆全部讀出。EPCS4存儲(chǔ)空間是512KB。IO模擬SPI時(shí)序的方式速度有限,讀/寫512KB各需要40S,用SPI總線速度會(huì)快不少。該方法已經(jīng)在2塊FPGA里運(yùn)行沒問題,證明Bin文件并沒有在燒寫過程中綁定FPGA芯片序列號。
演示:
啟動(dòng)后按“5”進(jìn)入EPCS4測試代碼。
按“N”將Bin文件從Nand拷貝到SDRAM的0x30200000,長度512KB。
按“W”將0x30200000的數(shù)據(jù)燒錄到EPCS4中,寫入后計(jì)算寫入前數(shù)據(jù)校驗(yàn)碼得0x00000039,然后再讀出EPCS4中“所有”數(shù)據(jù),計(jì)算讀出內(nèi)容的校驗(yàn)碼也是0x00000039,比較校驗(yàn)移植返回“Success?。?!”,否則返回“Check sum Error!!!”。
硬件連接:
升級過程中FPGA需要掉電,或者將FPGA與EPCSxx連接的引腳斷開,否則3個(gè)設(shè)備連接到共用信號線無法通信。
EPCS4驅(qū)動(dòng)編寫、移植注意事項(xiàng):
1、 演示代碼驅(qū)動(dòng)部分EPCS4.c、EPCSxx.h采用的是IO模擬SPI總線協(xié)議,不能直接使用,需要看的是各函數(shù)實(shí)現(xiàn)的邏輯,照搬到WinCE上。該代碼可以直接兼容EPCS4、EPCS16、EPCS64。對于EPCS1、EPCS128只要修改頁面大小、扇區(qū)大小相關(guān)宏。EPCS1、EPCS128不支持epcs_read_silicon_id(具體查看EPCSxx芯片手冊)。
2、 Mainboot.c文件只需要看3個(gè)函數(shù):epcs4_write_file()、epcs4_read_file()、check_sum(),其中讀寫函數(shù)必須根據(jù)具體芯片容量而定,可以通過讀取芯片ID而獲得芯片類型,動(dòng)態(tài)修改燒寫代碼容量。
3、 SPI時(shí)序CLK脈沖寬度“能寬不能窄”,芯片手冊建議脈沖跨度大于20nS,演示代碼中IO模擬SPI速率很低,脈沖寬度3uS,所以未加任何延時(shí)。據(jù)說2440SPI總線速率能達(dá)到20MB,所以有必要適當(dāng)添加延時(shí),或配置脈沖寬度,
4、 Read Status命令可以再任何時(shí)候發(fā)送,返回0表示處于空閑狀態(tài)(具體狀態(tài)意義查看芯片手冊),發(fā)送Read Status以外的命令必須確定芯片處于空閑狀態(tài),否則命令被拋棄。
5、 “每次”發(fā)送寫、擦除命令前必須發(fā)送寫使能命令
6、 發(fā)送“連續(xù)”讀、寫字節(jié)命令最大長度只能在一個(gè)Page范圍之內(nèi),讀寫到Page末地址若還有數(shù)據(jù)請求,多余的部分被芯片拋棄。
7、 不允許在一個(gè)CS周期內(nèi)發(fā)送兩個(gè)命令
正確的命令是:CS拉低——發(fā)送命令1——CS拉高;CS拉低——發(fā)送命令2——CS拉高;
不允許:CS拉低——發(fā)送命令1——發(fā)送命令2——CS拉高;
建議移植代碼測試步驟
1、讀取芯片ID號(silicon ID或Device Identification)
2、如果讀取錯(cuò)誤的話用示波表查看時(shí)序,保證CLK脈沖周期大于40ns,以及MOSI發(fā)送的內(nèi)容正確(Read silicon ID——0xAB或Read silicon ID——0x 9F)。
3、讀取扇區(qū)內(nèi)容。
4、擦除、寫入(寫入前必須先擦除)所有扇區(qū),并讀出寫入數(shù)據(jù)。
5、讀取EPCSxx數(shù)據(jù)在NandFlash里建立bin文件,最后燒寫到EPCSxx能運(yùn)行
6、與節(jié)點(diǎn)管理器添加更新FPGA通信協(xié)議
評論