OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 404|回复: 0

《DFZU2EG_4EV MPSoC开发板之嵌入式Linux 驱动开发指南》 第十六章 另一种方式编译ZYNQ镜像

[复制链接]

1061

主题

1072

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4407
金钱
4407
注册时间
2019-5-8
在线时间
1196 小时
发表于 2024-2-26 16:56:33 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2024-2-26 16:56 编辑

第十六章 另一种方式编译ZYNQ镜像

1)实验平台:正点原子 DFZU2EG_4EV MPSoC开发板

2) 章节摘自【正点原子】DFZU2EG_4EV MPSoC开发板之嵌入式Linux 驱动开发指南 V1.0


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz-MPSOC.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)Linux技术交流QQ群:887820935

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

由于前面我们一直都是使用xilinx的petalinux工具编译镜像文件,例如包括u-boot、linux内核、设备树、ZYNQ PL端的bitstream文件以及fsbl等,虽然petalinux功能上比较全面,但是在编译速度上太慢了!相信大家在使用petalinux的时候已经感受到了。为此笔者专门去研究了一下,那本章笔者就带大家通过另外一种比较快的方式编译各种镜像文件。
本章采用分步式的方式编译启动开发板所需要的各种镜像文件,虽然步骤比较繁琐,但灵活性比较高;虽然本章使用的是另一种方式编译镜像,但还是得需要用到petalinux提供的一些工具,所以大家一定要安装petalinux。

1.1 创建Petalinux工程,生成BOOT.BIN
对于Zynq MPSoC而言,一个完整的linux系统包含PS和PL两个构件,其中PS构件包含fsbl、uboot、设备树文件、linux内核、根文件系统共5个要素,PL构件包含bit文件一个要素,当不使用PL的时候,该要素非必须。
编写linux驱动的时候,经常改动的要素有设备树文件、linux内核、根文件系统,当然如果改动PL的话还需改动bit文件。因而我们将这些要素独立出来,从而方便修改变更。也就是说我们将bit文件从原先的BOOT.BIN文件独立出来,将image.ub文件分开为内核Image和设备树dtb。另外将根文件系统放到SD卡的EXT4分区,加载启动速度。下面我们正式开始。
将开发板资料盘(A盘)\4_SourceCode\3_Embedded_Linux\vivado_pro\4ev\base\system_wrapper.xsa文件复制到Ubuntu系统目录下,例如/home/shang/xsa/目录,大家根据自己的情况选择目录。本实验以MPSoC 4ev开发板为例,如果大家用的是MPSoC 2eg开发板,则选择开发板资料盘(A盘)\4_SourceCode\ 3_Embedded_Linux\vivado_prj\2eg\base\system_wrapper.xsa文件。
复制完成后,在xsa目录下有一个system_wrapper.xsa文件,如下所示:                        
image001.png
图 16.1.1 xsa文件
创建Petalinux工程的步骤在第六章Petalinux设计流程实战中已讲解,本章就不细述。在当前xsa路径下输入如下命令:
  1. sptl                                    //设置petalinux工作环境
  2. petalinux-create -t project --template zynqMP -n ALIENTEK-ZYNQ-MPSOC
  3.                                        //创建petalinux工程
  4. cd ALIENTEK-ZYNQ-MPSOC             //进入petalinux工程目录下
  5. petalinux-config --get-hw-description ../       //导入xsa文件
复制代码
以上命令执行完成之后会自动在当前目录下创建一个名为ALIENTEK-ZYNQ-MPSOC的文件夹,也就是我们出厂镜像的petalinux工程对应的工程目录。
注:后面更新vivado工程的时候,只需要从vivado工程中导出xsa文件,并在该Petalinux工程下使用“petalinux-config--get-hw-description <xsa文件路径>”命令重新配置即可。
xsa文件导入成功之后会自动弹出petalinux工程配置窗口,如下图所示:
image003.png
图 16.1.2 petalinux工程配置窗口
进入“Subsystem AUTO Hardware Settings”菜单,然后进入“SD/SDIO Settings”子菜单,接着按回车键,将PrimarySD/SDIO设置为“psu_sd_1”,保存并返回到“Subsystem AUTO HardwareSettings”菜单界面。
进入“Advanced bootable images storage Settings”子菜单中,移动到“dtb image settings”选项,如下图所示:
image005.png
图 16.1.3移动到“dtb image settings”选项
进入“dtb image settings”选项并将image storage media设置为primary sd,如下图所示:
image007.png
图 16.1.4设置image storage media为primary sd
配置完成后,返回到最初的顶层配置界面,进入到“Image Packaging Configuration”菜单下的“Root filesystem type (INITRAMFS)”子菜单下,如下图所示:
image009.png
图 16.1.5 选择EXT(SD/eMMC/QSPI/SATA/USB)
选择“EXT”,按键盘上的“Enter”键,然后返回到上一级,进入“Device node of SDdevice”子菜单,设置为“/dev/mmcblk1p2”,表示根文件系统在sd卡第二个分区,如下图所示:
image011.png
图 16.1.6配置Device node of SD device
保存并退出。
上面的配置是将dtb文件从image.ub文件中独立开来,并将根文件系统放到外部存储,例如SD卡的EXT4分区,而不是放在image.ub中。
接下来如果直接编译的话,会报设备树错误,提示设备树中缺少phy1,所以我们打开工程目录/xsa/ALIENTEK-ZYNQ-MPSOC/project-spec/meta-user/recipes-bsp/device-tree/files下的system-user.dtsi文件,向其中添加gem0节点。添加后的设备树文件如下所示:
  1. /include/"system-conf.dtsi"
  2. / {
  3. };
  4. &gem0{
  5.     psu_ethernet_0_mdio: mdio {
  6.         #address-cells = <1>;
  7.         #size-cells = <0>;
  8.         phy1:phy@4 {
  9.             reg = <0x4>;   /* YT8521 phy address */
  10.         };
  11.         gmii_to_rgmii_0: gmii_to_rgmii_0@0 {
  12.                         compatible ="xlnx,gmii-to-rgmii-1.0";
  13.                         phy-handle =<&phy1>;
  14.                         reg = <0>;
  15.         };
  16.     };
  17. };
复制代码
配置完成后,编译fsbl和uboot,及生成BOOT.BIN文件,命令如下:
  1. petalinux-build -c bootloader
  2. petalinux-build -cu-boot
  3. petalinux-build -cpmufw             //编译电源管理文件
  4. petalinux-build -c arm-trusted-firmware  //编译安全固件
  5. petalinux-package--boot --fsbl --u-boot --force
复制代码
执行结果如下图所示:
image013.png
图 16.1.7 生成BOOT.BIN
可以看到BOOT.BIN文件包含zynqmp_fsbl.elf和u-boot.elf文件,而没有包含bit文件,此外,pmufw.elf是电源管理文件,bl31.elf是加密固件文件。这四个文件我们基本不会再改动,所以后面无论编写任何linux驱动以及更改Vivado工程,都不会改动BOOT.BIN文件了。
1.2 自动生成设备树文件
在Petalinux工程中执行编译uboot后,会在工程的components/plnx_workspace/device-tree/device-tree/目录下生成设备树文件,如下图所示:
image015.png
图 16.2.1 设备树文件
上图中红框圈出的是我们需要用到的设备树文件,每个文件的介绍可参考12.4.4小节。
我们打开设备树system-conf.dtsi文件,可以看到bootargs的值为"earlycon console=ttyPS0,115200clk_ignore_unused root=/dev/mmcblk1p2 rw rootwait",如下图所示:
image017.png
图 16.2.2 bootargs的值
其中“root=/dev/mmcblk1p2 rw rootwait”表示从sd卡第二分区启动根文件系统,这个参数我们后面会用到。这个参数是16.1节配置“Device node of SD device”选项后产生的。
Linux设备树是是一个很重要的知识点,将会在后面的章节给大家详细说明,本章先不讲,这些文件后面我们会用到。
至此,该小节内容结束,请继续下一小节的内容。
题外话:
如果读者在实际使用中需要使用新vivado工程的时候,BOOT.BIN文件是不需要变动的,但设备树文件会随着Vivado工程的不同而需要改动,所以需要重新生成设备树文件。
重新生成设备树文件的方法有如下两种:
第一种,也就是上一小节注中讲到的‘后面更新vivado工程的时候,只需要从vivado工程中导出hdf文件,并在该Petalinux工程下使用“petalinux-config--get-hw-description hdf文件路径”命令即可’。使用新Vivado工程的hdf文件配置Petalinux工程并不会生成新的设备树文件,还需要执行编译命令才行(不知道是不是Petalinux的一个小bug),例如编译uboot:
  1. petalinux-build -c u-boot
复制代码
只有在编译完成后,才会在Petalinux工程的components/plnx_workspace/device-tree/device-tree/目录下生成新的设备树文件。
1.3 编译kernel
本节内容可直接参考13.6小节。
1.4 编译rootfs
根文件系统我们直接使用petalinux进行编译即可。首先设置环境变量,然后进入到Petalinux工程目录下(/home/shang/xsa/ALIENTEK-ZYNQ-MPSOC/)。为了免去后面每次启动linux都要手动输入密码进入系统,所以我们先配置根文件系统免密码登录,进入根文件系统配置界面的命令如下:
  1. petalinux-config -c rootfs
复制代码
进入“Image Features  --->”菜单下,使能“debug-tweaks”,如下图所示:
image019.png
图 16.4.1使能“debug-tweaks”
这样配置后,会自动登录,不用再手动输入用户名和密码,方便调试。
配置完成后,保存退出。
接下来直接编译根文件系统:
  1. petalinux-build -c rootfs
复制代码
image021.png
图 16.4.2编译根文件系统
等待其编译完成,完成之后产生的根文件系统压缩包在images/linux目录下,如下所示:
image023.png
图 16.4.3产生根文件系统的压缩包
因为我们要使用SD卡启动,并且SD卡会有一个EXT4格式的分区专门存放根文件系统,所以我们要使用压缩格式的根文件系统,例如rootfs.tar.gz或rootfs.tar.bz2。
1.5 启动开发板
在第六章实验中,我们使用petalinux工具生成的BOOT.BIN和image.ub两个文件启动开发板,但是这里我们不这样做。
前面给大家介绍过image.ub这个文件的本质,那么它其实是多个文件组合在一起的,包括内核镜像、dtb以及根文件系统,这样的做法有一个弊端,不够灵活,一个变了整个image.ub文件就得重新制作一遍,很麻烦。同样BOOT.BIN文件是fsbl镜像、u-boot镜像以及pl端bit文件集合在一起的,那么既然是集合在一起的,那么我们单独使用也是可以的嘛。
经过本章前面几小节一系列的过程之后,我们就已经得到了启动开发板的所有所需的镜像文件了。所以我们这里的思路就是将内核镜像文件Image、内核设备树文件以及根文件系统从image.ub文件中分离出来;而将bit文件从BOOT.BIN文件中分离出来,这样做之后我们的SD卡中将会存在5部分内容:Image、dtb、rootfs、bit以及BOOT.BIN(fsbl镜像与u-boot镜像的集合体),明确之后我们将他们拷贝到我们的SD卡中。
step1、制作SD启动卡
SD启动卡的制作方式在6.3.10小节当中已经给大家介绍过了,这里不再细说,笔者直接将一张16G的TF卡格式化了2个分区,FAT32和EXT4,使用“df -Th”命令查看SD卡分区信息,如下所示:
image025.png
图 16.5.1 SD启动卡分区信息
step2、拷贝镜像到FAT分区
将前面过程当中生成的各种镜像文件拷贝到SD启动卡的FAT分区,包括Image(内核镜像,内核源码目录arch/arm64/boot/Image)、system-top.dtb(内核设备树dtb文件,内核源码目录arch/arm64/boot/dts/xilinx/system-top.dtb)、system.bit(pl端bitstream文件,/home/shang/xsa/ALIENTEK-ZYNQ-MPSOC/images/linux/system.bit,注意路径不要和第六章的工程混淆了)、BOOT.BIN(/home/shang/xsa/ALIENTEK-ZYNQ-MPSOC/images/linux/)。大家根据自己前面步骤当中文件存放的目录去找到相应的这些镜像文件,注意复制之前确保FAT分区没有上述文件。
复制完成后,看看我们的FAT分区有哪些文件:
image027.png
图 16.5.2 FAT分区中的文件
我们将system-top.dtb重命名为system.dtb,如下图所示:
image029.png
图 16.5.3设备树镜像重命名
step3、将根文件系统解压到EXT4分区
接下来我们需要将16.4小节编译的根文件系统压缩包文件解压到SD启动卡的EXT4分区,这里笔者使用rootfs.tar.gz压缩包文件,进入到rootfs.tar.gz压缩包文件所在目录,执行解压命令(解压之前确保EXT4分区没有根文件系统):
  1. sudo tar -xzf rootfs.tar.gz -C /media/shang/rootfs
复制代码
image031.png
图 16.5.4解压rootfs.tar.gz
/media/shang/rootfs是笔者的SD启动卡对应的EXT4分区的挂载点,注意解压的时候需要使用前面要加sudo,也就是要以root用户的身份进行解压。解压完成之后执行sync命令将数据同步到SD卡中,之后卸载SD启动卡,卸载成功之后拔掉它。
image033.png
图 16.5.5卸载SD启动卡
step4、启动开发板
将我们做好的启动卡插入开发板,启动模式设置为sd卡启动,连接串口,最后连接电源启动,打印信息如下所示:
image035.png
图 16.5.6 开发板启动
在U-Boot启动倒计时结束之前,按回车或者是空格键停止启动,进入到U-Boot的命令行模式,因为现在不能直接启动,我们需要对U-Boot环境变量进行修改,在U-Boot命令行下执行下面这些命令设置环境变量,如下所示:
image037.png
图 16.5.7 设置环境变量
  1. env default -a
  2. setenv bitstream_load_address 0x4000000
  3. setenv bitstream_image system.bit
  4. setenv bitstream_size 0x5000000
  5. setenv kernel_img Image
  6. setenv dtbnetstart 0x100000
  7. setenv netstart 0x200000
  8. setenv bootargs = "earlyconconsole=ttyPS0,115200 clk_ignore_unused root=/dev/mmcblk1p2 rw rootwait"
  9. setenv default_bootcmd 'ifmmcinfo; then run uenvboot; echo Copying Linux from SD to RAM... &&load mmc 1 ${bitstream_load_address} ${bitstream_image} && fpga loadb 0${bitstream_load_address} ${bitstream_size} && run cp_kernel2ram&& run cp_dtb2ram && booti ${netstart} - ${dtbnetstart}; fi'
复制代码
需要注意的是命令中间的空格不要漏掉了,因为以前发现很多初学者老是会漏掉这些空格,这样就导致命令执行失败。
关于U-Boot命令的使用在前面已经给大家讲解过,不过这里也给大家简单地说明一下我们设置的这些环境变量的作用:
首先第一条命令就是将uboot的环境还原到当前设置;第二条命令我们设置了bitstream文件从SD卡中拷贝到内存中的地址;第三条命令设置了bitstream_image变量等于SD卡中bitstream文件的名字,也就是system.bit;第四条命令设置了bitstream_size变量等于bitstream文件的大小;第五条命令设置了kernel_image变量等于SD卡中内核镜像的名字,也就是Image;第六条命令设置了dtbnetstart变量,也就是设备树dtb文件从SD卡拷贝到内存中的地址;第七条命令设置了netstart变量,也就是内核镜像文件从SD卡拷贝到内存中的地址。dtbnetstart和netstarte变量在我们的这个U-Boot中默认是有的,只不过它们的内容并不适合当前的环境,所以需要重新设定。
第八条命令设置了bootargs变量,这个变量传递给内核,最重要的作用就是指明根文件系统存储的位置。
最后一条命令设置了default_bootcmd变量,其实这个变量在我们使用的这个U-Boot中也是存在的,这里也是对他重新定义,这个变量的内容很长,我们可以把它的内容整理一下,如下:
  1. 示例代码16.5.1 default_bootcmd变量内容整理
  2. ifmmcinfo; then
  3.     run uenvboot;
  4.     echo Copying Linux from SD to RAM... &&                     // 打印字符串
  5.     load mmc 1 ${bitstream_load_address} ${bitstream_image} &&  // 从SD卡拷贝bitstream文件到内存
  6.     fpga loadb 0 ${bitstream_load_address} ${bitstream_size} && // 从内存中加载bitstream数据到FPGA
  7.     run cp_kernel2ram &&                   // 从SD卡拷贝内核镜像到内存
  8.     run cp_dtb2ram &&                       // 从SD卡拷贝设备树到内存
  9.     booti ${netstart} - ${dtbnetstart};  // booti启动内核
  10. fi
复制代码
“&&”符号其实就是C语言中的“与”,跟C语言里面的作用一样;${xxx}就是变量的引用;if … fi这个就是if条件判断语句了,fi表示条件判断的结束,U-Boot里边的这种语法很简单地,就不给大家细说了,如果不明白可以在网上找找资料。
前面跟大家讲过,U-Boot中的bootcmd变量的作用,U-Boot启动内核或在命令行下执行boot命令时其实就是去执行bootcmd,那我们来看看bootcmd的内容是什么:
image039.png
图 16.5.8 bootcmd的内容
所以从上面可以知道,bootcmd的内容其实就是运行default_bootcmd,也就是上面定义的那个。
变量设置完成之后,执行“saveenv”命令保存环境变量到QSPI Flash中,那么下次就不用再设置了
保存完成执行“boot”命令启动内核:
image041.png
图 16.5.9 启动内核
启动完成之后进入系统:
image043.png
图 16.5.10 登陆系统
step5、另一种方式——NFS方式挂载根文件系统
我们在上一步启动开发板时,通过设置bootargs变量,从sd卡ext4分区加载根文件系统,考虑方便后面开发驱动,我们换一种方式,通过NFS方式挂载根文件系统。
首先进入/home/shang/workspace/nfs/路径下,该路径下有一个rootfs文件夹,删除该文件夹内原有的根文件系统,如下图所示:
image045.png
图 16.5.11删除原有的根文件系统
进入16.4节生成rootfs.tar.gz文件的路径下,将rootfs.tar.gz文件解压到rootfs目录。命令如下:
  1. tar -xzvf rootfs.tar.gz -C ~/workspace/nfs/rootfs/
复制代码
结果如下图所示:
image047.png
图 16.5.12解压rootfs.tar.gz文件
image049.png
图 16.5.13解压后的rootfs目录
将前面做好的启动卡插入开发板,启动模式设置为sd卡启动,连接串口,用网线连接开发板ps网口和电脑(按照13.6.3节设置网络环境变量,如果电脑连接无线网,要断开无线网),最后开发板连接电源启动,进入uboot模式,如下图所示:
image051.png
图 16.5.14进入uboot模式
首先需要设置step4中设置的环境变量:
  1. env default -a
  2. setenv bitstream_load_address 0x4000000
  3. setenv bitstream_image system.bit
  4. setenv bitstream_size 0x5000000
  5. setenv kernel_img Image
  6. setenv dtbnetstart 0x100000
  7. setenv netstart 0x200000
  8. setenv default_bootcmd 'ifmmcinfo; then run uenvboot; echo Copying Linux from SD to RAM... &&load mmc 1 ${bitstream_load_address} ${bitstream_image} && fpga loadb 0${bitstream_load_address} ${bitstream_size} && run cp_kernel2ram&& run cp_dtb2ram && booti ${netstart} - ${dtbnetstart}; fi'
复制代码
然后输入如下命令设置bootargs变量:
  1. setenv bootargs ‘console=ttyPS0,115200root=/dev/nfs rwnfsroot=192.168.2.21:/home/shang/workspace/nfs/rootfs,nfsvers=3ip=192.168.2.22:192.168.2.21:192.168.2.1:255.255.255.0::eth1:off’
复制代码
输入“saveenv”保存环境变量,然后输入“boot”命令启动内核,如下图所示:
image053.png
图 16.5.15设置环境变量
image055.png
图 16.5.16启动内核
image057.png
图 16.5.17进入linux系统
最后进入linux系统,如上图所示。通过NFS方式挂载根文件系统能方便驱动开发,后面我们都用这种方式。我们的驱动开发篇将以本章使用的U-Boot源码、内核源码等进行开发工作!
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-5-29 06:58

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表