0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

FSBL的數(shù)據(jù)段和代碼段如何連接?

FPGA之家 ? 來源:FPGA之家 ? 2023-07-06 09:50 ? 次閱讀

FSBL的數(shù)據(jù)段和代碼段如何鏈接

搞懂?dāng)?shù)據(jù)段和代碼段是如何被鏈接成一個(gè)二進(jìn)制文件的,這應(yīng)該是每一個(gè)ARM程序員必須搞清楚的一個(gè)事情。它會(huì)幫助程序員更加透徹的知道ARM是怎么被安排去工作的,所以數(shù)據(jù)段你和代碼段如何鏈接在一起,是我們搞懂FSBL的第一步。

建個(gè)Example工程,不要光顧著看,自己動(dòng)動(dòng)手掌握的更快。

要回答這個(gè)問題其實(shí)必須要建一個(gè)工程,相關(guān)的軟件操作流程可以參考各種開發(fā)板的實(shí)驗(yàn)手冊(cè),我這里見得描述一下:

現(xiàn)在VIVADO里面新建一個(gè)PL工程,可以自己搭,也可以用范例,本小節(jié)所涉及的PL來自范例,如下所示,整個(gè)PL實(shí)際上由:

1.1 ARM部分(硬核+外設(shè)),如圖中所示的processing_system,其中就包含了除APU以外,還有DDR,以及FIXED_IO。DDR好理解,就是連接外部DDR存儲(chǔ)器唄,那這個(gè)FIXED_IO是個(gè)啥呢?這個(gè)實(shí)際上就是arm的外設(shè),包含了Q-spi的必要引腳,也包括了Debug Info所需的串口??偠灾际茿RM的外設(shè)

1.2 復(fù)位部分,看名字就很好理解,該模塊專門用于所以Zynq的PL部分部件的復(fù)位

1.3 AXI Interconnect,這個(gè)模塊非常重要,簡單地說這就是一個(gè)總線解析器,一主(一個(gè)master AXI4)多從(兩個(gè)slave AXI4)。我們之前提到過,AXI4將會(huì)用于連接Zynq的PS(ARM部分)和PL(FPGA部分),這里就是一個(gè)例子,后面每一個(gè)Slave AXI4都連著一個(gè) Xilinx 的IP,或者是用戶自定義的具備AXI4的IP。這樣就簡單了,只要用戶定義的IP包含AXI4接口,同時(shí)將必要的可讀或者可寫數(shù)據(jù)映射到這個(gè)AXI4接口上,那么Zynq的ARM就能夠通過總線接觸到這些映射到總線上的數(shù)據(jù),it means the ARM could read/write its content mapped on the Bus of AXI4.

1.4 AXI GPIO & AXI BRAM Controller, 這兩個(gè)就是上述的Xilinx的IP,自帶有AXI4總線接口,這樣ARM就能夠通過總線解析器控制他們

1.5 實(shí)際的應(yīng)用,其實(shí)也不會(huì)比這個(gè)在復(fù)雜太多,只是再加一些自定義的IP

20e78094-1b9b-11ee-962d-dac502259ad0.png

2 利用這個(gè)范例,我們進(jìn)一步建立BSP,然后基于BSP建立APP(用戶程序),以及FSBL(范例,Zynq的加載程序),如下圖所示,其包含了app, bsp, platform, fsbl。通過任何一個(gè)開發(fā)版的用戶手冊(cè)都可以獲得完整的工程建立流程,這里不再贅述。

211498ea-1b9b-11ee-962d-dac502259ad0.png

3 其中bsp和fsbl里面,包含加載過程中所用到的所有源碼,下面一一解析。

查看鏈接文件,原來存儲(chǔ)空間是這樣有條不紊的被分配

點(diǎn)擊FSBL->src->lscript.ld,界面上將會(huì)呈現(xiàn)(這里的SDK是2017.2版本):

21217e70-1b9b-11ee-962d-dac502259ad0.png

感謝這個(gè)SDK的開發(fā)工具,使得用戶能夠以圖表的方式去查看數(shù)據(jù)段和代碼段的具體分布(以前都是通過直接看源碼,畢竟科技進(jìn)步了~),不過老程序員可能更喜歡看源碼,那我們就結(jié)合的看吧

這個(gè)圖主要呈現(xiàn)了三部分內(nèi)容:

定義了兩個(gè)存儲(chǔ)空間,包括offset和length,其源碼表達(dá)如下

213db66c-1b9b-11ee-962d-dac502259ad0.png

接下來定義了堆棧的大小,忘了啥是堆棧的可以自行百度復(fù)習(xí)一下

214b6f0a-1b9b-11ee-962d-dac502259ad0.png

接下來就是將FSBL編譯完成后的所有數(shù)據(jù)和代碼,按照一定的順序鏈接生成二進(jìn)制文件,舉個(gè)例子:

215cd24a-1b9b-11ee-962d-dac502259ad0.png

上面的源碼的作用是:

(1)定義FSBL的程序入口在== _vector_table ==

(2)將代碼段(.text*)鏈接到ps7_ram_0_S_AXI_BASEADDR的最前頭,而這里的代碼段實(shí)際包含了.vector等等內(nèi)容,我們查看一下.vectors到底是個(gè)啥吧,搜索一下把,結(jié)果就在bsp的asm_vectors.S(匯編文件里面)

2172fa16-1b9b-11ee-962d-dac502259ad0.png

進(jìn)到這個(gè)匯編程序,如下所示:

2182d77e-1b9b-11ee-962d-dac502259ad0.png

這里先關(guān)注兩個(gè)名字,一個(gè)就是==.vectors==,另一個(gè)就是==_vector_table==

看下面的源碼可知,.vectors就是一個(gè).section,相當(dāng)于下面所有的匯編源碼取了一個(gè)別名,叫做.vectors,這些源碼最終被放置到了上述位置!

第二個(gè)需要關(guān)注的是_vector_table,其實(shí)際上就是全局變量(看下面的源碼.globl _vector_table ),這個(gè)全局變量在這里就是一個(gè)指針,指向了B_boot 這個(gè)操作。

同時(shí)回過頭看上面的源碼ENTRY(_vector_table),這就是定義了FSBL的程序入口,也就是cpu執(zhí)行的第一條指令保存在 _vector_table -----> B_boot

這里可以簡單的小結(jié)一下, FSBL執(zhí)行的第一條指令就是B_boot,這是通過查看(編寫)FSBL->src->lscript.ld才獲悉的,可想而知這個(gè)鏈接文件有多重要,后期等我們更加熟悉,可以嘗試一下取修改它,這里做個(gè)記號(hào),繼續(xù)往下走!

ARM要開始運(yùn)行FSBL了,然而并不是main()

上面已經(jīng)提及實(shí)際FSBL程序最先被執(zhí)行的語句是B_boot,這是一條匯編指令,意思就是說跳轉(zhuǎn)到 _boot程序塊,同時(shí)轉(zhuǎn)跳指令B是無需返回的,所以后續(xù)BUndefined啥的實(shí)際上并不會(huì)被執(zhí)行,看一下**_boot**是什么:

218f0936-1b9b-11ee-962d-dac502259ad0.png

匯編語言不是筆者的強(qiáng)項(xiàng),因此只能大概說明一下(有興趣的可以自己逐條查看作用,過程會(huì)比較痛苦。方式能收獲更多CPU底層的細(xì)節(jié),這里不展開):

1 針對(duì)CPU0和CPU1有不同的程序,基本就是CPU0干活,CPU1就是WFE

2 CPU干的活就是初始化MMU和TLB等等,其中比較關(guān)鍵的就是初始化堆棧(SP寄存器指向棧頂),前面也提及過,在鏈接的時(shí)候分配了堆??臻g,而堆棧對(duì)C語言函數(shù)是非常重要的。棧的作用:一般來說函數(shù)調(diào)用或者中斷,都會(huì)涉及到現(xiàn)場(chǎng)保護(hù)和現(xiàn)場(chǎng)恢復(fù),被保護(hù)的現(xiàn)場(chǎng)實(shí)際上就是CPU的幾個(gè)專用的reg,以及正在執(zhí)行的函數(shù)的局部變量等數(shù)據(jù),這些數(shù)據(jù)會(huì)被推進(jìn)棧內(nèi),其相應(yīng)的SP寄存器也會(huì)加上入棧數(shù)據(jù)的長度,在函數(shù)執(zhí)行返回?fù)]著中斷返回時(shí),棧內(nèi)的數(shù)據(jù)按順序再次出來,總體來說就是先進(jìn)后出。而堆的作用一般就是給系統(tǒng)動(dòng)態(tài)分配存儲(chǔ)空間的,包括用戶經(jīng)常調(diào)用的malloc說分配的空間,就是在堆里。簡而言之,堆棧的完成初始化是為了c語言函數(shù)提供了環(huán)境。否則C語言是無法正確被執(zhí)行的。

3 完成上面一系列的功能后,開始一執(zhí)行去第一條C語言函數(shù)**_start**,見下面的匯編代碼

21a57bbc-1b9b-11ee-962d-dac502259ad0.png

21c265ce-1b9b-11ee-962d-dac502259ad0.png

一樣的,我們不仔細(xì)展開這段匯編,其實(shí)通過注釋就能夠明白,這里的主要功能就是初始化各種數(shù)據(jù),包括bss等等。最后,匯編來到了main,這個(gè)main就是FSBL的主函數(shù),也就是大家比較熟悉的c語言函數(shù)。

小結(jié),實(shí)際上BSP在背后干了好多事情(上述所有的匯編都是bsp提供的),這是為了讓用戶能夠忽略一些技術(shù)細(xì)節(jié),直奔主題main。而這些技術(shù)細(xì)節(jié)已經(jīng)有Xilinx官方為我們完整無誤的準(zhǔn)備好了,所以FSBL我們其實(shí)只用聚焦在main函數(shù)即可,其他的臟活累活BSP已經(jīng)替我們完成了,我們用不用太操心。不過通過上面的一些展開,大伙兒應(yīng)該也有了一個(gè)模糊的概念,也就是說雖然我們寫的所有的函數(shù)都是從main函數(shù)開始,然后CPU執(zhí)行的第一條指令,絕對(duì)不是main,而是最基礎(chǔ)的匯編。這個(gè)匯編會(huì)替你搞定c語言環(huán)境,讓我們的main能夠很ojbk的運(yùn)行。下次把目光回到main函數(shù)

終于要開始進(jìn)入main()了,激動(dòng)不?

費(fèi)話不多講,直接懟源碼,如下所示

21d2e098-1b9b-11ee-962d-dac502259ad0.png

逐條懟:
一開始就定義了三個(gè)變量,這三個(gè)變量的作用請(qǐng)看下面的注釋

21ea9288-1b9b-11ee-962d-dac502259ad0.png

next, 接下來開始初始化MIO,PLL,CLK和DDR,調(diào)用的函數(shù)就是ps7_init()

21fad490-1b9b-11ee-962d-dac502259ad0.png

如果看過我們上一篇blog應(yīng)該有個(gè)印象,MIO不是已經(jīng)被初始化過一遍嗎,怎么又要?是的,就是這么靈活,也就是說你的FSBL可以在Qspi(這樣BootROM只會(huì)初始化Qspi的接口MIO)里,你的BitStream可以保存在eMMC上,那這個(gè)多出來的eMMC的MIO也需要在初始化一下了。不多講,直接看ps7_init()

220c6e26-1b9b-11ee-962d-dac502259ad0.png

221e230a-1b9b-11ee-962d-dac502259ad0.png

該函數(shù)主要完成:

讀取PS版本,估計(jì)一些老料子的方式略有不同吧

根據(jù)PS版本,賦予相對(duì)應(yīng)初始化數(shù)組的指針。這個(gè)數(shù)組基本上構(gòu)成舉例(ps7_mio_init_data_1_0)如下

222d19c8-1b9b-11ee-962d-dac502259ad0.png

可以簡單的理解為,這個(gè)ps7_mio_init_data_1_0數(shù)組中的而每一個(gè)元素都是一種操作,這個(gè)操作包含了EMIT_WRITE,EMIT_READ等等。比如說EMIT_WRITE,為了完成這個(gè)操作,實(shí)際上包含了3個(gè)元素,操作指令碼+地址+數(shù)據(jù)(不同的操作包含的數(shù)據(jù)不同,有些操作會(huì)有四個(gè)元素)。

223c3606-1b9b-11ee-962d-dac502259ad0.png

其想要實(shí)現(xiàn)的功能就是往addr write val,比如說EMIT_WRITE(0XF8000008, 0x0000DF0DU),其想要實(shí)現(xiàn)的功能就是將地址0XF8000008上的數(shù)據(jù)寫為0x0000DF0DU

而0XF8000008這個(gè)地址,通過查看TRM,實(shí)際上就是給SCLR_UNLOCK寄存器寫入0xDF0D,目的就是為了解鎖SCLR所有的寄存器,使其可寫,也就是說沒有完成這一步的話,SCLR的其余寄存器使不允許寫操作的!

22495a84-1b9b-11ee-962d-dac502259ad0.png

Xilinx希望通過這種比較奇怪的方式完成了一系列操作(EMIT_WRITE和其他操作)的封裝成一個(gè)組合(ps7_mio_init_data_1_0),這一些列的操作共同完成了比如說MIO的初始化,DDR的初始化等等。同時(shí)Xilinx提供了一個(gè)函數(shù)去解讀這些操作,**ps7_config ()**正是為了實(shí)現(xiàn)這個(gè)功能,如下所示,利用ps7_config ()和ps7_mio_init_data來完成MIO的初始化

225efd9e-1b9b-11ee-962d-dac502259ad0.png

下面來看一下ps7_config()

226ae4f6-1b9b-11ee-962d-dac502259ad0.png

22843f96-1b9b-11ee-962d-dac502259ad0.png

229b47c2-1b9b-11ee-962d-dac502259ad0.png

該函數(shù)很簡單,實(shí)際上就是EMIT_WRITE,EMIT_EXIT,EMIT_READ等一系列操作的解包過程,有興趣的可以深入查看一下。需要注意的是,最后一個(gè)操作一定是EMIT_EXIT,也就是說不管是ps7_mio_init_data還是ps7_pll_init_data,這些數(shù)組的最后一個(gè)元素(操作)一定是EMIT_EXIT,讀者可自行檢查。

小節(jié)

Xilinx利用了一種非常不常見的方式完成了部分(MIO或者DDR)初始化,究其原因可能是這部分初始化工作是固定的,所以什么可讀性啊都不需要了?既然xilinx這么干了,我們看得懂就行了,這種方式極其不推薦。




審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9006

    瀏覽量

    366033
  • FPGA設(shè)計(jì)
    +關(guān)注

    關(guān)注

    9

    文章

    428

    瀏覽量

    26446
  • 存儲(chǔ)器
    +關(guān)注

    關(guān)注

    38

    文章

    7402

    瀏覽量

    163389
  • DDR
    DDR
    +關(guān)注

    關(guān)注

    11

    文章

    701

    瀏覽量

    65095

原文標(biāo)題:FPGA - Zynq - 加載 - FSBL源碼解析1

文章出處:【微信號(hào):zhuyandz,微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    FSBL數(shù)據(jù)代碼如何連接

    搞懂數(shù)據(jù)代碼是如何被鏈接成一個(gè)二進(jìn)制文件的,這應(yīng)該是每一個(gè)ARM程序員必須搞清楚的一個(gè)事情。
    發(fā)表于 07-21 09:02 ?882次閱讀
    <b class='flag-5'>FSBL</b>的<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>段</b>和<b class='flag-5'>代碼</b><b class='flag-5'>段</b>如何<b class='flag-5'>連接</b>?

    C代碼關(guān)聯(lián)的知識(shí)點(diǎn)

    之前有位網(wǎng)友在交流群里發(fā)了一代碼的截圖,我覺得很有意思,在此分享一下。
    發(fā)表于 08-30 10:42 ?378次閱讀
    一<b class='flag-5'>段</b>C<b class='flag-5'>代碼</b>關(guān)聯(lián)的知識(shí)點(diǎn)

    淺談text、data和bss

    保存在.bss 中。 text: 用于存放程序代碼的區(qū)域, 編譯時(shí)確定, 只讀。更進(jìn)一步講是存放處理器的機(jī)器指令,當(dāng)各個(gè)源文件單獨(dú)編譯之后生成目標(biāo)文件,經(jīng)連接器鏈接各個(gè)目標(biāo)文件并解
    發(fā)表于 08-21 15:51

    如何查看CCS編譯后程序、數(shù)據(jù)的大???

    hi, 編譯文件時(shí)提示沒有空間了,調(diào)整了code區(qū)域后,程序運(yùn)行ram區(qū)域又不夠了。想查看一下ccs編譯完后,程序數(shù)據(jù)、bss的大小,可以嗎?
    發(fā)表于 06-21 11:24

    請(qǐng)問寫DSP程序自己定義代碼數(shù)據(jù)有什么好處??? 默認(rèn)分配不是更省事嗎?

    寫DSP程序自己定義代碼數(shù)據(jù)有什么好處?。?默認(rèn)分配不是更省事?
    發(fā)表于 08-22 08:31

    代碼的跨

    08 代碼的跨執(zhí)行
    發(fā)表于 06-10 06:50

    請(qǐng)問鏈接腳本文件里面的代碼數(shù)據(jù),bss的位置可以更改嗎?

    (4) : {*(.rodata)} //3.data ALIGH(4): {*(.data)} //4.bss ALIGH(4) : {*(.bss) *(COMMON)} //5}代碼都在最前面,數(shù)據(jù)
    發(fā)表于 06-25 02:25

    請(qǐng)問數(shù)據(jù)/代碼/BSS/棧/堆存放什么量?

    請(qǐng)問數(shù)據(jù)/代碼/BSS/棧/堆存放什么量?
    發(fā)表于 12-03 06:06

    代碼、數(shù)據(jù)、附加、堆棧定義

    代碼:程序員在編制程序時(shí)要把存儲(chǔ)器劃分成,代碼用來存放程序的指令序列,代碼
    發(fā)表于 06-30 10:41 ?9791次閱讀

    什么是臨界 RTOS臨界的作用是什么

    代碼的臨界也稱為臨界區(qū),指處理時(shí)不可分割的代碼區(qū)域,一旦這部分代碼開始執(zhí)行,則不允許任何中斷打斷。為確保臨界
    的頭像 發(fā)表于 10-06 14:38 ?1.2w次閱讀
    什么是臨界<b class='flag-5'>段</b> RTOS臨界<b class='flag-5'>段</b>的作用是什么

    匯編語言和RSEG應(yīng)該如何使用詳細(xì)資料說明

    RSEG是選擇指令,要想明白它的意思就要了解的意思。是程序代碼數(shù)據(jù)對(duì)象的存儲(chǔ)單位。程序代碼
    發(fā)表于 09-10 17:26 ?2次下載
    匯編語言<b class='flag-5'>段</b>和RSEG應(yīng)該如何使用詳細(xì)資料說明

    FreeRTOS學(xué)習(xí)筆記--臨界代碼處關(guān)閉中斷

    的一句話:“臨界代碼是指不能被中斷的代碼”。實(shí)際上,不只在進(jìn)行全局操作的代碼需要對(duì)中斷進(jìn)行管控,在某些嚴(yán)格時(shí)序上也需要對(duì)中斷進(jìn)行管控。例如A任務(wù)需要利用IIC、SPI、并口等協(xié)議進(jìn)行
    發(fā)表于 12-04 14:51 ?10次下載
    FreeRTOS學(xué)習(xí)筆記--臨界<b class='flag-5'>段</b><b class='flag-5'>代碼</b>處關(guān)閉中斷

    段段存儲(chǔ)介紹

    .text代碼: 用來放程序代碼(code), 在代碼編譯完成后, 長久只讀存放于此,屬于圖中的代碼
    的頭像 發(fā)表于 09-28 15:39 ?746次閱讀
    六<b class='flag-5'>段段</b>存儲(chǔ)介紹

    什么是RTOS臨界

    代碼的臨界也稱為臨界區(qū),指處理時(shí)不可分割的代碼區(qū)域,一旦這部分代碼開始執(zhí)行,則不允許任何中斷打斷。為確保臨界
    的頭像 發(fā)表于 02-14 09:48 ?1029次閱讀
    什么是RTOS臨界<b class='flag-5'>段</b>

    devc怎么注釋掉一代碼

    在DevC中,要注釋掉一代碼,你可以使用注釋符號(hào)來標(biāo)記這段代碼。注釋符號(hào)的作用是告訴編譯器不要編譯這些代碼,而是將其視為注釋,這樣可以方便開發(fā)人員在
    的頭像 發(fā)表于 11-22 10:23 ?2103次閱讀