精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

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

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

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

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

建個Example工程,不要光顧著看,自己動動手掌握的更快。

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

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

1.1 ARM部分(硬核+外設),如圖中所示的processing_system,其中就包含了除APU以外,還有DDR,以及FIXED_IO。DDR好理解,就是連接外部DDR存儲器唄,那這個FIXED_IO是個啥呢?這個實際上就是arm的外設,包含了Q-spi的必要引腳,也包括了Debug Info所需的串口。總而言之都是ARM的外設

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

1.3 AXI Interconnect,這個模塊非常重要,簡單地說這就是一個總線解析器,一主(一個master AXI4)多從(兩個slave AXI4)。我們之前提到過,AXI4將會用于連接Zynq的PS(ARM部分)和PL(FPGA部分),這里就是一個例子,后面每一個Slave AXI4都連著一個 Xilinx 的IP,或者是用戶自定義的具備AXI4的IP。這樣就簡單了,只要用戶定義的IP包含AXI4接口,同時將必要的可讀或者可寫數(shù)據(jù)映射到這個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, 這兩個就是上述的Xilinx的IP,自帶有AXI4總線接口,這樣ARM就能夠通過總線解析器控制他們

1.5 實際的應用,其實也不會比這個在復雜太多,只是再加一些自定義的IP

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

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

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

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

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

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

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

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

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

定義了兩個存儲空間,包括offset和length,其源碼表達如下

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

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

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

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

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

上面的源碼的作用是:

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

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

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

進到這個匯編程序,如下所示:

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

這里先關注兩個名字,一個就是==.vectors==,另一個就是==_vector_table==

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

終于要開始進入main()了,激動不?

費話不多講,直接懟源碼,如下所示

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

逐條懟:
一開始就定義了三個變量,這三個變量的作用請看下面的注釋

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Xilinx希望通過這種比較奇怪的方式完成了一系列操作(EMIT_WRITE和其他操作)的封裝成一個組合(ps7_mio_init_data_1_0),這一些列的操作共同完成了比如說MIO的初始化,DDR的初始化等等。同時Xilinx提供了一個函數(shù)去解讀這些操作,**ps7_config ()**正是為了實現(xiàn)這個功能,如下所示,利用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ù)很簡單,實際上就是EMIT_WRITE,EMIT_EXIT,EMIT_READ等一系列操作的解包過程,有興趣的可以深入查看一下。需要注意的是,最后一個操作一定是EMIT_EXIT,也就是說不管是ps7_mio_init_data還是ps7_pll_init_data,這些數(shù)組的最后一個元素(操作)一定是EMIT_EXIT,讀者可自行檢查。

小節(jié)

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




審核編輯:劉清

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

    關注

    134

    文章

    9046

    瀏覽量

    366816
  • FPGA設計
    +關注

    關注

    9

    文章

    428

    瀏覽量

    26484
  • 存儲器
    +關注

    關注

    38

    文章

    7452

    瀏覽量

    163605
  • DDR
    DDR
    +關注

    關注

    11

    文章

    711

    瀏覽量

    65228

原文標題:FPGA - Zynq - 加載 - FSBL源碼解析1

文章出處:【微信號:zhuyandz,微信公眾號:FPGA之家】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

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

    搞懂數(shù)據(jù)代碼是如何被鏈接成一個二進制文件的,這應該是每一個ARM程序員必須搞清楚的一個事情。
    發(fā)表于 07-21 09:02 ?916次閱讀
    <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代碼關聯(lián)的知識點

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

    淺談text、data和bss

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

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

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

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

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

    代碼的跨

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

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

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

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

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

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

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

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

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

    匯編語言和RSEG應該如何使用詳細資料說明

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

    FreeRTOS學習筆記--臨界代碼處關閉中斷

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

    段段存儲介紹

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

    什么是RTOS臨界

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

    devc怎么注釋掉一代碼

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