Xilinx SDK安装
为了方便linux使用者,xilinx提供了一套SDK,使得linux BSP开发变得很轻松。第一步是下载Xilinx Vivado tools suite,或者xilinx SDK,下面都称SDK。SDK的安装比较简单,不需要太多步骤。安装SDK后,适用于zynq的交叉编译工具链就有了,运行一下提供的脚本settings64.sh(我的linux主机是64位ubuntu14.04)。如果在后面进行交叉编译时遇到很奇怪的问题,比如说编译器提示头文件或者c文件哪里有错误,可能是CROSS_COMPILE这个环境变量没有正确设置。此时可以通过命令export CROSS_COMPILE=arm-xilinx-linux-gnueabi-来设置它。
注意:Xilinx SDK的交叉工具编译链用于petalinux的应用程序或者驱动开发你看不到错误提示,但是程序无法运行(具体提示什么错误我忘记了)。petalinux和Xilinx SDK各自有一套工具用于交叉编译,具体有什么差别不得而知,但是尽量使用petalinux的工具是我的建议。
petalinux安装
除了App开发SDK和交叉编译工具链,官方还提供了一个构件系统,可以很简单地实现u-boot,kernel,root filesystem和device tree的构建和后期文件处理。这套工具对开发者隐藏了很多底层细节,使用文档手册详细介绍了如何通过若干个命令来生成基于JTAG/SD/TFTP启动的BOOT.BIN和image.ub。BOOT.BIN在本文与boot.bin是两种东西。
BOOT.BIN 由FSBL.elf、download.bit/pl.bit和u-boot.elf生成,从SD卡启动时需要用到它,这里的SD是指FAT格式的SD卡,里面存放BOOT.BIN文件,而不是EXT文件格式的SD卡。
boot.bin 由FSBL.elf、download.bit/pl.bit、u-boot.elf和image.ub生成,这个文件的生成需要用到bootgen,bootgen需要安装了Xilinx SDK才有。
image.ub其实不算是一个映象,而是一个映像的集合,包含多个独立的映像和相应的寻址信息。在这里指的是zImage.elf、device tree和root filesystem。在安装完成后,记得source
配置
zed-board bsp安装
构建linux之前,需要先建立一个petalinux的工程,我选择基于官方bsp建立工程的方式来建立,请参考相关设计指引。
petalinux的下载地址:http://www.xilinx.com/support/download/index.html/content/xilinx/en/downloadNav/embedded-design-tools.html
config
使用petalinux-config命令来进行构建参数的设置。kernel、u-boot和root filesystem可以单独进行细分配置,参考petalinux-config的帮助文档。
根据xilinx的规则,需要给每个可执行程序一个flash分区和分配相应的空间,如下图所示。因为boot分区准备放fsbl、bit文件和u-boot,所以开了6MB的空间。内核分区开始地址为0x600000。这些信息需要与boot.bif(下面生成二进制下载文件时需要用到)文件的信息一致。
subsystems/linux/configs/device-tree$ vim system-conf.dtsi
将分区与相应的程序映像绑定,也就是给常见的必需的linux组件分配flash存储空间。这样u-boot才知道内核映像和其它文件所在的分区。u-boot image可以选择存在flash和SD卡,这里需要选择flash(默认是选择SD)。kernel image比它多一种选择,用户需要从flash、SD和ethernet里面选择,默认是SD卡。下图是根据我的选择生成的config文件。
JFFS2实际上是不存在的,所以选择存在哪里都不要紧。DTB是内嵌到image.ub的,所以这里的选择也是无效的。BOOTENV不知道有什么用,反正没有看到一个单独的文件叫这样的名字的。也就是说,实际上起作用的就是BOOT.BIN和image.ub的存储选项。
通过上面的配置,系统知道了u-boot和kernel的存储介质和偏移地址。但是内核在运行时的地址还没有设置,物理内存的信息也需要配置。因为zedboard的内存为256MB,从0开始,所以内核也安排从地址0开始。u-boot text base address暂时不确定在我们这个应用中的实际作用,也许没有用到,有待验证。
0x400000的作用是告诉链接器u-boot在运行时的物理地址是0x400000的位置。这个从u-boot.map文件的内容可以看出来。我也尝试将fsbl的调试打开,信息验证了上面的分析。但是,有一个问题没有弄明白,接下来的启动过程里面,因为内核的地址是0x00000000,内核超过10MB,u-boot一旦解压内核,u-boot本身的代码就被覆盖了,但是它还是可以跳转到内核的开始地址0x00000000。按道理来说,代码被覆盖了,继续执行会遇到不可解释的结果,或者系统异常,但是这些都没有,很顺利地开始了内核的启动。我的理解是u-boot的代码有两份,内核覆盖了其中1份,另外1份还存在某个位置,flash、ddr、ocm或者L1/L2 cache都有可能。
u-boot配置
很奇怪,xilinx提供的BSP包名字是ZED Baord,但是u-boot的配置默认是Zynq ZC702 Board,所以这里修改了默认选项。
build
构建使用petalinux-build -c all命令。
后期制作
build命令执行完成,会在images/linux/下出现若干个文件,其中我们需要用到的是zynq_fsbl.elf、download.bit、image.ub、u-boot.elf。建立一个文本文件保存为boot.bif。输入以下内容。
执行bootgen -image boot.bif -o boot.bin。boot.bin需要通关jtag在windows下烧写到QSPI Flash。
注意:如果需要在SD卡启动,那需要两个文件,BOOT.BINpetalinux-package --boot --fsbl
u-boot工作原理
在用户指定的内存地址查找image,如果找到就解压到预先设定的另外一个目标地址,并跳转过去执行指令。
u-boot如何知道内存中是否有image,在用户指定的内存地址需要有1个数据结构,该数据结构包含内核(符合FIT标准)等映像的详细信息,这个数据结构一般由构建系统在编译内核时自动生成。要触发这个动作,可以通过调用u-boot命令行下的bootm命令。从上电到内核启动的过程简单描述如下
1. BOOT ROM运行FSBL
2. FSBL装载完bit文件后找到u-boot并运行。u-boot是在QSPI Flash里面直接运行的,不需要拷贝到DDR。
3. DDR检查是否有SD卡,发现没有,停下来等待用户命令。
4. 输入sf probe命令激活spi flash功能模块,输入sf read 0x10000000 0xc00000 0x1000000。
5. 上一步将image.ub拷贝到了DDR的0x10000000的地址。(image.ub是构建系统生成的,是一个很复杂的映像,简单来说包括内核映像、initRD映像、device tree和它们的寻址信息以及其它信息) 输入bootm命令后面加上参数0x10000000,内核启动开始,可以看到很多启动信息。
注:不要使用go命令来代替bootm,go是跳转到制定的地址执行指令,因为我们放在DDR里面的实际上是分区/文件,而不是最终的可执行的内核,所以需要使用可以对这个分区/文件进行处理的bootm命令。
参考文献:
http://www.xilinx.com/support/documentation-navigation/development-tools/software-development/petalinux-tools.html?resultsTablePreSelect=documenttype:SeeAll#documentation
实现USB host功能,需要修改device tree。
usb + host