通过QSPI启动ZedBoard并运行Ramdisk根文件系统

通过SD卡启动Linux,所需时间较长,将系统镜像存储到QSPI中,此过程则会迅捷很多。当然,ZedBoard自带的QSPI只有32MB,文件系统只能选用较小的Ramdisk了,因为此文件系统只存在于DDR中,每次在线对文件系统做了修改,掉电后修改都会消失,相当不便。结论是,此种方式适合简单应用的发布阶段。

折腾了几天,从官网获取了各个镜像或者其源码,并生成Mcs后烧录进了QSPI,将系统成功启动。通过本文记录如下。主要讲操作,涉及些许原理,遇到过的问题也对现象、思路、解决办法做了记录,分享给大家。更多的ZedBoard Demo教程,可以访问我的个人网站www.qingchengyouran.com获取。

环境

ZedBoard Zynq Evaluation and Development Kit (xc7z020clg484-1)
Xilinx SDK 2017.1
VMWare 12.5.2 build-4638234 + Ubuntu 14.04
交叉编译工具链使用arm-xilinx-linux-gnueabi-
putty_V0.63.0.0.43510830

概述

Zynq芯片启动流程如上图所示,可以看出想要将ZedBoard从QSPI卡启动,需要完成以下工作:

  1. 约定各系统镜像在QSPI中的存储区域,fsbl、bit、u-boot从0地址开始依次存储,主要需要定义内核、设备树、文件系统的存储区域。
  2. 获取启动所需镜像文件,包括fsbl.elf、bitstream、u-boot.elf、zImage、devicetree、linux根文件系统,
  3. 通过SDK生成.mcs文件,并通过Jtag烧写进QSPI,重启测试。

一、约定内核、设备树、文件系统在QSPI中的存储区域

考虑到各镜像大小分别是:fsbl + bit + u-boot = 5127KB,zImage=2404KB,devicetree=10KB,Ramdisk=3608KB,对QSPI的存储空间做如下分配:

/*
 * 32MB QSPI flash mapping
 *   start       end      size       name(size)
 * ---------------------------------------
 * 0x0000000 - 0x0800000  0x800000   FSBL+Bit+uBoot(8MB)
 * 0x0800000 - 0x0C00000  0x400000   uImage(4MB)
 * 0x0C00000 - 0x0C10000  0x010000   devicetree(64KB)
 * 0x0C10000 - 0x1010000  0x400000   ramdisk(4MB)
 * 0x1010000 - 0x1FFFFFF  0xFEFFFF   data(16MB-64KB)
 */

此约定需要同时作用于u-boot源码的include/configs/zynq-zed.h文件,以及通过SDK生成mcs文件时候的偏移地址设定。

二、FSBL、BitStream、Ramdisk获取

考虑从Digilent官网直接获取上述三个镜像。可以使用ZedBoard_oob_Design提供的文件,地址是:http://www.digilentinc.com/Data/Documents/Other/ZedBoard_OOB_Design.zip

其中FSBL没有必要自己新建,一般都不会调它,如果想要自己弄,可以参考“通过SD卡启动ZedBoard并运行Linaro根文件系统”。

Bitstream可以自己做一个,考虑到Digilent提供的System.bit对ZedBoard的各个外设做了很好的初始化和使用Demo,重新新建的想要达到此水准步骤较多,偷懒直接使用了。

Ramdisk也没有必要自己做,拿一个现成的做修改就可以了。

三、在虚拟机中编译出u-boot.elf

  1. 从GitHub上下载Digilent发布的u-boot源码,网址为 https://github.com/Digilent/u-boot-digilent/releases ,建议直接从releases中下载,我选用了V2012.04版本,
  2. 在虚拟机中解压,tar -zxvf u-boot-digilent-digilent-v2012.04.tar.gz,
  3. 进入u-boot,修改include/configs/zynq_zed.h文件,主要是对QSPI启动模式下Linux内核、devicetree、Ramdisk存储地址存储空间的定义和调用,QSPI中存储地址需要符合第一步的约定,
"qkernel_addr=0x0800000\0"         \
"qdevtree_addr=0x0C00000\0"         \
"qramdisk_addr=0x0C10000\0"         \
"qkernel_size=0x300000\0"        \
"qdevicetree_size=0x010000\0"        \
"qramdisk_size=0x400000\0"        \
"qspiboot=sf probe 0 0 0;" \
    "sf read 0x8000 ${qkernel_addr} ${qkernel_size};" \
    "sf read 0x1000000 ${qdevtree_addr} ${qdevicetree_size};" \
    "sf read 0x800000 ${qramdisk_addr} ${qramdisk_size};" \
    "go 0x8000\0" \
  1. 设置交叉编译工具链为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-
  1. 在根目录下生成了u-boot,即为镜像。通过mv u-boot u-boot.elf重命名为elf格式。

四、编译linux源码,生成zImage

  1. 从GitHub上下载Digilent发布的linux源码,网址为 https://github.com/Digilent/linux-digilent/releases ,从releases中下载,我选用了linux-digilent-3.6-digilent-13.01,
  2. 在虚拟机中通过tar -xvzf linux-digilent-3.6-digilent-13.01.tar.gz 解压,
  3. 打开终端,进入解压出的目录,依次执行如下两条指令,
export ARCH=arm
export CROSS_COMPILE=arm-xilinx-linux-gnueabi-
make digilent_zed_defconfig   # 对应arch/arm/configs 下的同名头文件
make LOADADDR=0x00008000
  1. 等待时间较长,生成的zImage在arch/arm/boot目录下。

五、生成devicetree.dtb

设备树devicetree是内核启动必须的,u-boot在跳到内核入口前会把这一块数据复制到DDR的已知地址。

  1. 使用gedit打开arch/arm/boot/dts/digilent-zed.dts文件,
  2. 设定bootargs参数,约定使用ramdisk文件系统,并指定其在内存中的存储区域
bootargs = "console=ttyPS0,115200 root=/dev/ram rw initrd=0x800000,8M init=/init earlyprintk rootwait devtmpfs.mount=1";
  1. 使用dtc工具将dts编译生成devicetree.dtb文件
./scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb ./arch/arm/boot/dts/digilent-zed.dts
  1. 此时devicetree.dtb文件生成在了linux内核根目录下

六、在SDK中调用bootgen工具,生成mcs文件,并烧写

  1. 将前几步获取的fsbl.elf、system.bit、u-boot.elf、zImage、devicetree、 ramdisk8M.image.gz放到同一个路径下,在SDK中Xilinx Tools -> Create Boot Image


其中zImage、devicetree.dtb、 ramdisk8M.image.gz的offset地址需要与第一步的约定保持一致,这样u-boot才能读取到,各镜像偏移地址如下:

the_ROM_image:
{
     [bootloader]./fsbl_debug.elf
     ./system.bit
     ./u-boot.elf
     [offset = 0x800000]./zImage
     [offset = 0xC00000]./devicetree.dtb
     [offset = 0xC10000]./ramdisk8M.image.gz
}
  1. 点击Create Image,生成Boot.mcs文件,
  2. 使用usb先,将PC于ZedBoard的usb-jtag口连接,最好将ZedBoard打到Jtag模式,给ZedBoard供电,
  3. SDK中Xilinx Tools -> Program Flash,在Image File中选中Boot.mcs文件,点击Program开始QSPI烧写


  4. usb-jtag速度可观,不到1分钟完成烧写,将ZedBoard置于QSPI启动模式下,加电,通过Putty可以看出ZedBoard成功启动了Linux系统,且启动时间只花了1.73秒,远比SD卡启动模式快。开发板上OLED也打印出了Digilent商标。


遇到过的问题

1、其间安装了office2019,结果Vivado/SDK打不开了,提示Microsoft Visual C++ 2015 Redistributable(x64),Error when launching 'vivado.bat',launcher time out


原因:office更新了部分Visual C的部件,Vivado2017只认Visual C++ 2015,更新的版本居然不认识。

解决办法:去掉SDK、Vivado启动过程中对Visual C++的版本Check,D:\Program_Files\Xilinx\Vivado\2017.1\bin\loader.bat,D:\Program_Files\Xilinx\SDK\2017.1\bin\loader.bat,使用rem # 注释掉如下line116~140


参考:https://forums.xilinx.com/t5/Installation-and-Licensing/Problem-with-Vivado-2017-1-and-Visual-Studio-2017/td-p/761515

2、使用ZedBoard的USB-JTAG,HardWare Manager和SDK都扫描不到链路
原因:ZedBoard的USB-JTAG驱动没有安装到位。
解决办法:在..\Xilinx\Vivado\2017.1\data\xicom\cable_drivers\nt64目录下,以管理员身份运行install_drivers_wrapper.bat。
如果安装可能存在问题,可以查看同目录下的install_drivers_wrapper.log,例如,如果不以管理员身份运行bat文件,安装处问题,体现在log中如下:
Driver Installer - Version 1.22 Already in the installer executable location. DriverInstaller->OS Version = Windows NT and later. Major Version = 6, Minor Version = 2, SP = 0. Cannot open SC Manager as an administrator. Opened SC Manager as non-admin. User is NOT in the admin group. User does not have Administrator privileges. Driver installation did not complete successfully.

3、U-BOOT识别不到QSPI Flash
现象:更新自己的MCS后,通过QSPI启动Linux失败,工作台显示

SF: Unsupported flash IDs: manuf 00, jedec 0000, ext_jedec 0000
Failed to initialize SPI flash at 0:0 (error -93)

u-boot中使用“sf probe 0 0 0”来识别QSPI,是这句命令没有得到正确的结果。

分析:1、板子开机自带的MCS可以启动Linux,所以ZedBoard硬件没有问题。 2、使用ZedBoard_oob_Design的镜像生成了MCS,Linux也可以正常启动,怀疑自己做的镜像有问题。 3、我使用了Xilinx提供的u-boot,这个u-boot是用来匹配Xilinx官方的ZC-702和ZC-706开发板的,不是ZedBoard的!

解决办法:从Digilent网站 https://github.com/Digilent/u-boot-digilent/releases 上下载u-boot-digilent-2012.04-digilent-13.01.tar.gz,这是匹配ZedBoard的源码,重新编译后测试果然OK。

4、ZedBoard Linux启动失败,停留在 Starting application at 0x00008000 ……


原因:使用了自己建的ZedBoard工程生成的Bit,导致出现此问题,更换成ZedBoard_oob_Design中提供的System.bit后,Linux正常启动

解决办法:暂时使用Digilent提供的system.bit,此问题留待后续深入研究后解决。

5、Ramdisk文件系统的疑惑,uramdisk.image.gz是什么?
ramdisk.image.gz根文件系统其格式与uboot不同,启动时uboot会提示ramdisk格式错误,若要让uboot能够识别ramdisk.image.gz根文件系统,需要利用mkimage工具给ramdisk.image.gz添加64bit的头部信息,生成uramdisk.image.gz。

在ubuntu中安装mkimage工具,命令如下:$ sudo apt-get install uboot-mkimage

通过ramdisk8M.image.gz生成uramdisk.image.gz的命令如下:

$ mkimage -A arm -T ramdisk -C gzip -n Ramdisk -d ramdisk8M.image.gz uramdisk.image.gz 

你可能感兴趣的:(通过QSPI启动ZedBoard并运行Ramdisk根文件系统)