【正点原子FPGA连载】第十三章Linux内核移植 摘自【正点原子】DFZU2EG

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

1实验平台正点原子MPSoC开发板
2平台购买地址https://detail.tmall.com/item.htm?id=692450874670
3全套实验源码+手册+视频下载地址 http://www.openedv.com/thread-340252-1-1.html

第十三章Linux内核移植

前面章节我们简单了解了一下Linux内核顶层Makefile和Linux内核的启动流程本章我们就来学习一下如何将Xilinx官方提供的Linux内核移植到正点原子的MPSoc开发板上。需要说明的是当我们使用Petalinux工具的时候是不需要移植内核的因为Petalinux工具可以根据硬件描述文件xsa使能相应配置。本章讲解内核移植更准确的说是内核适配是为了了解一般情况下不使用Petalinux的内核移植过程。通过本章的学习我们将掌握如何将半导体厂商提供的Linux BSP包移植到我们自己的平台上。

13.1Linux内核获取
关于Linux的起源以及发展历史网上相关的介绍太多了这里不作过多介绍。Linux由Linux基金会管理与发布Linux官网为https://www.kernel.org所以你想获取最新的Linux版本就可以在这个网站上下载网站界面如下图所示
在这里插入图片描述

图 13.1.1 linux官网
从上图可以看出最新的稳定版Linux已经到了5.17.9大家没必要追新因为4.x版本的Linux和5.x版本没有本质上的区别5.x更多的是加入了一些新的平台、新的外设驱动而已。
Xilinx会从https://www.kernel.org下载某个版本的Linux内核然后将其移植到自己的芯片平台上测试成功以后就会将其开放给Xilinx的芯片平台开发者。开发者下载Xilinx提供的Linux内核然后将其移植到自己的产品上。后面的移植我们使用Xilinx提供的Linux源码Xilinx提供的Linux内核源码发布在https://github.com/Xilinx/linux-xlnx可以clone或下载注意要与Petalinux版本一致否则会出现一些问题我们使用的是2019.2版本的Petalinux所以选择的linux内核源码要带2019.2Tags带2019.2。不过我们不从上面的github网站下载因为在6.3.5节配置Linux内核时Petalinux工具就已经生成了linux内核源码如下图所示所以没有必要从github网站下载。
在这里插入图片描述

图 13.1.2 Xilinx linux内核源码
后面的linux内核移植和驱动开发都需要使用该源码为了方便访问和备份版本管理
我们将Petalinux生成的linux内核源码拷贝到12.1.1节建立的git.d文件夹下如下图所示
在这里插入图片描述

图 13.1.3拷贝linux内核源码到git.d目录
13.2Petalinux使用外部linux内核源码
上一节我们将Petalinux生成的内核源码移动到~/git.d/linux-xlnx目录绝对路径/home/shang/git.d/linux-xlnx以后我们在该内核源码上移植修改、添加驱动等Petalinux工程都无法使用该内核源码了如何让Petalinux能访问使用呢
方法如下

  1. 进入到Petalinux工程目录下设置好Petalinux工作环境后输入“petalinux-config”命令配置Petalinux工程。
    设置Linux Components Selection —>linux-kernel (linux-xlnx) —>为“ext-local-src”如下图所示
    在这里插入图片描述

图 13.2.1配置linux-kernel
该配置项将linux来源配置为外部的本地源。设置好后按回车键返回。设置External linux-kernel local source settings —> External linux-kernel local source path (NEW)为“/home/shang/git.d/linux-xlnx”也就是当前内核源码存放的目录结果如下图所示
在这里插入图片描述

图 13.2.2配置External linux-kernel local source path
保存配置并退出现在该Petalinux工程就可以访问和使用/home/ shang /git.d/linux-xlnx中的内核源码了。
需要注意的一点是在Petalinux工程配置linux内核和编译时需要先清理/home/ shang /git.d/linux-xlnx中的内核命令 make distclean否则配置和编译会报错12.2节外部uboot源码也要清理。
13.3Linux内核编译初次编译
我们在13.1小节中将Petalinux生成的linux内核源码放到了git.d文件夹下。现在进入到该内核源码目录处查看内核目录结构命令如下
cd ~/git.d/linux-xlnx/
ls
可以看到Linux源码根目录如下图所示
在这里插入图片描述

图 13.3.1 Linux内核源码根目录
其中oe-logs和oe-workdir是Petalinux工具生成的链接目录不是linux内核的源码目录。
现在我们讲解一下如何编译出对应的Linux镜像文件。新建名为“zynqmp.sh”的shell脚本然后在这个shell脚本里面输入如下所示内容
示例代码 zynqmp.sh文件内容
#!/bin/sh
make distclean
make xilinx_zynqmp_defconfig
unset PKG_CONFIG_PATH
make menuconfig
make -j8
第2行执行“make distclean”清理工程所以zynqmp.sh每次都会清理一下工程。如果通过图形界面配置了Linux但是还没保存新的配置文件那么就要慎重使用zynqmp.sh编译脚本了因为它会把你的配置信息都删除掉。
第3行执行“make xxx_defconfig”配置工程。该配置文件在/home/shang/git.d/linux-xlnx/arch/arm64/configs路径下。
第4行执行“unset PKG_CONFIG_PATH”取消环境变量PKG_CONFIG_PATH。打开图形配置界面需要先取消该环境变量否则有问题。
第5行执行“make menuconfig”打开图形配置界面对Linux进行配置如果不想每次编译都打开图形配置界面的话可以将这一行删除掉。
第6行执行“make”编译Linux源码。如果读者ubuntu虚拟机使用的是多核处理器可以在make命令后加参数“-jn”来加快编译其中n表示处理器核数笔者虚拟机是8核所以这里参数为“-j8”。
可以看出Linux的编译过程基本和uboot一样都要先执行“make xxx_defconfig”来配置一下然后再执行“make”进行编译。如果需要使用图形界面配置的话就执行“make menuconfig”。
使用chmod给予zynqmp.sh可执行权限然后运行此shell脚本命令如下
chmod 777 zynqmp.sh
./zynqmp.sh
编译的时候会弹出Linux图形配置界面如下图所示
在这里插入图片描述

图 13.3.2 Linux图形配置界面
Linux的图行界面配置和uboot是一样的这里我们不需要做任何的配置直接按两下ESC键退出退出图形界面以后会自动开始编译Linux。等待编译完成完成以后如下图所示
在这里插入图片描述

图 13.3.3 Linux编译完成
编译完成以后就会在arch/arm64/boot这个目录下生成一个叫做Image的文件如下图所示
在这里插入图片描述

图 13.3.4 Linux内核镜像文件
Image就是我们要用的Linux内核镜像文件。Image.gz文件是Image文件的压缩文件可以用uboot的bootz命令启动不过Xilinx不用该文件。
另外也会在arch/arm64/boot/dts/xilinx下生成很多.dtb文件这些.dtb就是设备树文件比如zynqmp-zcu102-rev1.0.dtb文件就是xilinx zcu102开发板对应的设备树文件。
13.4Linux内核源码工程目录分析
我们在13.1节获取的linux内核源码目录如下图所示
在这里插入图片描述

图 13.4.1未编译的Linux内核源码目录
上图是petalinux生成的未编译的Linux源码目录文件我们在分析Linux之前一定要先在Ubuntu中编译一下Linux因为编译过程会生成一些文件而生成的这些恰恰是分析Linux不可或缺的文件。编译后的Linux目录如下图所示
在这里插入图片描述

图 13.4.2编译后的Linux目录
上图中重要的文件夹或文件的含义如下表所示
表 13.4.1 Linux目录
类型 名字 描述 备注
文件夹 arch 架构相关目录。 Linux自带
block 块设备相关目录。
crypto 加密相关目录。
Documentation 文档相关目录。
drivers 驱动相关目录。
firmeare 固件相关目录。
fs 文件系统相关目录。
include 头文件相关目录。
init 初始化相关目录。
ipc 进程间通信相关目录。
kernel 内核相关目录。
lib 库相关目录。
mm 内存管理相关目录。
net 网络相关目录。
samples 例程相关目录。
scripts 脚本相关目录。
security 安全相关目录。
sound 音频处理相关目录。
tools 工具相关目录。
usr 与initramfs相关的目录用于生成initramfs。
virt 提供虚拟机技术(KVM)。
文件 .config Linux最终使用的配置文件。 编译生成的文件。
.gitignore git工具相关文件。 Linux自带
.mailmap 邮件列表。
.missing-syscalls.d 。 编译生成的文件
.tmp_xx 这是一系列的文件作用目前笔者还不是很清楚。 编译生成的文件
.version 好像和版本有关。
.vmlinux.cmd cmd文件用于连接生成vmlinux。
COPYING 版权声明。 Linux自带
CREDITS Linux贡献者。
Kbuild Makefile会读取此文件。
Kconfig 图形化配置界面的配置文件。。
MAINTAINERS 维护者名单。
Makefile Linux顶层Makefile
Module.xx
modules.xx 一系列文件和模块有关。 编译生成的文件
zynqmp.sh 正点原子提供的Linux编译脚本。 正点原子提供
README Linux描述文件。 Linux自带
System.map 符号表。 编译生成的文件
vmlinux 编译出来的、未压缩的ELF格式Linux文件
vmlinux.o 编译出来的vmlinux.o文件。
上表中的很多文件夹和文件我们都不需要去关心我们要关注的文件夹或文件如下
1、arch目录
这个目录是和架构有关的目录比如arm、arm64、avr32、x86等等架构。每种架构都对应一个目录在这些目录中又有很多子目录比如boot、common、configs等等以arch/arm64为例其子目录如下图所示
在这里插入图片描述

图 13.4.3 arch/arm子目录
上图是arch/arm64的子目录这些子目录用于控制系统引导、系统调用、动态调频、主频设置等。arch/arm64/configs目录是不同平台的默认配置文件xxx_defconfig如下图所示
在这里插入图片描述

图 13.4.4配置文件
可以看到总共有3个defconfig文件其中两个以xilinx开头的都是用于Xilinx厂商soc系列的配置文件。xilinx_zynqmp_defconfig属于Zynq UltraScale+ MPSoC系列平台的通用默认配置文件xilinx_versal_defconfig应该属于Versal系列平台的通用默认配置文件。执行“make xilinx_zynqmp_defconfig”即可完成配置。
arch/arm64/boot/dts/xilinx/目录里面是对应开发平台的设备树文件xilinx zcu102开发板对应的设备树文件如下图所示
在这里插入图片描述

图 13.4.5正点原子DFZU2EG_4EV MPSoC开发板对应的设备树
其中zynqmp-zcu102-rev1.0.dts为zcu102开发板1.0版本的设备树文件编译后的设备树镜像文件为zynqmp-zcu102-rev1.0.dtb。
arch/arm64/boot目录中有编译出来的Image镜像文件而Image就是我们要用的linux镜像文件。
arch/arm/mach-xxx目录分别为相应平台的驱动和初始化文件比如mach-zynq目录里面就是ZYNQ 系列CPU的驱动和初始化文件。
2、block目录
block是Linux下块设备目录像SD卡、eMMC、NAND、硬盘等存储设备就属于块设备block目录中存放着管理块设备的相关文件。
3、crypto目录
crypto目录里面存放着加密文件比如常见的crc、crc32、md4、md5、hash等加密算法。
4、Documentation目录
此目录里面存放着Linux相关的文档如果要想了解Linux某个功能模块或驱动架构的功能就可以在Documentation目录中查找有没有对应的文档。
5、drivers目录
设备驱动程序目录此目录根据驱动类型的不同分门别类进行整理比如drivers/i2c就是I2C相关驱动目录drivers/gpio就是GPIO相关的驱动目录这是我们学习的重点。
6、firmware目录
此目录用于存放固件。
7、fs目录
此目录存放文件系统相关代码比如fs/ext2、fs/ext4、fs/f2fs等分别是ext2、ext4和f2fs等文件系统。
8、include目录
头文件目录。与系统相关的头文件被放置在内核 include/linux子目录下。
9、init目录
此目录存放Linux内核启动的时候初始化代码。
10、ipc目录
IPC为进程间通信ipc目录是进程间通信的具体实现代码。
11、kernel目录
Linux内核代码。与平台相关的部分代码放在arch//kernel目录下其中代表各种处理器平台
12、lib目录
lib是库的意思lib目录都是一些公用的库函数。
13、mm目录
此目录存放与平台无关的内存管理代码与平台相关的内存管理代码放在arch/*/mm目录下。
14、net目录
此目录存放网络相关代码。
15、samples目录
此目录存放一些示例代码文件。
16、scripts目录
脚本目录Linux编译的时候会用到很多脚本文件这些脚本文件就保存在此目录中。
17、security目录
此目录存放安全相关的文件。
18、sound目录
此目录存放音频相关驱动文件音频驱动文件并没有存放到drivers目录中而是单独的目录。
19、tools目录
此目录存放一些编译的时候使用到的工具。
20、usr目录
此目录存放与initramfs有关的代码。
21、virt目录
此目录存放虚拟机相关文件。
22、.config文件
根uboot一样.config保存着Linux最终的配置信息编译Linux的时候会读取此文件中的配置信息。最终根据配置信息来选择编译Linux哪些模块哪些功能。
23、Kbuild文件
有些Makefile会读取此文件。
24、Kconfig文件
图形化配置界面的配置文件。
25、Makefile文件
Linux顶层Makefile文件建议好好阅读一下此文件。
26、README文件
此文件详细讲解了如何编译Linux源码以及Linux源码的目录信息建议仔细阅读一下此文件。
13.5移植准备工作
从本小节开始我们对官方linux内核进行移植使其能在正点原子MPSoC开发板上启动并正常工作。
进入到13.1节创建的linux内核源码目录~/git.d/linux-xlnx输入如下命令清理linux内核源码
make distclean
初次移植不知道该添加哪些文件的时候最好的方法就是看看别的开发板是怎么添加的我们以Xilinx的ZCU102开发板为例看看内核源码中有哪些文件或文件夹与ZCU102开发板有关。
输入如下命令根据文件名称或文件夹名称查找与ZCU102开发板有关的文件或文件夹
find . -name “zcu102
结果如下图所示
在这里插入图片描述

图 13.5.1查找相关的文件或文件夹
然后搜索内容中带有zcu102字样的文件命令如下
grep -irn --exclude-dir=.git “zcu102”
结果如下图所示
在这里插入图片描述

图 13.5.2带zcu102字样的文件
由于Documentation文件夹是说明文档不编译进内核剩下的就是arch/arm64/boot/dts/xilinx目录下的Makefile和设备树dts文件了。
下面开始移植。
13.6移植步骤
13.6.1添加开发板默认配置文件
编译内核之前需要先配置内核配置内核用的文件为开发板的默认内核配置文件。开发板的默认内核配置文件在内核源码的arch//configs目录下ARCH对应开发板使用的芯片架构对于我们使用的MPSoC开发板而言ARCH为arm64。在添加之前先看下arch/arm64/configs目录下arm64架构不同平台的默认配置文件如下图所示
在这里插入图片描述

图 13.6.1默认配置文件
可以看到总共有3个defconfig文件其中两个以xilinx开头的都是用于Xilinx厂商soc系列的配置文件。前面说过xilinx_zynqmp_defconfig是用于Zynq UltraScale+ MPSoc系列平台的通用默认配置文件为了保持一致我们依旧使用xilinx_zynqmp_defconfig作为开发板的默认配置文件。不过呢我们还是可以修改xilinx_zynqmp_defconfig的。要想修改配置文件首先得知道配置项的含义如果直接打开xilinx_zynqmp_defconfig文件来修改的话移除配置项到还可以添加的话就无从谈起了所以我们得在图形配置界面修改配置项。此处我们就不修改了保持默认的配置即可。
可以使用如下命令来配置正点原子MPSoC开发板对应的linux内核
make xilinx_zynqmp_defconfig
13.6.2添加开发板对应的设备树文件
Linux支持设备树每个开发板都有对应的设备树文件。Xilinx的Zynq UltraScale+ MPSoc系列芯片的所有设备树文件都存放在arch/arm64/boot/dts/xilinx目录下如下图所示
在这里插入图片描述

图 13.6.2 Zynq UltraScale+ MPSoc系列芯片的所有设备树文件
其中zynqmp.dtsi、zynqmp-clk.dtsi和zynqmp-clk-ccf.dtsi设备树文件是Zynq UltraScale+ MPSoc系列芯片通用的基础设备树文件我们在12.4.4小节有介绍。Makefile用于设置哪些设备树文件将被编译其内容如下图所示
在这里插入图片描述

图 13.6.3默认编译的设备树
当编译linux内核源码时这些设备树文件也会默认编译如果不想编译其中的某些设备树文件可以删除或注释相应行。
不同的开发板有不同的设备树文件我们自己的开发板当然得用我们自己的设备树文件。设备树文件从哪来可以参考其他开发板的设备树文件然后与自己的开发板对比手动编写不过这样做工作量太大没什么意义除非迫不得已否则不推荐这种方法。最简便直接的方法是用Petalinux工具生成的设备树文件。Petalinux工具会根据我们提供的开发板xsa文件自动生成相应的设备树文件生成的设备树文件在Petalinux工程第六章Petalinux设计流程实战章节建立的Petalinux工程的components/plnx_workspace/device-tree/device-tree目录下如下图所示
在这里插入图片描述

图 13.6.4 Petalinux生成的设备树文件
后缀为dtsi和dts的都是设备树文件这些设备树文件都是Petalinux根据xsa自动生成的。关于这些设备树文件的含义在前面移植uboot的时候已经讲解过了。
要想在linux内核源码中添加开发板的设备树文件可以将system-top.dts文件及其依赖文件添加到linux内核源码中。打开system-top.dts文件其内容如下图所示
在这里插入图片描述

图 13.6.5 system-top.dts文件的内容
可以看到总共include五个设备树文件其中zynqmp.dtsi和zynqmp-clk-ccf.dtsi是通用文件不用添加剩下的pcw.dtsi、pl.dtsi和system-user.dtsi需要添加。
进入到第六章创建的Petalinux工程的components/plnx_workspace/device-tree/device-tree目录下然后输入如下命令将设备树文件复制到linux内核源码相应目录
cp pcw.dtsi pl.dtsi ~/git.d/linux-xlnx/arch/arm64/boot/dts/xilinx/
cp system-top.dts ~/git.d/linux-xlnx/arch/arm64/boot/dts/xilinx/
其中system-top.dts设备树文件是我们开发板的默认设备树文件。
然后切换到project-spec/meta-user/recipes-bsp/device-tree/files/目录下将设备树文件system-user.dtsi复制到linux内核源码相应目录
cp system-user.dtsi ~/git.d/linux-xlnx/arch/arm64/boot/dts/xilinx/
system-user.dtsi是用户设备树文件。为了方便管理我们一般配置这个设备树文件添加外设。
复制结果如下图所示
在这里插入图片描述

图 13.6.6向内核源码中添加设备树
添加完开发板的设备树文件后还需要进行相应的修改才可以使用。
进入到linux内核源码的arch/arm64/boot/dts/xilinx/目录下编辑system-user.dtsi文件修改前共有119行内容如下

1 /include/ "system-conf.dtsi"
  2 #include <dt-bindings/gpio/gpio.h>
  3 #include <dt-bindings/input/input.h>
  4 
  5 / {
  6     model = "Alientek Zynq MpSoc Development Board";
  7 
  8     leds {
  9         compatible = "gpio-leds";
 10 
 11         gpio-led0 {
 12             label = "ps_led1";
 13             gpios = <&gpio 38 GPIO_ACTIVE_HIGH>;
 14             linux,default-trigger = "timer";
 15         };
 16 
 17         gpio-led1 {
 18             label = "ps_led2";
 19             gpios = <&gpio 39 GPIO_ACTIVE_HIGH>;
 20             default-state = "on";
 21         };
 22 
 23         gpio-led2 {
 24             label = "pl_led1";
 25             gpios = <&axi_gpio_0 0 0 GPIO_ACTIVE_HIGH>;
 26             linux,default-trigger = "timer";
 27         };
 28 
 29         gpio-led3 {
 30             label = "pl_led2";
 31             gpios = <&axi_gpio_0 1 0 GPIO_ACTIVE_HIGH>;
 32             default-state = "on";
 33         };
 34     };
 35 
 36     keys {
 37         compatible = "gpio-keys";
   …
   …
   …
 97 &sdhci1 {
 98 disable-wp;
 99 no-1-8-v;
100 };
101 
102 &i2c1 {
103     clock-frequency = <400000>;
104 
105     eeprom@50 {
106         compatible = "24c64";
107         reg = <0x50>;
108         pagesize = <32>;
109     };
110 };
111 
112 &dwc3_0 {
113     dr_mode = "host";
114     maximum-speed = "super-speed";
115 };
116 
117 &usb0 {
118     dr_mode = "host";
119 };
修改后的内容如下
1 #include <dt-bindings/gpio/gpio.h>
  2 #include <dt-bindings/input/input.h>
  3 
  4 / {
  5     model = "Alientek Zynq MpSoc Development Board";
  6     compatible = "xlnx,zynqmp-atk", "xlnx,zynqmp";
  7 };
  8 
  9 &gem3 {
 10     phy-handle = <&ethernet_phy>;
 11     local-mac-address = [00 0a 35 00 1e 53];
 12 
 13     ethernet_phy: ethernet-phy@7 {
 14         reg = <0x7>;
 15     };
 16 };
 17 
 18 &gem0 {
 19     psu_ethernet_0_mdio: mdio {
 20         #address-cells = <1>;
 21         #size-cells = <0>;
 22         phy1:phy@4 {
 23             reg = <0x4>;   /* YT8521 phy address */
 24         };
 25         gmii_to_rgmii_0: gmii_to_rgmii_0@0 {
 26                         compatible = "xlnx,gmii-to-rgmii-1.0";
 27                         phy-handle = <&phy1>;
 28                         reg = <0>;
 29         };
 30     };
 31 };
 32 
 33 &sdhci0 {
 34 mmc-hs200-1_8v;
 35 bus-width = <0x8>;
 36 non-removable;
 37 };
38 
 39 &sdhci1 {
 40 disable-wp;
 41 no-1-8-v;
 42 };
 43 
 44 &dwc3_0 {
 45     dr_mode = "host";
 46     maximum-speed = "super-speed";
 47 };
 48 
 49 &usb0 {
 50     dr_mode = "host";
 51 };

删除了原文件第一行的“/include/“system-conf.dtsi””在第6行添加了“compatible = “xlnx,zynqmp-atk”, “xlnx,zynqmp”;”。
删除第8行至第64行根节点下leds和keys两个节点这两个节点在后面驱动章节中用到的时候再添加。
删除第102行至第110行iic节点。
gem3是ps端网口gem0是pl端网口sdhci0和sdhci1分别是emmc和sd卡接口dwc3_0和usb0分别是usb3.0接口和usb2.0接口。上面这6个节点我们保留。
修改完设备树后还需要在arch/arm64/boot/dts/xilinx目录中的Makefile文件中添加开发板的设备树文件。添加到Makefile中的设备树文件在编译内核的时候会自动编译。
打开arch/arm64/boot/dts/xilinx/Makefile文件添加行“dtb-$(CONFIG_ARCH_ZYNQMP) += system-top.dtb”如下图所示
在这里插入图片描述

图 13.6.7添加设备树文件
可以看到像zc1232、zc1254、zc1751、zcu100、zcu102、zcu104、zcu106、zcu113、zcu1275、zcu1285这些设备树我们没有用到可以直接删除删除后的Makefile内容如下图所示
在这里插入图片描述

图 13.6.8修改后的Makefile
这样编译linux内核的时候就可以从system-top.dts编译成system-top.dtb文件了。到此为止MPSoC开发板就已经添加到linux内核源码中了。
在linux内核源码目录中输入“git status”命令可以看到移植过程中我们修改了哪些文件如下图所示
在这里插入图片描述

图 13.6.9移植过程中修改的文件
如果后面测试的时候只修改设备树文件的话可只重新编译设备树在linux内核源码根目录下输入如下命令编译设备树
make dtbs
命令“make dtbs”只编译设备树文件也就是将.dts编译为.dtb编译完成以后就可以使用新的设备树文件。
13.6.3Linux内核编译与测试
经过前两个小节我们已经在Linux内核里面添加了正点原子MPSoC开发板的配置接下接进行编译测试。在终端中输入如下命令配置编译linux内核源码
make distclean
make xilinx_zynqmp_defconfig
make -j8
第1行清理工程。
第2行使用默认配置文件xilinx_zynqmp_defconfig来配置Linux内核。
第3行编译Linux。参数“-j8”表示处理器使用8核来运行编译读者可根据自己电脑配置自行设置此参数。
编译完成以后就会在目录arch/arm64/boot下生成Image镜像文件Image.gz是Image镜像文件的压缩文件在arch/arm64/boot/dts/xilinx目录下生成system-top.dtb文件如图 13.6.10和图 13.6.11所示。
在这里插入图片描述

图 13.6.10生成Image镜像文件
在这里插入图片描述

图 13.6.11生成system-top.dtb文件
将/tftpboot目录下原有的Image镜像文件删除重新复制编译生成的Image文件和system-top.dtb文件到/tftpboot目录下如下图所示
在这里插入图片描述

图 13.6.12复制镜像和设备树文件
拷贝完成以后就可以测试了。将开发板启动模式调为JTAG模式开发板连接下载器电脑连接开发板的usb_uart接口用网线连接PS端网口和电脑最后连接开发板电源。
开发板硬件连接好后打开虚拟机按照图 12.3.4所示将jtag下载器连接到虚拟机内进入到工程ALIENTEK-ZYNQ路径下输入“sptl”命令设置环境变量然后使用“petalinux-boot --jtag --fpga --u-boot”命令下载并启动uboot。同时观察串口终端软件上的打印信息注意在倒计时结束前按回车键进入uboot模式如下图所示
在这里插入图片描述

图 13.6.13进入uboot模式
进入uboot模式后输入如下命令设置网络环境变量
setenv ipaddr 192.168.2.22
setenv ethaddr 00:0a:35:00:1e:53
setenv gatewayip 192.168.2.1
setenv netmask 255.255.255.0
setenv serverip 192.168.2.21
然后输入如下命令将Image和system-top.dtb下载到开发板并启动
tftpboot 0x200000 Image
tftpboot 0x100000 system-top.dtb
booti 0x200000 - 0x100000
结果如下图所示
在这里插入图片描述

图 13.6.14 uboot模式下启动linux内核
出现上图所示内容就表示Linux内核启动成功说明我们已经在Xilinx提供的Linux内核源码中成功添加了正点原子MPSoC开发板。
13.7根文件系统缺失错误
在上一小节打印信息的最后出现如下图所示的信息
在这里插入图片描述

图 13.7.1根文件系统缺失错误
在上图中最后会有下面这一行
end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
也就是提示内核崩溃因为根文件系统目录不存在VFS(虚拟文件系统)不能挂载根文件系统。即使根文件系统目录存在如果根文件系统目录里面是空的依旧会提示内核崩溃。这个就是根文件系统缺失导致的内核崩溃。但是内核是启动了的只是根文件系统不存在而已。
13.8image.ub的来源
从前面章节中我们知道编译linux内核后得到的是Image镜像文件和dtb设备树文件而我们在前面uboot移植章节使用uboot启动linux的时候使用的是image.ub镜像文件那么image.ub文件是怎么产生的呢它和Image文件、设备树文件有什么关系是否一定需要image.ub文件才能启动内核呢
在12.6节uboot启动Linux测试中我们使用了image.ub文件在13.6.3节Linux内核编译与测试中我们使用Image和设备树文件启动linux结果是都可以正常启动linux说明启动linux内核并不一定需要image.ub文件而且从中我们也可以得出一个信息image.ub文件一定是包含Image文件和设备树文件信息的。接下来我们来探索下image.ub的来源。
既然image.ub文件包含Image文件和设备树文件信息那么image.ub文件一定是由某个工具打包制作而得到的常用的镜像制作工具是mkimage。mkimage工具位于u-boot-xlnx/tools目录下初次使用前要把mkimage文件复制到系统可执行命令文件夹内也就是/usr/bin/如下图所示
在这里插入图片描述

图 13.8.1复制mkimage文件
我们先用mkimage来分析image.ub文件命令mkimage -l images/linux/image.ub结果如图 13.8.2所示。从显示的内容来看image.ub确实是包括linux内核镜像和设备树的另外从“FIT description”的信息来看image.ub文件是U-Boot fitImage。现在我们根据“FIT description”的信息来搜索哪个文件包含该内容搜索结果如图 13.8.3所示。
在这里插入图片描述

图 13.8.2 分析image.ub文件
在这里插入图片描述

图 13.8.3 搜索结果
可见包含该内容的文件不少。大致的看了一下以上文件以“.its”结尾的文件是由run.do_assemble_fitimage_initramfs*文件生成的。我们打开build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.4+git999-r0/linux-xlnx-5.4+git999/fit-image.its文件内容如下

/dts-v1/;

/ {
        description = "U-Boot fitImage for PetaLinux/5.4+git999/zynqmp-generic";
        #address-cells = <1>;

        images {
                kernel@1 {
                        description = "Linux kernel";
                        data = /incbin/("linux.bin");
                        type = "kernel";
                        arch = "arm64";
                        os = "linux";
                        compression = "gzip";
                        load = <0x80000>;
                        entry = <0x80000>;
                        hash@1 {
                                algo = "sha256";
                        };
                };
                fdt@system-top.dtb {
                        description = "Flattened Device Tree blob";
                        data = /incbin/("/home/cx/workspace/petalinux/ALIENTEK-ZYNQ/build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.4+git999-r0/recipe-sysroot/boot/devicetree/system-top.dtb");
                        type = "flat_dt";
                        arch = "arm64";
                        compression = "none";
                        
                        hash@1 {
                                algo = "sha256";
                        };
                };
    };

        configurations {
                default = "conf@system-top.dtb";
                conf@system-top.dtb {
            description = "1 Linux kernel, FDT blob";
            kernel = "kernel@1";
            fdt = "fdt@system-top.dtb";
            
            
                        hash@1 {
                                algo = "sha256";
                        };
                };
    };
};

可以看出该文件的内容与我们使用“mkimage -l images/linux/image.ub”命令得到的信息基本一致。另外从该文件内容可以看到镜像的kernel来源于linux.bin而设备树来源于工程目录下的build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.4+git999-r0/recipe-sysroot/boot/devicetree/system-top.dtb。从build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.4+git999-r0/temp/run.do_assemble_fitimage.22866是由vmlinux生成的。其实我们也可以用Image来代替linux.bin下面我们使用Image和zynqmp-atk.dtb生成image.ub。
将build/tmp/work/zynqmp_generic-xilinx-linux/linux-xlnx/5.4+git999-r0/linux-xlnx-5.4+git999/fit-image.its文件复制到linux内核源码根目录下也就是“~/git.d/linux-xlnx/”目录下然后修改相应的内容修改后的fit-image.its文件内容如下

/dts-v1/;

/ {
        description = "U-Boot fitImage for Alientek ZYNQ MPSoc";
        #address-cells = <1>;

        images {
                kernel-1 {
                        description = "Linux kernel";
                        data = /incbin/("arch/arm64/boot/Image");
                        type = "kernel";
                        arch = "arm64";
                        os = "linux";
                        compression = "none";
                        load = <0x80000>;
                        entry = <0x80000>;
                        hash-1 {
                                algo = "sha256";
                        };
                };
                fdt-1 {
                        description = "Flattened Device Tree blob";
                        data = /incbin/("arch/arm64/boot/dts/xilinx/system-top.dtb");
                        type = "flat_dt";
                        arch = "arm64";
                        compression = "none";
                        
                        hash-1 {
                                algo = "sha256";
                        };
                };
        };

        configurations {
                default = "config-1";
                
                config-1 {
                    description = "1 Linux kernel, FDT blob";
                    kernel = "kernel-1";
                    fdt = "fdt-1";
                };
        };
};

保存文件内容后在终端中输入命令“mkimage -f fit-image.its image.ub”如下图所示
在这里插入图片描述

图 13.8.4 生成image.ub文件
在内核源码根目录下可以找到生成的image.ub文件如下图所示
在这里插入图片描述

图 13.8.5 生成的image.ub文件
如何验证该文件确实可行呢。如果是通过SD卡启动开发板可以将生成的image.ub文件复制到SD卡中如果是通过网络启动开发板可以将其复制到/tftboot目录下启动开发板测试。经测试是可以启动内核的如何启动可以参考错误!未找到引用源。节启动结果如下图所示
在这里插入图片描述

图 13.8.6 验证结果
至此我们终于知道了image.ub是怎么来的怎么生成的了。另外image.ub既然是U-Boot fitImage那U-Boot fitImage又是什么呢限于篇幅就不再介绍了可自行上网搜索笔者找到一篇不错的介绍推荐下链接如下
http://www.wowotech.net/u-boot/fit_image_overview.html
从该链接可知U-Boot fitImage主要来源于Unify Kernel的思想其思想如下
“在编译linux kernel的时候不必特意的指定具体的架构和SOC只需要告诉kernel本次编译需要支持哪些板级的platform即可最终将会生成一个Kernel image以及多个和具体的板子哪个架构、哪个SOC、哪个版型有关的FDT imagedtb文件。
bootloader在启动的时候根据硬件环境加载不同的dtb文件即可使linux kernel运行在不同的硬件平台上从而达到unify kernel的目标。”
关于fit更多的介绍和使用方法请参考本章的扩展阅读部分。
在这里插入图片描述

13.9CPU调频策略
1、设置MPSoC开发板的CPU调频策略
我们知道主频越高功耗也越高。为了节省CPU的功耗和减少发热我们有必要根据当前CPU的负载状态动态地提供刚好足够的主频给CPU。调频或称变频技术应运而生。变频技术作为电源管理技术以节能为目的加入linux内核。我们可以通过配置内核来选择不同的调频策略。
我们来看一下如何通过图形化界面配置Linux内核的CPU调频策略输入“make menuconfig”打开Linux内核的图形化配置界面如下图所示
在这里插入图片描述

图 13.9.1 Linux内核图形化配置界面
进入如下路径
CPU Power Management
-> CPU Frequency scaling
-> Default CPUFreq governor
打开默认调频策略选择界面如下图所示

图 13.9.2默认调频策略选择
可以看到Linux内核一共有6种调频策略
①Performance最高性能直接用最高频率不考虑耗电。
②Powersave省电模式通常以最低频率运行系统性能会受影响一般不会用这个。
③Userspace可以在用户空间手动调节频率可以看到这是默认的配置。
④Ondemand定时检查负载然后根据负载来调节频率。负载低的时候降低CPU频率以省电负载高的时候提高CPU频率增加性能。
⑤conservative保守模式类似于ondemand但调整相对较缓。
⑥schedutil4.7版本内核新增加的一种调度策略可以直接使用调度程序提供的信息做出调整cpu频率的决策也可以调用cpufreq驱动程序更改频率以立即调整CPU的性能无需生成进程上下文或其他工作项。
我们可以根据实际需求选择合适的调频策略。
关于Linux内核的移植就讲解到这里简单总结一下移植步骤
①在Linux内核中查找可以参考的板子一般都是半导体厂商自己做的开发板。
②编译出参考板子对应的Image和.dtb文件。
③使用参考板子的Image文件和.dtb文件在我们所使用的板子上启动Linux内核看能否启动。
④如果能启动的话就万事大吉如果不能启动就需要调试Linux内核和修改设置树。不过一般都会参考半导体官方的开发板设计自己的硬件所以大部分情况下都会启动起来。启动Linux内核用到的外设不多一般就DRAM(Uboot都初始化好的)和串口。
⑤修改相应的驱动像USB、eMMC、SD卡等驱动官方的Linux内核都是已经提供好了基本不会出问题。重点是网络驱动因为Linux驱动开发一般都要通过网络调试代码所以一定要确保网络驱动工作正常。如果是处理器内部MAC+外部PHY这种网络方案的话一般网络驱动都很好处理因为在Linux内核中是有外部PHY通用驱动的。只要设置好复位引脚、PHY地址信息基本上都可以驱动起来。
⑥Linux内核启动以后需要根文件系统如果没有根文件系统的话肯定会崩溃所以确定Linux内核移植成功以后就要开始根文件系统的构建。

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: linux