10.0難度系數★☆☆☆☆☆☆
10.1是什么是固化
我們前幾章將的程序都是通過JTAG先下載bit流文件,再下載elf文件,之后點擊Run As來運行的程序。JTAG的方法是通過TCL腳本來初始化PS,然后用JTAG收發信息,可用於在線調試。但是這樣只要一斷電,程序就丟失了。還得全部重新來過。
本章介紹通過制作鏡像文件,將鏡像文件拷貝到SD卡,然后將撥碼開關撥到SD啟動,那么每次斷電之后程序都會自動從SD啟動,程序就別固化,而不會掉電丟失了。
10.2固化的流程
10.3固化准備
《第七章 ZYNQ GPIO使用之EMIO》中的實驗其實就是一個最簡單的“PS + PL”運用的體現。如果我們想固化這個程序,及為這個程序做一個鏡像文件,制作改鏡像需要哪些材料呢?
首先,想到的兩個文件就是PL部分需要的bit文件,以及PS需要的elf文件。但是僅僅是這兩個文件是遠遠不夠的。我們還需要一段代碼吧bit文件以及elf文件安置好。那么這段代碼就是大名鼎鼎的FSBL.elf。
所以要制作這樣一個鏡像文件我們需要:FSBL.elf、bit、elf。
最后得到一個等式就是:BOOT.bin = FSBL.elf+該工程.bit+該工程.elf。該工程的bit文件和elf文件在我們的程序編譯完之后都有了,關鍵是這個FSBL.elf這么那里找?不用擔心,FSBL.elf文件xilinx找就為我們准備好了,我們可以利用SDK生成它。再次之前,我們先簡單了解一下zynq的啟動的過程。
10.4 zynq的從SD卡的啟動的過程
和大多數arm啟動過程一樣,這個啟動過程也分為3個階段,這三個階段分別稱之為階段0、階段1和階段2。
階段 0:即傳統的BootROM過程,zynq芯片里有個rom里面固化了一段不可修改的程序,只有zynq一上電,這段程序就會執行,它將對zynq的NAND、NOR、SD等基本外設控制器進行初始化。把SD卡這類易失的存儲器件初始化好了之后,就會把其中的程序拷貝到zynq的OCM(On-chip memory),那么這個被拷貝到片上RAM執行的程序就是我們今天要制作的文件——BOOT.bin。
階段 1:BOOT.bin加載到OCM上就開始執行了,之前說過BOOT.bin其實就是由FSBL.elf+該工程.bit+該工程.elf構成。而階段1要做的就是:首先配置PS部分,PS完成初始化后,會去配置PL部分,最后還可以去加載階段 2的代碼。
階段 2:這一階段是可選的,主要是為了完成Linux系統啟動過程。我們這次是還是裸奔,所以暫時不需要。
10.5 zynq啟動模式位的選擇
這里有個疑問,眾所周知zynq具有多種啟動方式:NOR, NAND, Quad-SPI, SD Card 以及JTAG 。zynq如何判斷到底從哪里啟動呢?事實上,當上電后,zynq 會根據模式管腳的設定選用boot的方式。而這個管腳的設定是通過MiZ702按鍵旁的撥碼開。
SD卡啟動模式選擇撥碼開關1-2-5-6 為ON 接到GND 3-4 為OFF 上拉到VCC
QSPI FLASH啟動模式選擇撥碼開關1-2-3-5-6為ON 接到GND 4 為OFF 上拉到VCC
MiZ702模式選擇通過撥碼開關來實現,當撥碼開關ON狀態接通到GND 否則接通到3V3.
MiZ702通過撥碼開關設置MIO的電平狀態
我們的開發板MiZ702默認撥碼的順序,就是默認的SD卡啟動,具體參看模式位應該如何選擇:
· MIO[2]/Boot_Mode[3]設置JTAG模式
· MIO[5:3]/Boot_Mode[2:0] 選擇Boot模式
· MIO[6]/Boot_Mode[4] 使能內部PLL
· MIO[8:7]/Vmode[1:0] 用於配置
10.6 BOOT.bin制作過程詳解
Step1:雙擊打開SDK並為工作空間選擇一個目錄,后點擊OK:
Step2:新建一個應用工程
Step3:填寫工程名,點擊Next
Step4:現在工程類型為Zynq FSBL
Step5:按下快捷鍵Ctrl + B編譯工程就能得到我們夢寐以求的FSBL.elf。這個文件可以到我們剛剛設置的工作空間的Debug目錄下找打,我這邊具體目錄是:D:\MiZ702\FSBL\FBLS\Debug。
Step6:我們將FSBL.elf連同《EMIO 使用詳解》工程中的elf和bit文件拷貝到一個文件夾下備用。
Step7:單擊SDK的工具欄處的Xilinx Tool->Creat Zynq Boot Image
Step8:依次添加FBLS.elf,design_1_wrapper.bit,以及emio.elf,請務必按順序添加。
Step9:點擊add,添加FSBL.elf
Step10:點擊add,添加system_wrapper.bit
Step11:點擊add,添加EMIOTest.elf文件
Step12:三個文件添加完畢之后,點擊Creat Image生成BOOT.bin
在之前設定的文件夾下找到,BOOT.bin並且將其拷到SD卡中,再把SD卡插到MiZ702,打開電源,和上次工程出現的現象重現了,這次斷電之后,程序也不會消失了~~
最后提醒下放大SD卡的bin文件,一定得叫BOOT.bin,不然不識別。
10.7 從Quad-SPI啟動
Step1:設置配置模式
正確設置模塊開關跳線,也就是把MIO5切換到OFF(上拉為H)其他全部切換到ON(短接到GND)
Step2:給開發板通電,同時連接串口到PC(不是必須的可以不連接)
Step3:選擇Xilinx Tools > Program Flash
Step4:下載過程,需要幾分鍾時間
Step5:下載過程,輸出的情況
Step6:下載完成后斷電重啟,就能看到從QSPI FLASH加載了
10.8 本章小結
本章詳細講解了SD卡下UBOOT的制作過程和如果編程QSPI FLASH。這樣固化后程序就不容易丟失了。
第十一章 ZYNQ DDR3 PS讀寫操作方案
本編文章的目的主要用簡明的方法在純PS里對DDR3進行讀寫。
本文所使用的開發板是Miz702
PC 開發環境版本:Vivado 2015.4 Xilinx SDK 2015.4
11.0本章難度系數★☆☆☆☆☆☆
11.1 搭建硬件工程
Step1:新建一個名為為Miz702_sys的工程
Step2:選擇RTL Project 勾選Do not specify source at this time
Step3:由於Miz702兼容zedboard 因此選擇zedboard開發包
Step4:單擊Finish
11.2使用IP Integrator創建硬件系統
Step1:單擊Create Block Design
Step2:輸入system
Step4:搜素單詞z選擇ZYNQ7 Processing System,然后雙擊
Step5:添加進來了ZYNQ CPU IP,然后單擊Run Block Automation
Step6:直接單擊OK
Step7:在你點擊了OK后,你會發現DDR以及FICED_IO自勱的延伸出來。
Step8:連線的作用就是把PS的時鍾可以接入PL部分,當然這里我們暫時用不到PL部分的資源。在Block文件中,我們迚行連線,將鼠標放在引腳處,鼠標變成鉛筆后迚行拖拽,連線如下圖所示:
Step9:雙擊ZYNQ,使能UART1點擊Run Connection Automation,按照如圖所示配置后單擊OK
Step10: 右擊 system.bd, 單擊Generate Output Products
Step11:支部操作會產生執行、仿真、綜合的文件
Step12:右擊system.bd 選擇 Create HDL Wrapper 這步的作用是產生頂層的HDL文件
Step13:選擇Leave Let Vivado manager wrapper and auto-update 然后單擊OK
11.3導出SOC硬件到SDK
Step1:File->Export->Export Hardware
Step2:勾選Include bitstream 直接單擊OK
Step3:File->Launch SDK加載到SDK
Step4:單擊OK
11.4軟件工程
新建一個PL_PS_INTC空的工程,並且添加main.c
DDR3的地址建好后,在mem_demo_bsp->ps7->cortexa9_0的路徑下,打開xparameters_ps.h這個頭文件,這個頭文件是cortexA9可以直接控制的外設地址的宏定義。在里面可以找到DDR的地址,可以看到如下代碼:
/* Canonical definitions for DDR MEMORY */ |
等會我們要使用這個地址,對DDR3進行讀寫操作,讀寫操作函數在mem_demo_bsp->ps7->cortexa9_0的路徑下,打開xil_io.h這個頭文件,這個頭文件是cortexA9可以直接控制的內存映射或者映射到了地址空間的IO。在里面可以看到如下代碼:
//從某個地址讀數據
u8 Xil_In8(INTPTR Addr);
u16 Xil_In16(INTPTR Addr);
u32 Xil_In32(INTPTR Addr);
//向某個地址寫數據。
void Xil_Out8(INTPTR Addr, u8 Value);
void Xil_Out16(INTPTR Addr, u16 Value);
void Xil_Out32(INTPTR Addr, u32 Value);
OK,有了這些就可以簡單的對DDR進行續寫操作了
14.3代碼實現
* main.c * * Created on: 2016年4月4日 * Author: Administrator */ #include "stdio.h" #include "xparameters.h" #include "xparameters_ps.h" #include "xil_printf.h" #include "xil_io.h" #define DDR_BASEARDDR XPAR_DDR_MEM_BASEADDR + 0x10000000 int main() { int i; int rev; xil_printf("Hello World\n\r"); for(i=0; i<32; i++) { Xil_Out32(DDR_BASEARDDR+i*4,i); } for(i=0; i<32; i++) { rev = Xil_In32(DDR_BASEARDDR+i*4); xil_printf("the address at %x data is : %x \n\r" ,DDR_BASEARDDR+i*4, rev); } return 0; } |
11.5 測試結果
串口終端的結果如下:
Hello World
the address at 10000000 data is : 0
the address at 10000004 data is : 1
the address at 10000008 data is : 2
the address at 1000000C data is : 3
the address at 10000010 data is : 4
the address at 10000014 data is : 5
the address at 10000018 data is : 6
the address at 1000001C data is : 7
the address at 10000020 data is : 8
the address at 10000024 data is : 9
the address at 10000028 data is : A
the address at 1000002C data is : B
the address at 10000030 data is : C
the address at 10000034 data is : D
the address at 10000038 data is : E
the address at 1000003C data is : F
the address at 10000040 data is : 10
the address at 10000044 data is : 11
the address at 10000048 data is : 12
the address at 1000004C data is : 13
the address at 10000050 data is : 14
the address at 10000054 data is : 15
the address at 10000058 data is : 16
the address at 1000005C data is : 17
the address at 10000060 data is : 18
the address at 10000064 data is : 19
the address at 10000068 data is : 1A
the address at 1000006C data is : 1B
the address at 10000070 data is : 1C
the address at 10000074 data is : 1D
the address at 10000078 data is : 1E
the address at 1000007C data is : 1F
....................
11.4 本章小結
通過本章的學習,在僅僅使用PS可以對DDR3讀寫,這樣在處理一些速度不快但是量很大的數據時很方便,當然這種方式每次讀寫都需要CPU干預,效率是比較低的,主要看需求吧。
官網論壇:www.osrc.cn