新近入手了一块国产化ZedBoard,全兼容Digilent ZedBoard,物美价廉。通过几天时间摸索,u-boot,linux,linaro都从官网下载了源码并编译生成镜像,并通过SD卡启动成功,通过本文记录如下。主要讲操作,涉及些许原理,遇到过的问题也对现象、思路、解决办法做了记录,在这里分享给大家。更多的ZedBoard Demo教程,可以访问我的个人网站www.qingchengyouran.com获取。
概述
Zynq芯片启动流程如上图所示,可以看出想要将ZedBoard从SD卡启动,需要完成以下准备工作:
- 将SD卡分为fat32和ext4两个分区,fat32分区保存Linux的内核映像,ext4分区保存Linux文件系统,
- 通过Vivado生成Bit文件,
- 导出硬件配置,在SDK中生成fsbl文件,
- 编译u-boot源码生成u-boot.elf,将.bit、fsbl.elf、u-boot.elf合成为BOOT.BIN文件并拷贝到fat32分区,
- 编译xilinx-linux源码生成uImage,拷贝到fat32分区
- 在xilinx-linux源码中修改dts文件,并用dtc工具生成devicetree.dtb,拷贝到fat32分区
- 将linaro文件系统拷贝到ext4分区
可以使用我生成的镜像做测试, https://pan.baidu.com/s/1p2Pgu_YF-vdSDqxUYbxOcQ ,提取码:xtjq
环境
ZedBoard Zynq Evaluation and Development Kit (xc7z020clg484-1)
BanQ-A1 32G TF存储卡 + SanDisk microSD Adapter + 川宇USB3.0高速读卡器
Xilinx Vivado 2017.1
Xilinx SDK 2017.1
VMWare 12.5.2 build-4638234 + Ubuntu 14.04
交叉编译工具链使用arm-xilinx-linux-gnueabi-
putty_V0.63.0.0.43510830
一、SD卡分区
Xilinx推荐SD卡至少大于4GB,speed-grade为6或者更高,在Linux下操作,分区软件使用GParted。
- sudo apt-get install GParted ,安装 gparted分区工具,
- 插入SD卡,在VMWare中点击“虚拟机 -> 可移动设备 -> Prolific USB SD Card Reader -> 连接 ”,让ubuntu识别到SD卡,
- sudo gparted,运行GParted,
- 工具栏选择/dev/sdb,先umount已有分区,再Delete掉,为格式化做准备,
-
新建分区,第一个分区至少60MB,格式化为fat32文件系统,Free space preceding需要设置为4MB,Label为BOOT,
- 新建分区,第二个分区用完剩余空间,格式化为ext4文件系统,Label为rootfs。
- 在工具栏点击绿色的勾“Apply All Opertaions”,进行格式化。
以上操作请参考ug1144-petalinux-tools-reference-guide,configuring SD Card ext filesystem Boot
以上操作都是在Ubuntu中进行,也可以在Windows下对SD卡进行分区,具体步骤见在Windows下对ZedBoard SD卡进行分区。
二、新建Vivado工程并生成Bit文件
- 打开Vivado2017.1,Create Project,RTL Project,Board:ZedBoard Zynq Evaluation and Development Kit,Finish
- 左侧Project Manager -> IP Integrator -> Create Block Design , 在Diagram视图中Add Ip -> ZYNQ7 Processing System,并点击上方的Run Block Automation,Vivado会按照内置的ZedBoard电路自动生成部分连接,包括DDR等,
-
我只生成最简化的FPGA工程,所以打算去掉图中标红的部分的配置,双击Zynq IP,在弹出的窗口中依次去掉M AXI GP0 Interface、Timer 0、FCLK_CLK0的勾就可以,
-
特别注意,修改SD卡IO的Speed,从默认的fast->slow。并修改SDIO的Requested Frequency为25MHz(默认是50MHz)。这样可以适配更多种类的SD卡,以免部分品牌SD卡出现启动失败的情况,
-
此时Diagram如下图,通过Create HDL Wrapper自动生成顶层文件,再点击Generate BitStream,
- 等待几分钟,在...\zed_helloworld\zed_helloworld.runs\impl_1路径下生成bit文件。
三、在SDK中编译出fsbl.el
- 在上一步的Vivado工程中,File -> Export -> Export Hardware,勾选include bitstream,确认后会在vivado根目录下生成zed_helloworld.sdk文件夹及Zed_HelloWorld_wrapper.hdf文件,这就是bit对应的硬件描述文件,用以配置fsbl,
- File -> Launch SDK,在SDK中File -> New -> Application Project,在弹出的窗口中输入Project Name为zedhello_fsb,其它选项默认,点击Next,
- 在Templates中选择Zynq FSBL,点击Finish,
- SDK会自动编译出zedhello_fsbl.elf,默认在zed_helloworld.sdk/zedhello_fsbl/Debug路径下。
四、在虚拟机中编译出u-boot.elf,并在SDK中生成BOOT.BIN
- 从GitHub上下载Xilinx发布的u-boot源码,网址为https://github.com/Xilinx/u-boot-xlnx,建议直接从releases中下载,xilinx一般一季度更新一次,此处选择当前交叉编译工具(arm-xilinx-linux-gnueabi-)支持的较新的u-boot-xlnx-xilinx-v2016.4.tar版本,
- 在虚拟机中通过tar -xvf u-boot-xlnx-xilinx-v2016.4.tar解压,
- 进入u-boot,打开include/configs/zynq-common.h,将sdboot的参数修改如下:
"sdboot=if mmcinfo; then " \
"run uenvboot; " \
"echo Copying Linux from SD to RAM... && " \
"load mmc 0 ${kernel_load_address} ${kernel_image} && " \
"load mmc 0 ${devicetree_load_address} ${devicetree_image} && " \
"bootm ${kernel_load_address} - ${devicetree_load_address}; " \
"fi\0" \
- 设置交叉编译工具链为arm-xilinx-linux-gnueabi-,在终端中,依次执行如下两条指令
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- zynq_zed_config
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi-
- 在根目录下生成u-boot,即为镜像。通过mv u-boot u-boot.elf重命名为elf格式。
-
将前两步生成的zedhello_fsbl.elf、Zed_HelloWorld_wrapper.bit、u-boot.elf放到同一个路径下,在SDK中Xilinx Tools -> Create Boot Image
- 如上图配置,一次Add三个文件,其中zedhello_fsbl.elf为bootloader,另两个为datafile,点击Create Image,在同一路径下生成BOOT.BIN。
五、编译xilinx-linux源码,生成uImage
- 从GitHub上下载Xilinx发布的linux源码,网址为https://github.com/Xilinx/linux-xlnx,从releases中下载,xilinx一般一季度更新一次,此处选择当前交叉编译工具(arm-xilinx-linux-gnueabi-)支持的较新的xilinx-v2016.4.tar.gz版本,
- 在虚拟机中通过tar -xvzf u-boot-xlnx-xilinx-v2016.4.tar解压,
- 打开终端,进入解压出的目录,依次执行如下两条指令,
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- xilinx_zynq_defconfig
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- uImage LOADADDR=0x00008000
- 等待时间较长,生成的uImage在arch/arm/boot目录下。
六、生成devicetree.dtb
设备树devicetree是内核启动必须的,u-boot在跳到内核入口前会把这一块数据复制到DDR的已知地址。
- 使用gedit打开arch/arm/boot/dts/zynq-zed.dts文件,
- 将第15行#include "zynq-7000.dtsi"修改为 /include/ "zynq-7000.dtsi"
- 在第34行添加bootargs参数
bootargs = "console=ttyPS0,115200 root=/dev/mmcblk0p2 rw earlyprintk rootfstype=ext4 rootwait devtmpfs.mount=0"; - 使用dtc工具将dts编译生成devicetree.dtb文件
./scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb ./arch/arm/boot/dts/zynq-zed.dts - 将前几步生成的Boot.bin,uImage,devicetree.dtb拷贝到SD卡Fat32分区中
七、将Linaro根文件系统拷贝到SD卡ext4分区
- 从Linaro官网http://release.linaro.org下载ubuntu版本,我选择的是archive->12.11-> ubuntu -> precise-images -> ubuntu-desktop -> linaro-precise-ubuntu-desktop-20121124-560.tar.gz,
- 将SD卡连接上虚拟机,识别出ext4分区,其地址为/media/username/rootfs,
- 通过以下命令,将linaro系统直接解压进SD卡的ext4分区,因为Linaro系统较大,这一步一定使用高速读卡器和较好的SD卡,否则等待时间会非常非常长,而且容易出问题。
sudo tar --strip-components=3 -C /media/username/rootfs -xzpf linaro-o-ubuntu-desktop-tar-20111219-0.tar.gz binary/boot/filesystem.dir
八、通过SD卡启动ZedBoard
-
将ZedBoard启动选择处跳帽设置如下图,配置为SD卡启动,并在卡槽中插入SD卡,
- 连接串口线,在电脑上打开Putty,设置对应串口,Speed为115200,Open,
-
ZedBoard供电,Zynq会自动从SD卡读取各系统镜像,可通过Putty观察其启动顺序,最终启动后文件系统如下图所示
遇到的问题
-
更换USB3.0读卡器后,ubuntu提示设备“Prolific USB SD Card Reader”无法连接到理想的主机控制器。
解决办法:关闭ubuntu,在虚拟机设置 -> USB控制器 -> USB兼容性 中选择 USB3.0,重启虚拟机,问题解决。
u-boot编译报错,In file included from tools/aisimage.c:10:0: include/image.h:949:27:fatal error: openssl/evp.h: No such file or directory # include
原因:缺库文件
解决办法:sudo apt-get install libssl-devdts编译报错,Error: ./arch/arm/boot/dts/zynq-zed.dts:15.1-9 syntax error FATAL ERROR: Unable to parse input tree
原因:第15行语法错误
解决办法:将第15行#include "zynq-7000.dtsi"修改为 /include/ "zynq-7000.dtsi"-
Boot.bin不启动,不知道死在了哪一步
思路:fsbl是第一个启动的个性文件,默认fsbl是关闭了调试信息的,应该打开FSBL调试信息,再观察具体在哪里出的错
解决办法:在SDK,fsbl工程的Properties,C/C++ Build -> Settings -> ARM v7 gcc compiler -> Symbols,添加“FSBL_DEBUG_INFO”,如下图所示。
重新编译fsbl,并生成boot.bin文件,copy到SD卡FAT32分区,上电,putty打印如下信息,可以明确定位到FSBL启动过程中的问题了。
更多的Zynq fsbl阶段调试方法,可以参考https://www.cnblogs.com/otod3r/p/5275732.html,内含安富利工程师的邮件摘抄。 -
FSBL启动报错,SD:Unable to open file BOOT.BIN:1,SD_INIT_FAIL,FSBL Status = 0xA009
原因:FSBL的SD驱动存在问题,对SD卡品质比较挑剔
解决办法:修改SD卡IO的Speed,从默认的fast->slow。并修改SDIO的Requested Frequency为25MHz(默认是50MHz)。这样可以适配更多种类的SD卡,以免部分品牌SD卡出现启动失败的情况。
内核启动失败,出现Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(179,2)
思路:a、观察得知,uboot和linux能够启动,说明fat32分区OK,rootfs位于ext4分区,这里有问题。 b、通过QSPI启动ZedBoard并挂载ramdisk文件系统,直接使用zedboard_oob_design的镜像就可以。然后通过mount -t ext4 /dev/mmcblk0p2 /mnt来手动mount此分区。结果打印如下信息:
[ 421.640000] EXT4-fs (mmcblk0p2): INFO: recovery required on readonly filesystem
[ 421.650000] EXT4-fs (mmcblk0p2): write access unavailable, cannot proceed
mount: mounting /dev/mmcblk0p2 on /mnt failed: Invalid argument
观察这个打印信息,发现是readonly filesystem,怀疑SD卡处于只读状态。因为FAT32分区的镜像只需要读取就OK,所以不影响系统初始阶段的启动,但是到了rootfs,需要读写交换数据,系统启动就失败了。
解决办法:把SD卡只读拨片往上拨动,让SD卡处于可读可写状态,如下图所示
- Linaor启动后,提示EXT4-fs (mmcblk0p2): mounted filesystem with ordered data mode. Opts:(null) Kernel panic - not syncing: No working init found.
分析:用了不合适的方式,将rootfs文件系统放到了SD卡的ext4分区,会提示此问题
解决办法:a、使用本文的解压命令,可以避免此问题
sudo tar --strip-components=3 -C /media/username/rootfs -xzpf linaro-o-ubuntu-desktop-tar-20111219-0.tar.gz binary/boot/filesystem.dir
b、使用xilinx官方ug1144-petalinux-tools-reference-guide推荐的方法,将rootfs.tar拷贝到SD卡中再解压