ZedBoard啟動教程 (轉)


看看,我們組里的那塊板子是不是 ZedBoard!!

轉自 http://blog.michiru.me/posts/zedboard-bring-up-guide.html

一份簡單而完整的ZedBoard啟動教程,如果湊巧你也在折騰這塊板子,希望能幫助你少花些時間在這些SB的工作上。大概分成三個部分:

  1. 使用編譯好的文件和ramdisk
  2. 使用編譯好的文件和Linaro Ubuntu Linux
  3. 自行編譯需要的文件

0.基礎

ZedBoard是一塊不錯的板子,價格便宜,外設豐富,還有Xilinx的官方支持,性能也還說的過去……其的核心是Xilinx的Zynq-7000系列AP SoC(All Programmable System on Chip)芯片,型號是Zynq-7020。簡單來說其由兩部分組成:ARM雙核Cortex-A9和Artix-7 Fabric,也就是ARM和FPGA集成在一塊芯片上啦。ARM部分被Xilinx稱作PS,FPGA部分則被稱作PL。

ZedBoard板子可以從JTAG(電腦輔助)或者由SD卡啟動,或者其它的一些奇怪的啟動方式。這里我們專注與從SD卡啟動,這時FPGA的配置是在開機時,由ARM來完成的。也就是說,即使只想用FPGA,空轉也好,也要讓ARM啟動起來。如果有JTAG輔助,想使用FPGA就只需要bitstream文件了。整個啟動過程是:

  • 開機
  • 寫死在板上BootROM中的程序啟動,讀啟動方式設置的跳線,如果是SD模式啟動電話,讀SD卡第一分區,尋找Boot.bin文件。
  • Boot.bin中應該包含FSBL(First stage boot loader)程序,它接管CPU。
  • FSBL初始化開發板。如果有bitstream文件,那么初始化FPGA。之后將CPU交給Boot.bin中第二塊代碼接管。它可以是用戶自己的程序,或者是SSBL(Second stage boot loader)。一般是SSBL。
  • SSBL(通常是U-Boot)接管CPU。它可以做一些准備工作之后啟動Linux內核,也可以啟動用戶自己的程序。一般是Linux內核。
  • 內核做很多很多工作,比如加載驅動,加載Rootfs(文件系統)等等。
  • 用戶可以開始使用操作系統了

所以,啟動這塊板子,我們需要的數據有:FSBL程序、bitstream文件(可選,如果你不想使用FPGA端的資源的話,但HDMI輸出需要FPGA來實現)、U-Boot、Linux Kernel、Rootfs。並且我們采用SD卡的方式啟動。

關於Rootfs

Rootfs也就是文件系統,有兩種可供選擇:

  1. ramdisk:非常小,幾乎沒什么功能,運行在ram里,任何修改在重啟之后就會丟失。

  2. 完整的Linux文件系統,比如Linaro Ubuntu。全功能,可能非常龐大,需要SD卡多分出一個區來放置,任何修改也都保存在SD卡里。另外一個可以選擇的是Arch

我們可以從Xilinx和Linaro的官網上直接下載已經編譯好的文件,或者從源代碼編譯出它們。

關於自己編譯

自己編譯也只是使用別人的代碼,別人的工具,在自己的計算機里運行一遍。就結果來看,這和使用別人已經編譯好的文件,直接啟動板子沒什么不同。不過從頭開始做一遍,可以讓你了解哪些部分有修改的余地。

我的操作系統是Ubuntu 14.10,搭建編譯環境比較方便,安裝好Xilinx的開發工具套件Vivado編譯環境就差不多了。對Windows,要得到好的編譯環境不容易,我不知道怎么搞定。但是,Linux下,那個USB-JTAG芯片的驅動又不是很容易裝上。考慮到這些破事兒,Windows宿主+Linux虛擬機是一個推薦的方案。編譯都在Linux下完成,如果需要JTAG就回到Win。

1.簡單的方式

首先使用最快最簡單的方式:使用編譯好的文件,並且使用ramdisk來啟動。首先去Xilinx的官網下載到已經編譯好的文件。目前最新的是Zynq 2014.4 Release (latest),里面包括了所有啟動需要的文件。使用

tar xf 2014.4-release.tar.xz

來解壓。有用的文件是:

  • uImage:Linux內核
  • uramdisk.image.gz:ramdisk
  • zed/bing.bin:啟動文件
  • zed/devicetree.dtd:設備樹文件
  • zed/fsbl.elf:FSBL
  • zed/u-boot.elf:SSBL

格式化SD卡

我們需要准備SD卡,用來啟動ZedBoard。這需要一個4G或者以上容量的SD卡來裝載所有啟動所需要的文件。

  1. 使用ramdisk時可以簡單的把整個SD卡分為一個區,格式化成FAT格式。不過我建議依舊按張下面的方式分區,免去后續的折騰。

  2. 使用完整的Linux文件系統時,需要將SD卡分為兩個分區:第一分區格式為FAT32,大小足夠裝下啟動用的文件,50MB綽綽有余。第二個分區為ext4,占剩下的所有空間,用來裝Ubuntu什么的文件系統。因為Windows自帶的磁盤工具是沒有辦法格式化和讀寫ext4格式的磁盤,所以你需要Linux。

插入SD卡到讀卡器再到電腦上,然后在終端運行:

lsblk

這會列出硬盤、USB、SD卡等儲存設備。從輸出中找出SD卡的設備名,一般是/dev/mmcblk0。我們用fdisk程序來分區:

sudo fdisk /dev/mmcblk0

輸入o來清除現在有的分區(會丟掉所有數據)

輸入p來查看所有的分區,應該是空的。

接下來按n新建第一個分區,按p選擇使用主分區,按1表示這是第一個分區,按回車來使用默認的開始扇區,輸入+50M來分配分區大小。

輸入n新建第二個分區,按p選擇使用主分區,按1表示這是第二個分區,回車兩次來使用默認的大小。

參考輸入輸出:

Command (m for help): n
Partition type:
p primary (0 primary, 0 extended, 4 free)
e extended
Select (default p): p
Partition number (1-4, default 1): 1
First sector (2048-15759359, default 2048):
Using default value 2048
Last sector, +sectors or +size{K,M,G} (2048-15759359, default 15759359): +50M

Command (m for help): n
Partition type:
p primary (1 primary, 0 extended, 3 free)
e extended
Select (default p): p
Partition number (1-4, default 2): 2
First sector (411648-15759359, default 411648):
Using default value 411648
Last sector, +sectors or +size{K,M,G} (411648-15759359, default 15759359):
Using default value 15759359

接下來設置啟動標志和分區類型:

Command (m for help): a
Partition number (1-4): 1

Command (m for help): t
Partition number (1-4): 1
Hex code (type L to list codes): c
Changed system type of partition 1 to c (W95 FAT32 (LBA))

Command (m for help): t
Partition number (1-4): 2
Hex code (type L to list codes): 83

寫入之前查看確認一下:

Command (m for help): p

Disk /dev/mmcblk0: 8068 MB, 8068792320 bytes
249 heads, 62 sectors/track, 1020 cylinders, total 15759360 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x920c958b

Device Boot Start End Blocks Id System
/dev/mmcblk0p1 * 2048 411647 204800 c W95 FAT32 (LBA)
/dev/mmcblk0p2 411648 15759359 7673856 83 Linux

最后確認寫入SD卡:

Command (m for help): w
The partition table has been altered!

Calling ioctl() to re-read partition table.

WARNING: If you have created or modified any DOS 6.x
partitions, please see the fdisk manual page for additional
information.
Syncing disks.

分區完成之后需要格式化各個分區:

mkfs.vfat -F 32 -n boot /dev/mmcblk0p1
mkfs.ext4 -L root /dev/mmcblk0p2

掛載第一個分區:

mkdir boot
mount /dev/mmcblk0p1 boot

2014.4-release.tar.xz中解壓縮出的zed/boot.binzed/devicetree.dtbuImageuramdisk.image.gz四個文件復制到SD卡第一個分區的根目錄中(注意不要保留文件結構)。

取消掛載:

sudo umount boot

啟動Zedboard

現在已經可以使用SD卡來啟動板子。將開發板上控制啟動模式的跳線設置為:

MIO[5]:1
MIO[4]:1
MIO[3]:0

這代表着從SD卡啟動(順便,3個全部0表示從JTAG啟動)。從電腦上拔出准備好的SD卡,然后插在ZedBoard的讀卡器上。用一根USB線纜將電腦和板上的USB-UART口相連,接通電源。打開電腦的串口終端工具(比如Windows下的teraterm,Linux下的minicom),Windows找設備名COMx的設備,Linux找ttyACMx。設置串口參數為:115200,8N1(波特率115200bps,數據位8位,不校驗,停止位1位,硬件軟件握手協議都是無)。如果一切順利的話,就能看到從串口來的輸出了。

默認用戶名是root,密碼也是root

這里有個小問題,ZedBoard開機之后,終端程序才能打開設備。

2.稍復雜一點的方式

這次我們使用Linaro Ubuntu。在上面准備好的SD卡的基礎上,去Linaro的下載頁下載Linaro Ubuntu文件系統。我的選擇是15.03的nano版本,即linaro-utopic-nano-20150220-698.tar.gz文件。其他版本比nano更大,東西也更多。

SD卡第一個分區中保留boot.bindevicetree.dtbuImage三個文件,可以刪掉ramdisk免得不小心啟動進去了。按照下面的步驟將Linaro Ubuntu復制到sd卡的第二個分區(mmcblk0p2)中:

1.解壓縮壓縮包:

sudo tar zxf flinaro-utopic-nano-20150220-698.tar.gz

2.插入SD卡,你的OS可能將其自動掛載了,取消掉掛載。

sudo umount /dev/mmcblk0p2

3.將SD卡的第二個分區掛載

mkdir rootfs
sudo mount /dev/mmcblk0p2 rootfs

4.使用rsync來拷貝文件系統到SD卡,這可能得花一點時間,你得一直等到終端恢復響應:

sudo rsync –a binary rootfs
sync

5.解除SD卡的掛載:

sudo umount rootfs

從電腦拔出SD卡,插入ZedBoard開機,不過這時U-Boot仍然會試圖從ramdisk啟動,我們需要設置一下它:

1.ZedBoard啟動過程中按下任何鍵來阻止U-Boot啟動。

2.設置新的U-Boot環境變量

setenv bootargs 'console=ttyPS0,115200 root=/dev/mmcblk0p2 rw rootwait'
setenv sdboot 'echo Copying Linux from SD to RAM... && mmcinfo && fatload mmc 0 0x3000000 ${kernel_image} && fatload mmc 0 0x2A00000 ${devicetree_image} && bootm 0x3000000 - 0x2A00000' 

3.保存環境變量:

saveenv

4.輸入boot來啟動。

3.最復雜的方式

下面我們會試圖編譯任何可以編譯的東西

3.0 需要的文件

需要的源代碼大部分可以在Xilinx的GitHub頁面上找到。xlnx的后綴代表這是Xilinx的分支。可以使用git來下載。或者到GitHub下載zip。

需要關注的項目:

注意這幾個項目都挺大,包括歷史記錄就更大了。使用Git下載那龐大無用的.git文件夾可能會讓你掀桌子,推薦下載zip壓縮包。分別解壓到某目錄。

3.1 編譯環境

首先是需要的開發軟件和工具們,感謝Xilinx,只需要安裝一個套件Xilinx Vivado,它的WebPACK版本是免費的。

根據你的操作系統和版本選擇下載。主要需要的是Vivado和Software Development Kit(SDK),Documentation Navigator和License Management Tools隨意。推薦最大的All OS and SDK Full Installer。

安裝

解壓tar壓縮包到任意目錄,打開目錄。對於windows,雙擊運行xsetup.exe;對於Linux,./xsetup,如果要安裝到默認目錄/opt/Xilinx下,你可能需要root權限(sudo ./xsetup)。

跟隨安裝向導,在其詢問軟件版本時,選擇Xilinx Vivado WebPACK(免費!);在其詢問是否安裝Cable驅動時,對Linux應該不勾選,因為一般都會失敗(起碼我失敗了),最后還得自己處理;其他選項隨意。

安裝略消耗時間。

運行

Windows下不需要特別做什么,就可以從開始菜單或者桌面的快捷方式運行。Linux下需要一點點配置:

source /opt/Xilinx/Vivado/2013.4/settings32.sh

如果是64位系統:

source /opt/Xilinx/Vivado/2013.4/settings64.sh

sh文件會為你配置好環境變量,然后在終端就能在終端中運行開發工具了(主要是vivadoxsdk)。每次打開一個新的終端,都需要這么做一次,覺得太麻煩的話可以把這句寫在你的~/.bashrc里。不過這樣每次啟動終端都會看到sh文件的輸出,還可能會造成別的什么問題。可以修改sh文件,注釋掉所有echo的行。

許可證書

盡管WebPACK是免費的,仍需要從Xilinx官網取得許可證書。大概是提供郵箱,個人信息等注冊賬戶;生成一個WebPACK的證書;email給自己或者直接下載;得到文件Xilinx.lic

運行xlcm來導入證書,或者將其放在~/.Xilinx文件夾下。

關於驅動

目前我還沒有搞定Digilent USB-JTAG線的Linux驅動,沒有辦法用JTAG下載和調試,所以我滾去了Win。如果你用什么方法搞定了,請告訴我。

3.2 編譯FSBL

FSBL即第一階段啟動器,它負責初始化開發板,配置FPGA,之后將CPU交給第二階段啟動器(SSBL)接管。對於我們,SSBL就是U-Boot。

打開Xilinx SDK(快捷方式或者xsdk),新建一個項目,類型是New Application Project。填寫好項目名稱(比如myfsbl)目錄、硬件平台(zed_hw_platform)、處理器(PS7_cortexa9_0)、OS平台(Standalone)、語言(C)、版支持包(New一個!)之后不要直接結束,選擇下一步,使用Zynq FSBL模板。

SDK會產生3個項目:myfsbl、myfsbl_bsp、zed_hw_platform,並且自動編譯,生成二進制文件myfsbl.elf(在myfsbl/Debug/下)。我的Ubuntu13在這一步報錯了,因為沒有找gmake——為此你得把gmake指向make

cd /usr/bin
sudo ln -s make gmake

一般來說,這里自動生成的FSBL代碼不需要特別修改就能直接使用,不過你可能希望FSBL輸出一些信息用於debug(或者單純因為好奇)。修改src下的fsbl.h文件,在大篇注釋后,合理的位置增加一行:

define FSBL_DEBUG_INFO 

重新編譯文件!這樣FSBL在啟動過程中,就會向串口(USB-UART)輸出信息。關於此詳細的解釋看那大篇注釋。

生成的myfsbl.elf就可以用來替換下載得到的fsbl.elf

3.3 編譯bitstream文件

bitsteam文件,或者叫比特流文件(*.bit),被fsbl用來配置FPGA。對於Zedboard的啟動來說,這個是可選的。如果要使用Zedboard的FPGA部分,就得寫HDL代碼,來得到這個文件。這肯定是整個工程很大部分的工作量,好好努力吧。

或者下載一個別人已經寫好的bitstream文件。

3.4 編譯U-Boot

U-Boot也是一個bootloader,在ZedBoard啟動的第二階段,被用來啟動linux內核。適用於ZedBoard的U-Boot源代碼可以在Xilinx的U-Boot項目找到。

為了得到u-boot二進制文件,我們得編譯它。在Linux,打開終端,cd到u-boot文件夾下。確保編譯環境(source了Vivado的sh文件,有gcc能make)。

首先要配置使用什么交叉編譯器:

export CROSS_COMPILE=arm-xilinx-linux-gnueabi- 

注意最后的-。編譯可以分為兩步:

make zynq_zed_config
make

或者一步:

make zynq_zed

漫長的編譯過程之后,會得到兩個有用的東西:u-boot文件(在u-boot-xlnx/下,大約1.4MB)和mkimage工具(u-boot-xlnx/tools下)。將u-boot文件復制到boot_image文件夾,改名為u-boot.bin

mkimage小工具在之后的步驟中會用到,將其添加到PATH環境變量中。

cd tools
export PATH=`PWD`:$PATH 

3.5 將FSBL、bitstream、U-Boot合成啟動鏡像:

boot_image文件夾下新建一個文本文件boot.bif,寫入以下內容:

image : {
        [bootloader]fsbl.elf
        bitstream.bit
        u-boot.elf  
}

使用bootgen小工具(Vivado附帶)來生成啟動鏡像boot.bin

bootgen -image boot.bif -o i boot.bin

3.6 編譯Linux Kernel

編譯Linux內核。同樣需要配置好編譯環境,cdlinux-xlnx目錄下:

export CROSS_COMPILE=arm-xilinx-linux-gnueabi- export ARCH=arm 

之后先做配置:

make xilinx_zynq_defconfig
make menuconfig  #可選

編譯需要用到上節中生成的mkimage小工具,確保已將其所在目錄添加到PATH。如果你使用已經編譯好的U-Boot文件而跳過了上節,那么你應該從源里安裝它:

sudo apt-get install u-boot-tools

開始編譯:

make UIMAGE_LOADADDR=0x8000 uImage 

漫長的編譯之后,在<some-path>/linux-xlnx/arch/arm/boot/下,會生成ImagezImage兩個文件。如果你在上一步中為mkimage小工具配置好了環境變量,第三個文件uImage也會出現。如果忘記了,也可以手動生成:

mkimage -A arm -O linux –T kernel -d zImage uImage

得到uImage可以用來替換下載得到的文件。

3.7 修改BusyBox Ramdisk:

已經編譯好的Ramdisk我們沒有辦法從頭做這個文件,只能修改它:

解壓縮文件系統鏡像:

gunzip ramdisk.image.gz

掛載鏡像:

chmod u+rwx ramdisk.image
mkdir tmp/
sudo mount -o loop ramdisk.image tmp/
cd tmp/

修改文件內容,比如hostname

取消掛載:

sudo umount tmp/
gzip ramdisk.image

最后需要將已經其添加上U-Boot字頭。mkimage小工具會為你做這件事情:

mkimage -A arm -T ramdisk -C gzip -d ramdisk.image.gz uramdisk.image.gz

3.8 編譯Device Tree Blob

Device Tree描述了整個板子的硬件結構,是Linux內核啟動必不可少的部分。它主要涉及2個文件:dtsdtb、和一個小工具:dtc。其中dts是文本文件, 實用人類可讀的格式描述了硬件結構。dtb是二進制文件。兩者之間的轉換工具是dtc

需要注意的是,設備樹文件需要和bitstream文件對應,如果沒有設計FPGA,也就是沒有.bit文件的話,可以使用linux-xlnx下已經有的dts。如果要使用Linaro Ubuntu,並且不想第一次開機時手動配置U-Boot的話,打開zedboard.dts文件,將其中的:

bootargs = "console=ttyPS0,115200 root=/dev/ram rw earlyprintk";

修改為:

bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0";

這句定義了U-Boot將會傳遞給Linux Kernel的參數,console=ttyPS0,115200設置了系統的輸出將會送入ttyPS0這個設備,也就是USB-UART接口。而root=/dev/mmcblk0p2則是說明文件系統是SD卡的第二個分區。

linux-xlnx目錄下,

make zynq-zed.dtb

具體來說./scripts/dtc/dtc這個小工具將zrch/arm/boot/zynq-zed.dts編譯成了Device Tree Blob文件(在linux-xlnx/arch/arm/boot/dts/下),它可以用來替換下載得到的文件。

它也可以反向轉換dtb到dts文件:

./scripts/dtc/dtc -I dtb -O dts -o <devicetree name>.dts <devicetree name>.dtb

如果你設計FPGA生成了bitstream文件,就需要編譯得到對應的dts文件。這挺復雜,你得參考Xilinx的教程

至此我們自己編譯或者修改了所有能編譯和修改的文件。

4.DEBUG

如果順利,Zedboard應該直接啟動到Linux,提示符會告訴你OS已經准備好了:

zynq>

如果不那么順利的話……首先FSBL會輸出Debug信息,比如正在初始化開發板,正在配置FPGA等。FPGA配置完成之后,板上的藍燈會亮起。之后,如果成功啟動SSBL,在終端會看到SUCCESS HANDOFF(打開了FSBL的Debug信息)。接下來是U-Boot的輸出,默認情況下,U-Boot會在等待3秒鍾后,再次讀入MIO的設置來選擇啟動方式(第一次是BootROM上的啟動程序讀取的)。可以按下任意鍵取消自動啟動,這時能看到U-Boot的命令行界面(u-boot>提示)。鍵入help來查看可以使用的指令,使用env list來查看現在的環境參數。

U-Boot環境參數

注意U-Boot在啟動時會從Zedboard的SPI Flash(斷電不會丟失)讀取環境參數配置,如果Flash上已經被寫過了一些錯誤的配置(比如另一個U-Boot寫下的),可能會導致啟動錯誤,kernal panic等。使用env reset來重置這些參數為默認(默認參數在U-Boot代碼里),使用env save來覆蓋在Flash上。

U-Boot使用一些列環境參數來控制啟動過程,比如modeboot由U-Boot讀取啟動配置跳線來決定(sdboot、jtagboot、netboot等),bootargs是將會傳遞給Linux Kernel的參數(如果有,會覆蓋devicetree中定義的內容)。

U-Boot指令

Xilinx的wiki中,boot.bif文件是這樣寫的:

image : {
    [bootloader]fsbl.elf
    bitstream.bit
    u-boot.elf
    [offset=0x3000000]uImage.bin
    [offset=0x2000000]devicetree.dtb
    [offset=0x2A00000]ramdisk.image.gz
}

這樣,在制作boot.bin文件時,boot.bin文件將會包含uImage等3個文件(體積會大很多),並且FSBL將會把它們加載到SPI Flash中。這樣SD中就只需Boot.bin,不用再放這3個文件了。

但是即使不怎么做,如果你看過U-Boot的環境變量就會知道——U-Boot也會從SD卡中尋找這3個文件,加載到同樣的地址中。這時,就可以使用U-Boot的命令:

bootm 0x3000000 0x2000000 0x2A000000

來啟動Linux內核。這也是U-Boot自動啟動執行的最后一句命令。如果使用Linaro,那么我們沒有ramdisk。上面的啟動命令應該改成

bootm 0x3000000 - 0x2A000000

5.JTAG啟動

如果在處理了U-Boot之后,你還是沒有成功激動到Linux,那么可以嘗試從JTAG啟動:

將ZedBoard設置為JTAG啟動(MIO[3~5]都是0),從電腦連接兩條USB線纜到ZedBoard:USB-UART和USB-JTAG口。考慮到USB-JTAG驅動的問題,推薦Windows。

打開Xilinx SDK,在tools菜單中找到skd console,運行。它看起來和普通的cmd一樣。

cd到存放這些亂七八糟文件的文件夾,運行:

XMB

接下來:

connent hw
load fsbl.elf
con

等待一會兒,fsbl會完成初始化。

stop
fpga -s bitstream.bit #可選
load u-boot.elf
load -data uImage 0x3000000
load -data devicetree.dtb 0x2000000
load -data ramdisk.image.gz 0x2a00000
con

U-Boot將會運行,並且在終端輸出信息。按任意鍵停止U-Boot自動啟動。然后

bootm 0x3000000 0x2000000 0x2A00000

來啟動Linux。

6.參考

  1. Xilinx官方Wiki
  2. Analog的教程
  3. Archlinux ARM的教程
  4. Digilent的教程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM