从零开始驯服Linux(一):ZYNQ-Linux启动文件构建全解析
ZYNQ系列芯片集成了ARM处理器和FPGA(可编程逻辑单元),正是因为由于ARM处理器的存在,所以我们可以在ZYNQ系列芯片上面运行Linux系统。
在ZYNQ系列芯片上运行Linux会给我们带来很多优势:首先,我们可以将部分逻辑处理(比如信号处理、数据流控制等)放到FPGA中,剩下的操作交给ARM处理器执行。这样,硬件和软件可以无缝协同,优化整体系统效率;其次,运行Linux意味着可以使用Linux的丰富生态和开源资源。你可以利用大量的开源软件、驱动、工具和库,减少开发成本并加速开发周期。最后,ZYNQ的开发环境(如Xilinx的Petalinux)对Linux的支持非常好,同时也可以利用如GDB、JTAG等调试工具进行开发,便于定位问题并优化代码。
本教程我们就一起来看一下,如何基于正点原子提供的出厂相关源代码,制作ZYNQ开发板的启动文件,并成功运行Linux系统。
1.1制作前准备工作
1)一款ZYNQ开发板:本次以领航者ZYNQ-7020开发板来演示;
2)一台运行Ubuntu系统的计算机(或者虚拟机);
资料盘A盘:https://pan.baidu.com/s/1vXxmhg_mZm_OVg4xQeiCVQ 提取码:zdyz
资料盘B盘:https://pan.baidu.com/s/1NNYDCpEkM2jd6jR69Y1mfg 提取码:zdyz
1.2安装ZYNQ-7000交叉编译工具链
编译uboot和内核源码需要在linux系统(虚拟机)中安装相应的交叉编译工具链。安装ZYNQ-7000系列芯片的交叉编译工具链需要sdk.sh文件。
把开发板资料盘B盘:\sdk\202002\sdk.sh拷贝到Ubuntu虚拟机。拷贝完成后,在虚拟机中切换到sdk.sh文件所在目录,为sdk.sh文件赋予可执行权限并安装,命令如下:
#如果之前没有安装过build-essential、git、u-boot-tools,请先执行如下命令进行安装sudo apt updatesudo apt -y install build-essential git u-boot-tools#安装SDKchmod +x sdk.sh./sdk.sh
默认是安装在/opt/petalinux/2020.2 目录下,如果想安装在其他目录下,可以输入相应的路径,此处笔者保持默认,按回车键继续,结果如下图所示:
图 1.1.1 安装SDK
再次确认是否将SDK安装在/opt/petalinux/2020.2 目录下,默认为“Y”,也就是“是”,按回车键继续往下执行,显示要输入用户密码,输入完成后回车进行安装,等待安装完成。安装完成后提示每次当你在一个新终端中使用SDK,需要先执行“. /opt/petalinux/2020.2/environment-setup-cortexa9t2hf-neon-xilinx-linux-gnueabi”以设置相应的环境变量,其中的“.”和source具有相同含义。
1.3拷贝源码到Ubuntu系统
拷贝u-boot源码
开发板出厂镜像使用的u-boot源码路径为:开发板资料盘(A 盘)\4_SourceCode\3_Embedded_Linux\资源文件\出厂镜像相关,在该目录下有一个名为atk-zup-uboot-xlnx.tar.gz的压缩包文件,如下所示:
图 1.2.1 u-boot源码
atk-zynq-uboot-xlnx.tar.gz是专门用于开发板出厂测试的u-boot源码压缩包文件。我们将atk-zynq-uboot-xlnx.tar.gz压缩包文件拷贝到Ubuntu系统中,如下所示:
图 1.2.2 将u-boot压缩包文件拷贝到Ubuntu
接下来将其解压,对应的解压目录就是U-Boot源码目录,这个解压目录大家可以自己设置。因为解压后会自动在解压目录中创建一个名为atk-zynq-uboot-xlnx的文件夹,该文件夹下即是uboot源码。为了避免和教程中使用的uboot相混淆,笔者这里选择将其解压到用户家目录下的~/workspace/src目录中。
执行如下命令将其解压到~/workspace/src/目录中:
mkdir -p ~/workspace/src/ #创建~/workspace/src/文件夹cd /mnt/hgfs/share/source_code/ #切换到uboot压缩包文件所在目录tar -xzf atk-zynq-uboot-xlnx.tar.gz -C ~/workspace/src/ #解压ls ~/workspace/src/ls ~/workspace/src/atk-zynq-uboot-xlnx/
图 1.2.3 解压U-Boot源码包
解压完成后,atk-zynq-uboot-xlnx文件夹存放的即是出厂镜像使用的uboot源码。
拷贝内核源码
开发板出厂镜像使用的Linux内核源码路径为:开发板资料盘(A 盘)\4_SourceCode\3_Embedded_Linux\资源文件\出厂镜像相关,在该目录下有一个名为atk-zynq-linux-xlnx.tar.gz的压缩包文件,如下所示:
图 1.2.4 内核源码压缩包文件
atk-zynq-linux-xlnx.tar.gz是专门用于开发板出厂镜像的Linux内核源码压缩包文件。我们将atk-zynq-linux-xlnx.tar.gz压缩包文件拷贝到Ubuntu系统中,如下所示:
图 1.2.5 将内核源码压缩包文件拷贝到Ubuntu
接下来将其解压,对应的解压目录就是Linux内核源码目录,这个解压目录大家可以自己设置。因为解压后会自动在解压目录中创建一个名为linux-xlnx的文件夹,该文件夹下即是Linux内核源码。为了避免和教程中使用的Linux内核源码相混淆,笔者这里选择将其解压到用户家目录下的~/workspace/src目录中:
执行如下命令将其解压到~/workspace/src目录中:
mkdir -p ~/workspace/src/cd /mnt/hgfs/share/source_code/ #切换到uboot压缩包文件所在目录tar -xzf atk-zynq-linux-xlnx.tar.gz -C ~/workspace/src/ #解压sync
图 1.2.6 解压内核源码
解压完成后,得到的atk-zynq-linux-xlnx文件夹即是出厂镜像使用的Linux内核源码根目录。使用ls命令(ls ~/workspace/src/atk-zynq-linux-xlnx),可看到Linux内核源码目录结构,如下图所示:
图 1.2.7 Linux内核源码目录结构
拷贝xsa文件
使用xsa文件以创建相应的Petalinux工程,
在开发板资料包中,已经给大家提供了开发板出厂时所对应的vivado工程。
对于领航者7010开发板,使用的是Navigator_7010工程。
笔者以领航者7020开发板为例,路径为:开发板资料盘(A盘)\4_SourceCode\3_Embedded_Linux\vivado_prj,在这个目录下有一个压缩包文件Navigator_7020.zip,将其在Windows系统下解压,解压后如下图所示:
图 1.2.8 vivado工程目录
system_wrapper.xsa为Vivado导出的xsa文件,这里直接将system_wrapper.xsa文件夹拷贝到Ubuntu系统某个目录下,例如/mnt/hgfs/share/xsa/7020/,如下图所示:
图 1.2.9 将xsa文件拷贝到Ubuntu
1.4编译
在上一节中我们已经将编译所需要的所有“原材料”拷贝到Ubuntu系统了,接下来可以进行编译了,需要注意在是,在编译之前,需要安装Xilinx的petalinux工具,以及设置交叉编译工具链的工作环境。如果还没安装petalinux的,可以参考《领航者ZYNQ之嵌入式Linux开发指南》的第5章内容Petalinux的安装进行安装;设置交叉编译工具链的工作环境请参考下一小节。
1.5设置交叉编译工具链的工作环境
每打开一个新终端,都需要在终端中执行如下命令设置SDK的环境变量以使用交叉编译器:
. /opt/petalinux/2020.2/environment-setup-cortexa9t2hf-neon-xilinx-linux-gnueabi
如果不想每打开一个新终端就执行这个命令,可以将其放入~/.profile或者/etc/profile文件中,命令如下:
echo '. /opt/petalinux/2020.2/environment-setup-cortexa9t2hf-neon-xilinx-linux-gnueabi ' | tee -a ~/.profile #注意看下图,这条命令是完整的一行
tail -5 ~/.profile
结果如下图所示:
图 1.4.1 加载~/.profile文件时设置SDK环境变量
这样,将命令“. /opt/petalinux/2020.2/environment-setup-cortexa9t2hf-neon-xilinx-linux-gnueabi”写入到~/.profile文件中,启动虚拟机登录当前用户后会自动执行该命令。不过当前终端不可用,需要重启才能生效。
注:如果读者之前用相同的方式设置过Petalinux 2020.2版本的SDK,请先从~/.profile等文件中删除相关的行,或者直接使用之前的SDK,如果可用的话。
设置SDK的环境变量后,在终端输入命令arm-xilinx-linux-gnueabi-gcc --version来查看当前使用的交叉编译器版本号。看到如下结果,表明环境变量已经生效。
图 1.4.2查看 gcc 版本信息
可以看到,我们使用的zynq交叉编译器版本为9.2.0。
设置环境变量后可以使用env命令查看生效的环境变量,下图为部分截图:
图 1.4.3查看设置后的环境变量
不同的环境变量有不同的作用。比如环境变量CC,可以看出该环境变量已经配置好gcc交叉编译器编译时所用的参数,比如使用arm-xilinx-linux-gnueabi-gcc编译器,可直接使用环境变量$CC,如交叉编译某个.c文件,如hello.c,直接使用$CC hello.c就可以了。
创建Petalinux工程
创建Petalinux工程的步骤在《领航者ZYNQ之嵌入式Linux开发指南》第六章Petalinux设计流程实战中已讲解,本章就不细述,也可直接使用第六章Petalinux设计流程实战的Petalinux工程,重新导入xsa文件即可。
先在Ubuntu主机终端中选一个合适的路径以创建出厂镜像使用的Petalinux工程,然后在终端中输入如下命令:
cd <相应的目录> #切换到创建Petalinux工程的目录sptl #设置petalinux工作环境petalinux-create -t project --template zynq -n base #创建Petalinux工程cd base #进入到petalinux工程目录下petalinux-config --get-hw-description /mnt/hgfs/share/xsa/7020 #导入相应的xsa文件
以上命令执行完成之后会自动在当前目录下创建一个名为base的文件夹,也就是我们出厂镜像的petalinux工程对应的工程目录。
xsa文件导入成功之后会自动弹出petalinux工程配置窗口,如下图所示:
图 1.4.4 petalinux工程配置窗口
使用默认配置即可,保存并退出。
编译出厂源码u-boot、制作BOOT.BIN
进入到u-boot源码根目录下。
领航者开发板对应的配置文件为:configs/xilinx_zynq_virt_defconfig
领航者开发板对应的设备树文件为:arch/arm/dts/zynq-atk.dts
执行如下命令编译u-boot源码:
make distclean # 清理工程make xilinx_zynq_virt_defconfig #配置ubootmake -j # 编译
图 1.4.5 编译u-boot源码
编译成功之后,会在u-boot目录下生成镜像文件,如下所示:
图 1.4.6 生成镜像文件
u-boot.elf是一个elf格式的uboot可执行文件,u-boot.dtb是uboot的设备树文件。
输入如下命令生成boot.scr启动脚本文件:
./tools/mkimage -c none -A arm -T script -d atk-zynq-boot.cmd.default boot.scr
图 1.4.7 生成boot.scr
boot.scr是出厂镜像中uboot用于从相应的存储设备加载内核镜像和设备树的脚本文件。
切换到创建的Petalinux工程目录,执行下面的命令制作领航者开发板所需的启动文件BOOT.BIN:
petalinux-build -c bootloader #生成fsbl.elf文件petalinux-package --boot --fsbl --fpga \--u-boot ~/workspace/src/atk-zynq-uboot-xlnx/u-boot.elf \--dtb ~/workspace/src/atk-zynq-uboot-xlnx/u-boot.dtb --force
图 1.4.8 制作BOOT.BIN文件
注:如果编译报设备树相关的错误,请按照第六章Petalinux设计流程实战那样配置设备树,我们不用Petalinux编译的设备树,只是解决错误。
命令执行成功之后,会在当前Petalinux工程的images/linux目录下生成BOOT.BIN启动文件,如下图所示:
图 1.4.9 生成BOOT.BIN文件
编译内核、设备树
进入到Linux内核源码根目录下。
内核defconfig配置文件为:arch/arm/configs/xilinx_zynq_defconfig
领航者7020开发板对应的设备树文件为:arch/arm/boot/dts/atk-navigator-7020.dts
领航者7010开发板对应的设备树文件为:arch/arm/boot/dts/atk-navigator-7010.dts
执行如下命令编译内核源码:
make distclean # 清理工程make xilinx_zynq_defconfig # 配置make -j8 # 编译zImage和设备树
图 1.4.10 编译内核源码
编译得到的内核镜像文件zImage在arch/arm/boot目录下,如下图所示:
图 1.4.11 生成的内核镜像文件
编译得到的设备树文件在arch/arm/boot/dts目录下,如下图所示:
图 1.4.12设成的设备树文件
atk-navigator-7020.dtb对应领航者7020开发板的设备树文件;
atk-navigator-7010.dtb对应领航者7010开发板的设备树文件。
至此,启动开发板所需所有镜像文件都已经编译完成了,包括BOOT.BIN文件、boot.scr、zImage、设备树dtb四个文件。
1.6Linux启动!
制作一张SD启动卡,SD启动卡的制作方法,可以参考《领航者ZYNQ之嵌入式Linux开发指南》第六章Petalinux设计流程实战中的制作SD启动卡小节。这里不再赘述!
将上一节编译得到的四个镜像文件拷贝到SD启动卡的第一个分区,也就是Fat32分区,其中
BOOT.BIN文件位于Petalinux工程的images/linux目录下;
boot.scr位于uboot源码根目录下;
zImage文件位于linux内核源码根目录下的arch/arm/boot/目录下;
dtb文件位于linux内核源码根目录下的arch/arm/boot/dts/目录下。
拷贝完成后如下所示:
图 1.5.1 SD启动卡Fat分区文件
注:一般只需要拷贝开发板对应的设备树dtb文件就可以了,拷贝多个设备树文件也是可以的,启动过程中只用到开发板对应的设备树dtb文件。
接下来我们要拷贝根文件系统到SD启动卡第二个分区,在开发板资料包中已经给大家提供了出厂时使用的根文件系统,在开发板资料盘(A盘)\4_SourceCode\3_Embedded_Linux\资源文件\出厂镜像相关目录下有一个名为rootfs.tar.gz的压缩包文件,如下所示:
图 1.5.2根文件系统
rootfs.tar.gz中包含的根文件系统是出厂镜像使用的根文件系统,由于测试需要,笔者也移植了一些软件到其中。该根文件系统比较大、内容比较多,包括Qt5、Python、opencv等常用库文件。
将rootfs.tar.gz拷贝到Ubuntu系统中,然后使用tar命令将rootfs.tar.gz压缩包文件解压到SD启动卡的第二个分区,如下所示:
sudo tar -xzf rootfs.tar.gz -C /media/$USER/rootfsls /media/$USER/rootfssync
图 1.5.3 解压根文件系统到SD卡第二分区
sync同步完成之后,卸载SD卡(umount命令),拔掉SD卡将其插入开发板SD卡卡槽,将开发板启动方式设置为SD卡启动,连接串口、LCD屏和电源启动开发板,领航者开发板连接SD(TF)卡的正面图如下图所示:
图 1.5.4 开发板插入TF卡和串口
打开MobaXterm串口上位机或其它串口上位机。上位机打印Linux启动信息如下:
图 1.5.5 打印Linux启动信息
1.7扩展:如何使出厂镜像从QSPI启动?
出厂镜像将启动文件放在QSPI中,根文件系统存到eMMC中。从QSPI启动,首先需要像出厂镜像那样将zImage文件、dtb文件和bit文件打包成image.ub文件,打包方法如下:
首先进入到Linux内核源码根目录下。
对于7020核心板,输入如下命令即可:
mkimage -f zynq-fit-image.its image.ub
对于7010核心板,输入如下命令即可:
sed -i 's/7020/7010/g' zynq-fit-image.itsmkimage -f zynq-fit-image.its image.ub
生成的image.ub文件在内核源码根目录下,输入命令ls -l image.ub即可看到。
打包完成后,将image.ub文件和之前编译得到的BOOT.BIN、boot.scr文件拷贝到SD启动卡的第一个分区,也就是Fat32分区,其中
BOOT.BIN文件位于Petalinux工程的images/linux目录下;
boot.scr位于uboot源码根目录下;
image.ub文件位于Linux源码根目录下。
根文件依旧如前解压到到SD启动卡第二个分区。
从SD卡启动后,在串口终端中输入如下命令将启动镜像固化到QSPI和拷贝根文件系统到eMMC:
/opt/image/burn_qspi.sh
图 1.6.1 执行固化脚本
系统固化完成之后,蜂鸣器会响,表明已经将系统镜像和根文件系统分别烧写到了QSPI和eMMC存储介质中了,也意味着开发板可以从QSPI方式启动系统了。
在资料盘中我们提供了一个.img格式文件的出厂镜像,这里主要是为了方便大家直接烧录出厂程序到TF卡中启动开发板,烧录镜像的步骤可以参考《领航者ZYNQ开发板用户快速体验》文档。相比于我们刚刚制作的这些启动文件,一个独立的img镜像文件显然更方便我们烧录到TF卡来启动Linux系统,我们也收到过很多的私信想学习如何将这些启动文件转化成img镜像文件,后续我们也会给大家分享详细步骤,敬请期待!