ZYNQ 啓動分析

目錄

1、概述

2、簡介

3、Boot Strap Pins

4、BootRom 流程

5、BootROM Header

5.1、Structure

5.2、Search BootROM Header

6、Lockdown

7、Post BootROM

7.1、State

7.2、Memory Map

8、PL Configuration

8.1、PL Control via PS Software

8.1.1、PL initialization via PS Software

8.1.2、PL Configuration via PS Software

8.1.3、Configure PL via PCAP Bridge

9、Summary


 

1、概述

ZYNQ 的詳細介紹參考 XILINX 官方文檔 UG585,在瞭解了 ZYNQ 的基本架構組成和豐富的資源後,下一步便是分析他的啓動流程,以便更好的認識 ZYNQ 並開始開發工作;

關於 ZYNQ 啓動方面的描述,這裏我覺得涉及到幾個大的方面:

1、系統上電啓動執行過程;

2、系統復位相關流程;

3、系統時鐘樹;

上面 3 點在 UG585 Datasheet 中都分別是一個大的章節來介紹,這裏先介紹系統上電執行過程的部分,也就是 UG585 的

Chapter 6 . Boot and Configuration

另外,啓動部分,又分爲兩種類型,安全啓動和非安全啓動,這裏僅對非安全啓動進行介紹,更多的安全啓動部分的詳細內容,參考官方 UG585 DS;

 

2、簡介

上電的時刻,PS_POR_B 信號會被置位,此刻 ZYNQ 硬件立馬去採樣一組稱作 Boot Strap Pins 的管腳,這組管腳告訴硬件以什麼方式啓動(QSPI Flash、NAND Flash、NOR Flash、SD Card),以及是否開啓 PLL 等(每個管腳的高低電平來表徵0/1信號,稍後詳細介紹);通常的做法是板端上,通過跳冒來選擇啓動方式,也就是原理圖上通過接地或者 Vcc 來確定一組上電採樣管腳,選擇好了後,再上電;

PS 端首先執行 BootROM 上的啓動代碼,這段代碼是直接在 On Chip ROM 中 XILINX 做進去的,無法看到而且也無法修改,所以 BootROM 是上電後,APU 執行的第一段代碼就是 BootROM 的這部分,我的 ZYNQ-7000 是雙核 Cortex-A9,兩個 CPU 核心,BootROM 由 CPU_0 來執行,此刻 CPU_1 處於 WFE 等待狀態;

BootROM 的主要任務是配置系統,將後續的 FSBL(First Stage Boot Loader)/ User Code 加載到 OCM 中運行,然後跳轉到 FSBL ,將控制權移交,並完成它的使命;(當然,在非安全的模式下,也支持片上 XIP 運行,也就是 QSPI Flash 或者 NOR Flash 上直接運行代碼);

FSBL 是咱們代碼編譯生成的,編譯完成後生成 bin 文件,並將這個 bin 放置到我們的啓動設備中(QSPI Flash 或者 NAND/NOR Flash 或者 SD Card 中);

所以呢,這裏咱們便可以知道 BootROM 中,至少含有 QSPI/NAND/NOR Flash 相關的控制器驅動程序和器件的標準訪問指令,以及 SDIO 的標準驅動(MMC)和 Mirco SD Card 標準的訪問指令;

既然這個 FSBL 是放置在啓動設備中,那麼在 BootROM 採集完 Boot Strap Pins 後呢,一定就去初始化對應的外設控制器,然後去啓動設備上去找咱們的 FSBL,這裏 XILINX 定義了一個叫做 BootROM Header 的玩意,BootROM 會去啓動設備上不斷的尋找這個 BootROM Header,以便完成接下來的工作交接(關於更多 BootROM Header 的東西,下面會介紹,看官稍安勿躁);

OK,找到 BootROM Header 後,BootRom 又幹了一些事情,然後控制權交給了 FSBL,這部分代碼咱們可以控制,可以在加載 OS 之前,如果攜帶了 bit stream 的情況下呢,在此刻去配置 PL 的邏輯;

最後,加載 BootLoader,進而跑進 OS,完成啓動;

 

3、Boot Strap Pins

前面說了,上電啓動的時候呢,會觸發 PS_POR_B 信號,一旦觸發這個信號,就會去採集 Boot Strap Pins 幾個引腳的電平狀態,以便 BootRom 判斷啓動設備是什麼,上電的流程信號如下:

其實系統復位有很多種類型,軟件可以觸發系統復位,WDT 也可以觸發系統復位,有些復位並不觸發重新採集 Boot Strap Pins 流程,這裏我們討論的 POR 上電覆位流程,是要觸發 Boot Strap Pins 的;其他的暫且放在以後專門的復位章節描述;

接着說 Boot Strap Pins,ZYNQ-7000 使用 7 個 pins 來描述 PS_POR_B 信號置位後,需要傳遞給 BootROM 的信息,如下所示:(這 7 個 pin是 MIO[8:2],每個接 20kΩ 的上拉或者下拉電阻,上拉代表邏輯 1,下拉代表邏輯 0):

上表直接描述了電壓等級、PLL 是否開啓,以及使用哪種類型的設備進行啓動;

 

4、BootRom 流程

整個 BootRom 的流程如下所示:

在這裏插入圖片描述

1、初始化 PLL

2、初始化 APU

3、ROM CRC check (可選)

4、MIO 初始化

5、如果 PL 上電了的話,初始化 PL(但並沒有配置 bit stream)

6、根據 Boot Strap Pins 選擇啓動方式,並搜索 BootROM Header

7、判斷 BootROM Header 中是否有加密的 flag 以斷定後期是否走加密流程(這裏暫時認爲走非加密流程)

8、非加密流程中,平臺寄存器初始化

9、判斷是否 XIP 模式(片上 Flash 執行,QSPI/NOR Flash 支持)

10、若 XIP,則直接跳轉到 User Code,跑 XIP

11、若非 XIP,那麼將 FSBL 加載到 OCM 中,跳轉到 OCM 中執行 User Code

 

5、BootROM Header

5.1、Structure

上面已經描述了,BootROM Header 是 BootROM 需要去搜索並根據 BootROM Header 來進行接下來的操作的一個關鍵結構,它的組成如下所示:

它定義了很多的字段:

Interrupt Table for Execution-in-Place — 0x000 to 0x01C
這些數據用於XIP,這裏不討論

Width Detection — 0x020
只用於 QSPI 啓動模式,用於決定  Quad-SPI device (x1, x2, or x4) 的位寬

Image Identification — 0x024
固定爲 0x584C4E58,‘XLNX’

Encryption Status — 0x028
配置 FSBL/User code 是否加密

FSBL/User Defined — 0x02C
指明 Header Version,在 UG821 Zynq-7000 SoC Software Developers Guide 中詳細描述

Source Offset — 0x030
用於保存 FSLB/User code image 被保存的offset地址,這個Offset是相對於Header的起始位置而言的

Length of Image — 0x034
用於保存被加載的FSLB/User code image的大小,最大 192KB。 該數據爲 0 時意味着不需要copy,是XIP。

FSB Load Address— 0x038
FSLB/User code image copy的目標地址,因爲該image是存在FLASH中的,需要被複制到其他OCM中去。

Start of Execution — 0x03C
copy完以後,cpu需要從哪裏開始執行第一條代碼,<= 0x30000,也即是192KB。這個很重要,會在介紹FSBL源碼的時候重新在驗證並確認這個功能。 然而這樣地址,或者長度之類的,都是通過配置Xilinx提供的工具自動打包生成的。

Total Image Length — 0x040
load進OCM的總長度,這個長度會大於等於Length of Image — 0x034,因爲在加密模式下,還會包含HMAC頭文件之類的。

QSPI Config Word — 0x044
固定爲0x01;

Header Checksum — 0x048
0x020 to 0x044的checksum,用於驗證Header是否完整;

FSBL/User Defined— 0x04C to 0x097
自定義數據

QSPI Config Word — 0x09C
指向Image Header Table,這個Table裏面會記錄整個FLASH裏面除了FSBL以外,還有幾個image,包括Bitstream,elf等等。每一個image會有一個Header(不是這裏的BootROM Header,而是專門的Header,FSBL裏面在介紹),所有的Header組成一個Table。

Register Initialization Parameters — 0x0A0 to 0x89C
這部分包含了 256 組的 <地址+數據> 對的定義,當初始化的時候,BootROM 利用 Add+Data 的方式,直接對某個地址寄存器進行配置;

 

5.2、Search BootROM Header

BootROM Header 放到啓動設備後呢,BootROM 代碼就要去搜索這個玩意,以便決定後面該怎麼執行;有兩點 BootRom 需要去尋找的:

1、Image Identifucation —— 爲 0x584C4E58,即 'XLNX';

2、CheckSum 正確;

如果滿足上述兩個條件,那麼 BootRom 覺得是找到的正確的 BootROM Header;

尋找 Header 的過程,是首先在起始的地方找,如果沒找到,那麼跳 32KB 的地方,再次找,以此類推:

這種 32KB 一跳搜索的方式,總有一個盡頭吧?UG585 規定根據不同設備,它搜索的地址空間的限制如下:

NAND:First  128MB

NOR:First 32MB

Quad-SPI,signal/dual SS with 4-bit I/O:First 16MB

Quad-SPI,dual SS with 8-bit I/O:First 32MB

SD Card:Signle Image in boot page,no searching

如果搜索到了,那麼皆大歡喜,繼續往下走,如果沒搜索到,BootROM 會產生 lockdown,將系統鎖住;

這裏值得注意的是,SD Card 啓動,不支持走 search 過程,和 multiboot ;SD Card boot 流程是在 SD Card 支持 FAT 16/32 文件系統,BootROM 直接從 SD Card 讀取 BOOT.BIN 文件(FSBL 編譯生成的文件)並加載到 OCM,更多的細節參考 UG585;

 

6、Lockdown

在 BootROM 啓動流程中(參考前面的啓動流程圖),出現錯誤後,系統會被 lockdown ,lock down 的原因會被硬件寫入 slcr.REBOOT_STATUS 寄存器的 Error Code:

具體的 BOOTROM_ERROR_CODE 詳見 UG585

 

7、Post BootROM

7.1、State

PS 端完成 BootROM 後,APU 和 OCM 的狀態如下:

MMU,ICache,Dcache,L2 Cache 全部 disable

處理器處於 supervisor 狀態

ROM Code 處於 inaccessible

OCM memory 可以被訪問,從 0x0000_0000 地址開始的192KB 的 ,和從 0xFFFF_0000 開始的 64KB 空間,一共256KB

CPU 0 處於 boot stage 1狀態

CPU 1 處於 WFE

7.2、Memory Map

OCM 片上 RAM 一共 256KB 的大小,它分爲兩部分:

1、0x0000_0000 開始的 192KB

2、0xFFFF_0000 開始的 64KB

64KB 的 memory block 用於 BootROM 放置 BootROM Header 和放置 program variable;當 BootROM 完成後,這個 64KB 的空間就可以被 FSBL 使用了;

 

8、PL Configuration

8.1、PL Control via PS Software

PS 端軟件是通過一個叫 PCAP 橋的東西控制 PL ,主要是通過一個叫 Devc 的模塊來操作

這個 PCAP Bridge 的內部結構如下,是通過 AXI 總線進行互聯:

8.1.1、PL initialization via PS Software

在任意時刻,devcfg.CTRL[PCFG_PROG_B] 位都可以用於對 PL 發射全局的 Reset 信號,如果設置這個 bit 被設置爲低電平,PL 開始它的初始化處理,同時 devcfg.STATUS[PCFG_INIT] 這個 bit 一直爲高,直到 devcfg.CTRL[PCFG_PROG_B] 被硬件設置爲高,XILINX ZYNQ 初始化 PL 的順序如下:

設置 PCFG_PROG_B 信號爲高

設置 PCFG_PROG_B 信號爲低

輪詢 PCFG_INIT 信號狀態,直到爲 0

設置 PCFG_PROG_B 信號爲高

輪詢 PCFG_INIT 信號狀態直到爲 1

8.1.2、PL Configuration via PS Software

爲了配置 PL,需要先使能 PCAP(AXI Interface)部分,清除終端,初始化 PL(8.1.1),關閉內部 DevC 的 loopback 功能;然後通過 DevC 的 DMA 單元進行對 PL 配置;當然,PS 和 PL 都需要 Power on;

8.1.2.1、PS Non-Secure Bring Up(no PL Power)

ZYNQ 可以支持只啓動 PS 端,PL 端不上電

可以看到 PS Power-On 後,PS_POR_B 信號被拉高,如果使用 PLL 的話,需要等待 PLL Lock 信號,PLL Lock 後 BootROM 便開始運行,執行完後,便開始 FSBL;

 

8.1.2.2、PS Bring Up With PL Configuration

PS 也可以攜帶 PL 的 bit stream 來啓動,在啓動過程中配置 PL;可以支持加密或者非加密模式:

 

8.1.2.3、PL Bring Up By FSBL/User Code

當然,配置 PL 呢,不一定是要在啓動的階段,你在任意系統運行階段來搞事情:

8.1.3、Configure PL via PCAP Bridge

上面說了配置 PL 的各個時間段,那麼現在來說一下通過 PCAP 橋來配置 PL 的過程:

1、使能 PCAP Bridge 並且選擇 PCAP 來進行配置:對 devcfg.CTRL[PCAP_MODE] 和 [PCAP_PR] bit 寫 1;

2、清除中斷:devcfg.INT_STS 寄存器寫全 1;

3、初始化 PL:

  • 設置 PCFG_PROG_B 信號爲 1
  • 設置 PCFG_PROG_B 信號爲 0
  • 輪詢 PCFG_INIT 信號狀態,直到爲 0
  • 設置 PCFG_PROG_B 信號爲 1

清除完成中斷:devcfg.INT_STS[PCFG_DONE_INT] 寫 1

4、爲了保證 PL Ready,需要輪詢 PCFG_INIT 信號狀態直到爲 1

5、確保 devcfg.STATUS[DMA_CMD_Q_F] 爲 0

6、關閉 PCAP 的 loopback:寫 0 給 devcfg.MCTRL[INT_PCAP_LPBK] bit;

7、配置 PCAP_2x 時鐘分頻:

  • Secure Mode:對 devcfg.CTRL[QUARTER_PCAP_RATE_EN] bit 寫 1
  • Non-Secure Mode:清除 devcfg.CTRL[QUARTER_PCAP_RATE_EN] bit 爲 0

8、啓動針對 bit stream 的 DMA 傳輸:

  • 配置 Source Address 爲 PL  的 bitstream 的存放地址;
  • 目的地址配置爲 0xFFFF_FFFF;
  • Source 傳輸數據的長度爲 32-bit word 爲單位的 PL bitstream 的大小;
  • Destination 目的地址長度爲 32-bit word 爲單位的 PL bitstream 的大小;

9、等待 DMA 傳輸完成:也就是等待 devcfg.INT_STS[DMA_DONE_INT] bit 爲 1;

10、檢查錯誤碼;檢查 devcfg.INT_STS 中的錯誤碼,看看在配置過程中是否發生了錯誤;

11、輪詢 [PCFG_DONE_INT] bit 爲 1,確認配置完成;

下圖爲 Secure 和 Non-Secure 的 PL bitstream 配置流程:

 

 

9、Summary

簡單的來說,上電覆位 POR 後,硬件去採集啓動管腳,並將其鎖存到寄存器中,BootROM 讀取啓動方式後,進行對應的啓動流程,包括等待 PLL Lock,尋找 BootROM Header,加載 FSBL,配置 PL 等;簡易流程如下所示:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章