這也是《FPGA實現(xiàn)串口升級及MultiBoot》系列中的一篇文章,作為一個專題單獨出來說明。
本篇文章分為三個主題:固化、啟動和MultiBoot實現(xiàn)。
固化分為SPI和BPI FLASH兩種情況;啟動分為SREC解析及加快啟動模式的ELF直讀;最后就是MultiBoot實現(xiàn)的時候應(yīng)該注意什么。
固化
軟核的固化和外部FLASH及應(yīng)用程序大小有很大關(guān)系。小應(yīng)用程序,使用BRAM即可運行,固化的時候和邏輯一起固化即可運行,這時候不管外部是什么類型FLASH,和邏輯固化一樣。大應(yīng)用程序,需要用到外部DDR,就需要兩個啟動程序,一個小的Bootloader,和邏輯一起啟動,起來后從外部FLASH讀取相應(yīng)的應(yīng)用程序放到DDR里運行,這時候就要根據(jù)不同的FLASH,設(shè)計相應(yīng)的讀取邏輯及應(yīng)用。下面我們根據(jù)不同的FLASH類型進行相應(yīng)的說明。
SPI FLASH
小應(yīng)用程序
小應(yīng)用程序,比如串口通信,IIC、SPI等配置通信,不占用多少STACK_SIZE和HEAP_SIZE,用內(nèi)部BRAM就可運行,這時候?qū)?yīng)用程序的LD設(shè)置為運行到BRAM即可,生成elf后就可以將其和邏輯的BIT融合在一起生成新的BIT,正常生成MCS即可燒寫。
elf和bit融合成新的BIT,有兩種方式,下面詳細介紹:
調(diào)試階段
調(diào)試階段通過Vitis或者SDK一步即可生成新的BIT:
即在vitis工作目錄-->應(yīng)用程序目錄-->_ide-->bitstream-->download.bit
該bit就是融合后的BIT,接下來可以使用Vitis/SDK或者Vivado進行下載。
穩(wěn)定階段
應(yīng)用程序一般比較簡單,所以調(diào)試穩(wěn)定后,就可以將elf交給邏輯端,讓他們繼續(xù)折騰。
Vivado中在生成bit前,通過下面步驟將elf和軟核關(guān)聯(lián)起來,后面Vivado生成bit后,就是包含了軟核程序的BIT,繼續(xù)后續(xù)的固化工作即可。
大應(yīng)用程序
大應(yīng)用程序就會復(fù)雜很多,主要是建立軟核讀取外部FLASH的通道。
大的應(yīng)用程序需要運行到SDRAM中,節(jié)省內(nèi)部BRAM,這里的“大”并不是我們說的elf文件大,而是需要的運行空間大。
其實可以完全不需要內(nèi)部BRAM也可以運行大應(yīng)用程序程序,不過制作過程比較復(fù)雜,我們這次還是需要一點內(nèi)部BRAM啟動bootloader。
整個流程框圖如下:
首先這種方式需要三個文件:1、FPGA的bit文件(需要包含F(xiàn)LASH的讀寫控制器);2、bootloader 生成的elf文件;3、大應(yīng)用應(yīng)用程序的ELF文件。
這里要用到比較重要的IP-axi_quad_spi(可以自己按照需求寫IP),將IP按照下面設(shè)置進行設(shè)置:
主要是使能STARTUP原語。
PS:7系列的在IP內(nèi)部使能STARTUP即可,對于U+系列由于FLASH的IO位于BANK0,需要在頂層再使用STARTUP3原語進行IO引出(IP內(nèi)部雖然也使用了原語,但是我調(diào)試的時候只有在頂層添加STARTUP3原語才能進行通信,不清楚是BUG還是沒設(shè)置好,按照官方說明使用方式也是要在頂層再添加原語)。
邏輯端添加上訴IP即可,接下來是應(yīng)用程序設(shè)計。
在SDK或者Vitis中添加下面BootLoader程序:
接下來要修改第一個地方:
就是這個起始地址,其中0x44A00000就是Vivado中IP的基地址,0x80000是從FLASH讀取的地址,即應(yīng)用存放在FLASH中的地址,該地址要和生成MCS時候地址相匹配。
第二個需要注意的地方就是BootLoader要放到BRAM里運行,查看以下LD:
這樣就可以和上面小應(yīng)用程序一樣,隨著邏輯端一起啟動。
接下來就是固化,固化也是分為兩個階段。
調(diào)試階段
調(diào)試階段首先將大應(yīng)用程序放到FLASH相應(yīng)的偏移地址上,通過以下工具可以直接燒寫:
這里先選擇大應(yīng)用程序生成的elf,然后選擇燒寫的偏移地址(按照BootLoader里設(shè)置的偏移地址進行設(shè)置),然后選擇對應(yīng)的FLASH,最后一定要勾選Convert ELF to bootloadable SREC format and program,這是目前官方驅(qū)動程序能讀取的二進制結(jié)構(gòu)-SREC。
關(guān)于怎么減少啟動時間我們后面會單獨討論。
注意點1:修改驅(qū)動
如果不能讀取FLASH,那么需要修改驅(qū)動文件。Board support Package setting,修改xilisf,設(shè)置serial_flash_family(根據(jù)FLASH廠家修改)serial_flash_interface根據(jù)需求修改。
注意點2:讀取超時
增加等待flash初始化時間:
原位置:
修改
/* *InitializetheSerialFlashLibrary. */ volatileintwait; do { Status=XIsf_Initialize(&Isf,&Spi,ISF_SPI_SELECT,IsfWriteBuffer); if(Status!=XST_SUCCESS){ xil_printf("XIsf_initializefailed!Status=%d ",Status); for(wait=0;wait100000;?wait++); ???for?(wait=0;wait?100000;?wait++); ??} ?}while(Status?!=?XST_SUCCESS?);
注意點3:讀取速度
某些國產(chǎn)FLASH的速度遠低于進口FALSH,所以注意看下數(shù)據(jù)手冊,控制好ext_spi_clk,同時下圖還有一個分頻系數(shù):
穩(wěn)定階段
如果BootLoader能夠引到啟動后,可以將BootLoader的ELF添加到Vivado工程中,這樣在大應(yīng)用程序需要重建后無需每次都建立BootLoader工程進行調(diào)試。同時axi_quad_spi不更改(基地址不變)情況下,BootLoader都不需要修改。
BPI FLASH
小應(yīng)用程序
小應(yīng)用程序和SPI的一樣,不隨著外圍FLASH不同而改變,就不贅述了。
大應(yīng)用程序
大應(yīng)用程序就更復(fù)雜一些,也是需要建立軟核讀取外部FLASH的通道。
接下來我們按照另一個思路講解BPI FLASH大應(yīng)用程序的固化。上面我們說過大應(yīng)用程序的固化需要三個文件:1、FPGA的bit文件(需要包含F(xiàn)LASH的讀寫控制器);2、bootloader 生成的elf文件;3、大應(yīng)用程序的ELF文件。我們按照順序講解每個文件生成需要的必要條件:
FPGA的bit文件
FPGA設(shè)計中需要增加對FLASH控制,對于BPI FLASH,官方推薦AXI-EMC IP,通過AXI-MEM映射外部FLASH,這個IP可以控制常見的BPI FLASH(可配置參數(shù)很低),對于不能控制的FLASH,需要自己寫控制器+控制驅(qū)動。
AXI_EMC IP 概述
AXI_EMC是FPGA的一個ip core,axi 外部存儲控制器,支持sram,nor flash ,psram,cellularRAM,IP核使用AXI4接口,支持32bit和64bit的數(shù)據(jù)位寬,支持以下memory type,即:
異步SRAM
同步SRAM
串行flash or并行nor flash
偽靜態(tài)隨機存儲器
每個emc控制器支持掛接4個存儲設(shè)備
來源:pg100-figure1-1
信號連接
我們這次使用的BPI FLASH為S29GL01GSXXXX,可以通過AXI-EMC 控制,具體在FPGA中的連線如下:
主要將這個IP連到MB上,外接引腳比較重要,因為IP要兼容的東西比較多,所以引出來的引腳比較多,對于不同的外設(shè)需要連接不同的引腳,對于本次設(shè)計的引腳連接如下表所示:
圖中紅線部分需根據(jù)表進行連接
IP界面時序參數(shù)配置
(1)第一頁
默認配置即可,如果使用比較大的內(nèi)存則可選總線位寬為64位,我們控制FLASH,默認32位即可:
這里注意以下,如果使用U+系列,這個IP會在下面位置有個使能STARTUP3原語的選項:
使能后和SPI FLASH一樣,需要在頂層添加STARTUP原語引出BPI的DQ0~DQ3。這里說下原因,因為7系列FPGA的DQ0~DQ3是在BANK14,而U+是在BANK0上,同時官方IP可能有BUG,導(dǎo)致需要2次使用原語。
(2)第二頁
這一頁的設(shè)置是核心,需要根據(jù)FLASH數(shù)據(jù)手冊進行配置:
Memory Type
支持Sync SRAM, Async SRAM, Linear Flash, Page Mode Flash, PSRAM, or Micron Flash
Data Width
Memory 數(shù)據(jù)位寬,也就是接的存儲設(shè)備的數(shù)據(jù)位寬,支持8,16,32,64位位寬
Parity
可以設(shè)置為No parity,Odd Parity,or Even Parity,只有Memory Type為Sync SRAM時才能設(shè)置
Delay Mode
可以設(shè)置為Flow-Through model or Pipeline Model,只有Memory Type為Sync SRAM時才能設(shè)置
Read CE Low to Data Valid Period
根據(jù)描述,該參數(shù)在不同的memory type下含義不同,如果是flash,則和tELQV的值相等,這里以Page Mode Flash為例說明,基本上也就是片選拉低的時間,其他類型的存儲設(shè)備沒有驗證,暫不清楚,以flash型號為S29GL01GSXXX(容量大小:128Mbyte)為例,根據(jù)芯片手冊中的描述:
該芯片讀時序如下:
對該芯片來說,該參數(shù)值就是tCE,即100ns = 100000ps
Read Address Valid to Data Valid Period
這里的意思為讀地址在數(shù)據(jù)有效前的保持時間,不是片選保持的時間,對于S29GL01GSXX來說,就是tAVQV的值,和描述的一樣,即為100ns = 100000ps,如上圖所示。
Page Access Period
根據(jù)描述的含義,對于Page Mode Flash來說就是訪問一頁需要的時間,以S29GL01GSXX為例,也就是tPACC,為25ns,如下:
Read CE High to Data Bus HZ Period
該參數(shù)的含義是指片選(CE)從有效變?yōu)闊o效后,至少要保持多長時間,即從低變高后,要保持多長時間的高電平,以S29GL01GSXX為例,就是圖中的tDF也就是tEHQZ,為20ns
Read OE High to Data Bus HZ Period
和上邊參數(shù)一樣,指OE高電平保持的時間,也就是上圖中的tDF,為20ns
AXI Read Timing
根據(jù)AXI EMC IP核手冊的page47頁得知以上讀時序圖,結(jié)合“IP核參數(shù)默認值”查看
AXI Write Timing
根據(jù)AXI EMC IP核手冊的page47頁得知以上寫時序圖,結(jié)合“IP核參數(shù)默認值”查看
IP核參數(shù)默認值:
Write Cycle Period
根據(jù)描述,AXI EMC core根據(jù)該參數(shù)去保持CE為低的時間,但不是指CE保持的時間,以S29GL01GSXX為例,值等于tWC,即60ns,如下
Write Enable Minimum Pulse Width
該參數(shù)指片選(WE)保持的最小時間,以S29GL01GSXX為例,值等于tWP,即最小25ns
Write Phase Period
該參數(shù)表示兩個WE之間的最小間隔,以S29GL01GSXX為例,值等于tWPH,即最小20ns
Write WE High to Data Bus LZ Period
該參數(shù)表示在一個寫周期里,寫使能(WE)到數(shù)據(jù)總線低阻的時間,或者寫到讀的恢復(fù)時間(可能理解的不正確,關(guān)于此參數(shù)配置時請謹慎),以S29GL01GSXX為例,使用的默認值,即0ps。
Write Recovery Period for Flash Memory
這個參數(shù)應(yīng)該指的是數(shù)據(jù)寫完后,WE還需要保持多少個時鐘周期的時間,這里使用默認值,根據(jù)下圖,此參數(shù)小于等于twrr,具體多少不知道,個人理解大于等于tWPH應(yīng)該就可以了。
IP其他界面默認即可,地址分配界面將IP尋址空間大小設(shè)置成實際FLASH大小,如下:
編譯后導(dǎo)出bit到SDK或者Vitis,就可以制作BootLoader.
以上參數(shù)解釋,參考下面的博文:
https://blog.csdn.net/qq_33166886/article/details/112490916
這里要用到比較重要的IP-axi_quad_spi(可以自己按照需求寫IP),將IP按照下面設(shè)置進行設(shè)置:
BootLoader制作
打開sdk或者Vitis,新建一個SREC的工程。這個就是傳說中啟動文件。
其中1是用來制作BPI FALSH的啟動文件,2是用來制作SPI FLASH啟動文件的。
修改FLASH的鏡像地址。地址不是亂寫的。是根據(jù)你的mcs文件大小,文件大小在runs/imp/ 文件夾下的 prm 文件上有告知。后面接上的。然后生成文件。注意這個地址也是你后面真正運行的elf地址寫入。
也可以按照prm文件后續(xù)接上elf文件:
bootloader工程,注意選擇ld看鏈接表設(shè)定。不要把代碼和數(shù)據(jù)放在DDR上面。
然后編譯工程。生成elf文件。然后按照之前的方式將BootLoader elf和vivado生成的bit合成一個新的bit。
剩下的步驟和之前SPI FLASH一樣了,就不贅述了。
啟動
固化完成了,接下來就是啟動了。小應(yīng)用程序和FPGA啟動一起,所以就不說明了,重點介紹大應(yīng)用程序。
大應(yīng)用程序如果使用官方的BootLoader,在讀取大應(yīng)用到DDR中時,是讀取的SREC,那么為什么要讀取SREC,SREC文件有什么特點?我們接下來開始揭開面紗。
SREC文件
SREC文件是帶有程序的地址信息和數(shù)據(jù)校驗功能,所以在讀取SREC文件時是連讀連校驗并且要轉(zhuǎn)譯,所以在讀取SREC時候會很慢,好處就是可以避免很多因為文件錯誤導(dǎo)致功能異常。結(jié)構(gòu)如下:
Record type | Byte count | Address | Data | Checksum |
---|
SREC 格式文件由一系列ASCII文本記錄組成。這些記錄從左到右具有以下結(jié)構(gòu):
a.Record type——2個字節(jié)ASCII字符,第一個字符為‘S’(ASCII 0x53),第二個字符為ASCII數(shù)字的‘0’~‘9’(ASCII 0x30 到 0x39)
b.Byte count——兩個十六進制數(shù)字(“00”至“FF”),表示記錄其余部分(地址 + 數(shù)據(jù) + 校驗和)后面的字節(jié)數(shù)(十六進制數(shù)字對)。此字段的最小值為 3(16 位地址字段加 1 個校驗和字節(jié)時為 2),最大值為 255(0xFF)。“00”/“01”/“02”為非法值。
c.Address——大端地址——4/6/8個16進制的ASCII數(shù)字,取決于Record type的類型
d.Data——數(shù)據(jù) ——2*n個16進制的ASCII數(shù)字(n字節(jié)數(shù)據(jù))
e.Checksum ——2個16進制的ASCII數(shù)字,即字節(jié)數(shù)、地址和數(shù)據(jù)字段的兩個十六進制數(shù)字對所表示的值之和的補碼的最低有效字節(jié)。在C 編程語言中,總和通過以下方式轉(zhuǎn)換為校驗和:0xFF - (sum & 0xFF)
圖片來源:https://en.wikipedia.org/wiki/SREC_(file_format)
ELF和SREC對比:
ELF轉(zhuǎn)換成SREC
如果使用官方的BootLoader,那么SREC格式是必不可少的,而SDK或者Vitis只能生成ELF文件,下面介紹幾種方式將ELF轉(zhuǎn)換成SREC。
方式一:通過XSCT Console
將elf轉(zhuǎn)換成SREC format,打開Xilinx—> XSCT Console。
通過cd 命令進入elf所在的目錄:
輸入:mb-objcopy -O srec app.elf app.srec
就會在ELF所在目錄生成SREC文件。
方式二:自動轉(zhuǎn)換
在應(yīng)用上右擊,屬性,打開屬性窗口。在圖中位置添加命令:
mb-objcopy -O srec {ProjName}.srec
這樣每次在APP編譯完成后就會將ELF自動轉(zhuǎn)換成SREC(在ELF目錄里)。
方式二:使用命令手動設(shè)置
使用下圖中兩個腳本,cd到elf文件位置后,使用mb-object命令完成轉(zhuǎn)換:
最后這種方式和方式一類似,好處就是可以使用Win下的腳本調(diào)用,然后生成一鍵腳本。
加快啟動
從上面的分析可知,在讀取SREC時候會進行很多無關(guān)操作,導(dǎo)致啟動時間大大增加,尤其是大應(yīng)用程序生成的ELF比較大(SREC也會比較大)的時候,這個時間肯定不能忍受的。
方式一:減少打印
在進行調(diào)試的時候,BootLoader會有讀取進程通過串口打印,這一操作方便調(diào)試的時候快速進行問題定位,完成調(diào)試的時候,可以將打印去掉,注釋掉下圖位置語句即可:
更改讀取方式
我們可以減少讀取過程中的轉(zhuǎn)譯和校驗等過程,直接引導(dǎo)搬運FLASH的elf文件至DDR,減少“中間商賺差價”的時間,可大大提高啟動速度,相關(guān)的工程可以參考下面的鏈接。
https://github.com/henrikbrixandersen/elf-bootloader?_ga=2.259888963.835186866.1691390458-2003547133.1691118205
在eb-config.h文件中更改實際用到的FLASH地址以及匹配FLASH信息,主要就是修改對應(yīng)FLASH的opration指令以及dummy cycle,可以根據(jù)你使用的FLASH類型查閱數(shù)據(jù)手冊。
MultiBoot實現(xiàn)注意點
在小應(yīng)用程序時候其實和純FPGA應(yīng)用一樣,沒什么大的區(qū)別,沒什么注意的。主要在大應(yīng)用程序:
大應(yīng)用程序主要包含上面幾個文件組成(根據(jù)自己需求可能有所不同)。考慮到升級過程中傳輸完成擦除FLASH后及突然斷電等特殊情況,所以需要考慮CRC error(突然斷電)、IDCODE error(升級包制作錯誤)、Watchdog timer time-out error(擦除FLASH后未升級、突然斷電)三種情況。
Golden區(qū)無需變動,主要在M區(qū)的程序,在升級APP時候面對上面的情況怎么操作?因為目前的MultiBoot機制只能在FPGA邏輯層進行操作,如果APP程序錯誤可能觸發(fā)不了回退機制。
這里提供一個思路,就是對M區(qū)APP增加CRC校驗,BootLoader在讀取APP的ELF或者SREC時如果CRC校驗錯誤,那么就破壞M區(qū)的FPGA程序(FLASH),讓FPGA程序啟動時候觸發(fā)四種錯誤的任何一種,就可以回退到Golden區(qū)再進行升級。
總結(jié)
總結(jié)就下面的一張圖了:
關(guān)于這部分內(nèi)容,大家有什么建議或者經(jīng)驗,歡迎大家評論區(qū)留言討論~
-
應(yīng)用程序
+關(guān)注
關(guān)注
38文章
3292瀏覽量
57909 -
軟核
+關(guān)注
關(guān)注
0文章
14瀏覽量
15880 -
固化
+關(guān)注
關(guān)注
0文章
167瀏覽量
10522
原文標題:一篇文章搞懂軟核(MicroBlaze)的固化和啟動
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術(shù)江湖】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論