OpenEdv-开源电子网

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

《DFZU2EG_4EV MPSoC开发板之嵌入式Linux 驱动开发指南》第十三章 Linux内核移植

[复制链接]

1070

主题

1081

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4443
金钱
4443
注册时间
2019-5-8
在线时间
1199 小时
发表于 2023-5-25 15:54:20 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-5-24 10:23 编辑

第十三章 Linux内核移植

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群:299746173

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

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

13.1 Linux内核获取
关于Linux的起源以及发展历史,网上相关的介绍太多了,这里不作过多介绍。Linux由Linux基金会管理与发布,Linux官网为https://www.kernel.org,所以你想获取最新的Linux版本就可以在这个网站上下载,网站界面如下图所示:                           
image001.png
图 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.2(Tags带2019.2)。不过我们不从上面的github网站下载,因为在6.3.5节配置Linux内核时,Petalinux工具就已经生成了linux内核源码,如下图所示,所以没有必要从github网站下载。
image003.png
图 13.1.2 Xilinxlinux内核源码

后面的linux内核移植和驱动开发都需要使用该源码,为了方便访问和备份(版本管理),

我们将Petalinux生成的linux内核源码拷贝到12.1.1节建立的git.d文件夹下,如下图所示:
image005.png
图 13.1.3拷贝linux内核源码到git.d目录

13.2 Petalinux使用外部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”,如下图所示:
image007.png
图 13.2.1配置linux-kernel

该配置项将linux来源配置为外部的本地源。设置好后按回车键返回。设置External linux-kernel local source settings ---> External linux-kernellocal source path (NEW)为“/home/shang/git.d/linux-xlnx”,也就是当前内核源码存放的目录,结果如下图所示:
image009.png
图 13.2.2配置External linux-kernel local sourcepath

保存配置并退出,现在该Petalinux工程就可以访问和使用/home/ shang /git.d/linux-xlnx中的内核源码了。

需要注意的一点是在Petalinux工程配置linux内核和编译时需要先清理/home/ shang /git.d/linux-xlnx中的内核(命令 make distclean),否则配置和编译会报错(12.2节外部uboot源码也要清理)。

13.3 Linux内核编译初次编译
我们在13.1小节中将Petalinux生成的linux内核源码放到了git.d文件夹下。现在进入到该内核源码目录处,查看内核目录结构,命令如下:
  1. cd ~/git.d/linux-xlnx/
  2. ls
复制代码
可以看到Linux源码根目录如下图所示:
image011.png
图 13.3.1 Linux内核源码根目录

其中oe-logs和oe-workdir是Petalinux工具生成的链接目录,不是linux内核的源码目录。

现在我们讲解一下如何编译出对应的Linux镜像文件。新建名为“zynqmp.sh”的shell脚本,然后在这个shell脚本里面输入如下所示内容:
  1. 示例代码 zynqmp.sh文件内容
  2.   #!/bin/sh
  3.   make distclean
  4.   make xilinx_zynqmp_defconfig
  5.   unset PKG_CONFIG_PATH
  6. make menuconfig
  7.   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脚本,命令如下:
  1. chmod 777 zynqmp.sh
  2. ./zynqmp.sh
复制代码
编译的时候会弹出Linux图形配置界面,如下图所示:
image013.png
图 13.3.2 Linux图形配置界面

Linux的图行界面配置和uboot是一样的,这里我们不需要做任何的配置,直接按两下ESC键退出,退出图形界面以后会自动开始编译Linux。等待编译完成,完成以后如下图所示:
image015.png
图 13.3.3 Linux编译完成

编译完成以后就会在arch/arm64/boot这个目录下生成一个叫做Image的文件,如下图所示:
image017.png
图 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.4 Linux内核源码工程目录分析
我们在13.1节获取的linux内核源码目录如下图所示:
image019.jpg
图 13.4.1未编译的Linux内核源码目录

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

image020.png
图 13.4.2编译后的Linux目录

上图中重要的文件夹或文件的含义如下表所示:
QQ截图20230524101852.png
QQ截图20230524101907.png
表 13.4.1 Linux目录

上表中的很多文件夹和文件我们都不需要去关心,我们要关注的文件夹或文件如下:

1、arch目录
这个目录是和架构有关的目录,比如arm、arm64、avr32、x86等等架构。每种架构都对应一个目录,在这些目录中又有很多子目录,比如boot、common、configs等等,以arch/arm64为例,其子目录如下图所示:
image022.png
图 13.4.3 arch/arm子目录

上图是arch/arm64的子目录,这些子目录用于控制系统引导、系统调用、动态调频、主频设置等。arch/arm64/configs目录是不同平台的默认配置文件:xxx_defconfig,如下图所示:
image024.png
图 13.4.4配置文件

可以看到,总共有3个defconfig文件,其中两个以xilinx开头的都是用于Xilinx厂商soc系列的配置文件。xilinx_zynqmp_defconfig属于ZynqUltraScale+ MPSoC系列平台的通用默认配置文件,xilinx_versal_defconfig应该属于Versal系列平台的通用默认配置文件。执行“make xilinx_zynqmp_defconfig”即可完成配置。

arch/arm64/boot/dts/xilinx/目录里面是对应开发平台的设备树文件,xilinx zcu102开发板对应的设备树文件如下图所示:
image026.png
图 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内核源码:
  1. make distclean
复制代码
初次移植不知道该添加哪些文件的时候,最好的方法就是看看别的开发板是怎么添加的,我们以Xilinx的ZCU102开发板为例,看看内核源码中有哪些文件或文件夹与ZCU102开发板有关。

输入如下命令,根据文件名称或文件夹名称,查找与ZCU102开发板有关的文件或文件夹:
  1. find . -name "*zcu102*"
复制代码
结果如下图所示:
image028.png
图 13.5.1查找相关的文件或文件夹

然后搜索内容中带有zcu102字样的文件,命令如下:
  1. grep -irn --exclude-dir=.git "zcu102"
复制代码
结果如下图所示:
image030.png
图 13.5.2带zcu102字样的文件

由于Documentation文件夹是说明文档,不编译进内核,剩下的就是arch/arm64/boot/dts/xilinx目录下的Makefile和设备树dts文件了。

下面开始移植。

13.6 移植步骤
13.6.1 添加开发板默认配置文件
编译内核之前需要先配置内核,配置内核用的文件为开发板的默认内核配置文件。开发板的默认内核配置文件在内核源码的arch/<ARCH>/configs目录下,ARCH对应开发板使用的芯片架构,对于我们使用的MPSoC开发板而言,ARCH为arm64。在添加之前先看下arch/arm64/configs目录下arm64架构不同平台的默认配置文件,如下图所示:
image032.png
图 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内核:
  1. make xilinx_zynqmp_defconfig
复制代码
13.6.2 添加开发板对应的设备树文件
Linux支持设备树,每个开发板都有对应的设备树文件。Xilinx的Zynq UltraScale+ MPSoc系列芯片的所有设备树文件都存放在arch/arm64/boot/dts/xilinx目录下,如下图所示:
image034.png
图 13.6.2 ZynqUltraScale+ MPSoc系列芯片的所有设备树文件

其中zynqmp.dtsi、zynqmp-clk.dtsi和zynqmp-clk-ccf.dtsi设备树文件是Zynq UltraScale+ MPSoc系列芯片通用的基础设备树文件,我们在12.4.4小节有介绍。Makefile用于设置哪些设备树文件将被编译,其内容如下图所示:
image036.png
图 13.6.3默认编译的设备树

当编译linux内核源码时,这些设备树文件也会默认编译,如果不想编译其中的某些设备树文件,可以删除或注释相应行。

不同的开发板有不同的设备树文件,我们自己的开发板当然得用我们自己的设备树文件。设备树文件从哪来,可以参考其他开发板的设备树文件,然后与自己的开发板对比,手动编写,不过这样做工作量太大,没什么意义,除非迫不得已,否则不推荐这种方法。最简便直接的方法是用Petalinux工具生成的设备树文件。Petalinux工具会根据我们提供的开发板xsa文件自动生成相应的设备树文件,生成的设备树文件在Petalinux工程(第六章Petalinux设计流程实战章节建立的Petalinux工程)的components/plnx_workspace/device-tree/device-tree目录下,如下图所示:
image038.png
图 13.6.4 Petalinux生成的设备树文件

后缀为dtsi和dts的都是设备树文件,这些设备树文件都是Petalinux根据xsa自动生成的。关于这些设备树文件的含义在前面移植uboot的时候已经讲解过了。

要想在linux内核源码中添加开发板的设备树文件,可以将system-top.dts文件及其依赖文件添加到linux内核源码中。打开system-top.dts文件,其内容如下图所示:
image040.png
图 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内核源码相应目录:
  1. cp pcw.dtsi pl.dtsi~/git.d/linux-xlnx/arch/arm64/boot/dts/xilinx/
  2. 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内核源码相应目录:
  1. cp system-user.dtsi ~/git.d/linux-xlnx/arch/arm64/boot/dts/xilinx/
复制代码
system-user.dtsi是用户设备树文件。为了方便管理,我们一般配置这个设备树文件添加外设。

复制结果如下图所示:
image042.png
图 13.6.6向内核源码中添加设备树

添加完开发板的设备树文件后,还需要进行相应的修改才可以使用。

进入到linux内核源码的arch/arm64/boot/dts/xilinx/目录下,编辑system-user.dtsi文件,修改前共有119行,内容如下:
  1. 1 /include/ "system-conf.dtsi"
  2.   2 #include<dt-bindings/gpio/gpio.h>
  3. 3 #include <dt-bindings/input/input.h>
  4.   4
  5.   5 / {
  6.   6     model = "Alientek Zynq MpSocDevelopment Board";
  7.   7
  8.   8     leds {
  9.   9         compatible = "gpio-leds";
  10. 10
  11. 11         gpio-led0 {
  12. 12             label = "ps_led1";
  13. 13             gpios = <&gpio 38GPIO_ACTIVE_HIGH>;
  14. 14             linux,default-trigger ="timer";
  15. 15         };
  16. 16
  17. 17         gpio-led1 {
  18. 18             label = "ps_led2";
  19. 19             gpios = <&gpio 39GPIO_ACTIVE_HIGH>;
  20. 20             default-state = "on";
  21. 21         };
  22. 22
  23. 23         gpio-led2 {
  24. 24             label = "pl_led1";
  25. 25            gpios = <&axi_gpio_0 0 0 GPIO_ACTIVE_HIGH>;
  26. 26             linux,default-trigger ="timer";
  27. 27         };
  28. 28
  29. 29         gpio-led3 {
  30. 30            label = "pl_led2";
  31. 31             gpios = <&axi_gpio_0 1 0GPIO_ACTIVE_HIGH>;
  32. 32             default-state = "on";
  33. 33         };
  34. 34     };
  35. 35
  36. 36     keys {
  37. 37         compatible = "gpio-keys";
  38.    …
  39.    …
  40.    …
  41. 97 &sdhci1 {
  42. 98 disable-wp;
  43. 99 no-1-8-v;
  44. 100 };
  45. 101
  46. 102 &i2c1 {
  47. 103     clock-frequency = <400000>;
  48. 104
  49. 105     eeprom@50 {
  50. 106         compatible = "24c64";
  51. 107         reg = <0x50>;
  52. 108         pagesize = <32>;
  53. 109     };
  54. 110 };
  55. 111
  56. 112 &dwc3_0 {
  57. 113     dr_mode = "host";
  58. 114     maximum-speed = "super-speed";
  59. 115 };
  60. 116
  61. 117 &usb0 {
  62. 118     dr_mode = "host";
  63. 119 };
复制代码
修改后的内容如下:
  1. 1 #include <dt-bindings/gpio/gpio.h>
  2.   2#include<dt-bindings/input/input.h>
  3.   3
  4.   4 / {
  5.   5     model = "Alientek Zynq MpSocDevelopment Board";
  6.   6     compatible = "xlnx,zynqmp-atk","xlnx,zynqmp";
  7.   7 };
  8.   8
  9.   9 &gem3 {
  10. 10     phy-handle = <eernet_phy>;
  11. 11     local-mac-address = [00 0a 35 00 1e 53];
  12. 12
  13. 13     ethernet_phy: ethernet-phy@7 {
  14. 14         reg = <0x7>;
  15. 15     };
  16. 16};
  17. 17
  18. 18 &gem0 {
  19. 19     psu_ethernet_0_mdio: mdio {
  20. 20         #address-cells = <1>;
  21. 21         #size-cells = <0>;
  22. 22         phy1:phy@4 {
  23. 23             reg = <0x4>;   /* YT8521 phy address */
  24. 24         };
  25. 25         gmii_to_rgmii_0: gmii_to_rgmii_0@0 {
  26. 26                        compatible ="xlnx,gmii-to-rgmii-1.0";
  27. 27                         phy-handle =<&phy1>;
  28. 28                         reg = <0>;
  29. 29         };
  30. 30     };
  31. 31 };
  32. 32
  33. 33 &sdhci0 {
  34. 34 mmc-hs200-1_8v;
  35. 35 bus-width =<0x8>;
  36. 36 non-removable;
  37. 37 };
  38. 38
  39. 39 &sdhci1 {
  40. 40 disable-wp;
  41. 41 no-1-8-v;
  42. 42 };
  43. 43
  44. 44 &dwc3_0 {
  45. 45     dr_mode ="host";
  46. 46     maximum-speed = "super-speed";
  47. 47 };
  48. 48
  49. 49 &usb0 {
  50. 50     dr_mode = "host";
  51. 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”,如下图所示:
image044.png
图 13.6.7添加设备树文件

可以看到像zc1232、zc1254、zc1751、zcu100、zcu102、zcu104、zcu106、zcu113、zcu1275、zcu1285这些设备树我们没有用到,可以直接删除,删除后的Makefile内容如下图所示:
image046.png
图 13.6.8修改后的Makefile

这样编译linux内核的时候就可以从system-top.dts编译成system-top.dtb文件了。到此为止,MPSoC开发板就已经添加到linux内核源码中了。

在linux内核源码目录中输入“git status”命令,可以看到移植过程中,我们修改了哪些文件,如下图所示:
image048.png
图 13.6.9移植过程中修改的文件

如果后面测试的时候只修改设备树文件的话可只重新编译设备树,在linux内核源码根目录下输入如下命令编译设备树:
  1. make dtbs
复制代码
命令“make dtbs”只编译设备树文件,也就是将.dts编译为.dtb,编译完成以后就可以使用新的设备树文件。

13.6.3 Linux内核编译与测试
经过前两个小节,我们已经在Linux内核里面添加了正点原子MPSoC开发板的配置,接下接进行编译测试。在终端中输入如下命令配置编译linux内核源码:
  1. make distclean
  2. make xilinx_zynqmp_defconfig
  3. 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所示。
image050.png
图13.6.10生成Image镜像文件

image052.png
图13.6.11生成system-top.dtb文件

将/tftpboot目录下原有的Image镜像文件删除,重新复制编译生成的Image文件和system-top.dtb文件到/tftpboot目录下,如下图所示:
image054.png
图 13.6.12复制镜像和设备树文件

拷贝完成以后就可以测试了。将开发板启动模式调为JTAG模式,开发板连接下载器,电脑连接开发板的usb_uart接口,用网线连接PS端网口和电脑,最后连接开发板电源。

开发板硬件连接好后,打开虚拟机,按照图 12.3.4所示将jtag下载器连接到虚拟机内,进入到工程ALIENTEK-ZYNQ路径下,输入“sptl”命令设置环境变量,然后使用“petalinux-boot--jtag --fpga --u-boot”命令下载并启动uboot。同时观察串口终端软件上的打印信息,注意在倒计时结束前按回车键进入uboot模式,如下图所示:
image056.png
图 13.6.13进入uboot模式

进入uboot模式后输入如下命令设置网络环境变量:
  1. setenv ipaddr 192.168.2.22
  2. setenv ethaddr 00:0a:35:00:1e:53
  3. setenv gatewayip 192.168.2.1
  4. setenv netmask 255.255.255.0
  5. setenv serverip 192.168.2.21
复制代码
然后输入如下命令将Image和system-top.dtb下载到开发板并启动:
  1. tftpboot 0x200000 Image
  2. tftpboot 0x100000 system-top.dtb
  3. booti 0x200000 - 0x100000
复制代码
结果如下图所示:
image058.png
图 13.6.14 uboot模式下启动linux内核

出现上图所示内容就表示Linux内核启动成功,说明我们已经在Xilinx提供的Linux内核源码中成功添加了正点原子MPSoC开发板。

13.7 根文件系统缺失错误
在上一小节打印信息的最后,出现如下图所示的信息:
image060.png
图 13.7.1根文件系统缺失错误

在上图中最后会有下面这一行:
  1. end Kernel panic - notsyncing: VFS: Unable to mount root fs on unknown-block(0,0)
复制代码
也就是提示内核崩溃,因为根文件系统目录不存在,VFS(虚拟文件系统)不能挂载根文件系统。即使根文件系统目录存在,如果根文件系统目录里面是空的依旧会提示内核崩溃。这个就是根文件系统缺失导致的内核崩溃。但是内核是启动了的,只是根文件系统不存在而已。

13.8 image.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/),如下图所示:
image062.png
图 13.8.1复制mkimage文件

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

image066.png
图 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文件,内容如下:
  1. /dts-v1/;

  2. / {
  3.         description = "U-Boot fitImagefor PetaLinux/5.4+git999/zynqmp-generic";
  4.         #address-cells = <1>;

  5.         images {
  6.                 kernel@1 {
  7.                         description = "Linuxkernel";
  8.                         data = /incbin/("linux.bin");
  9.                         type = "kernel";
  10.                         arch = "arm64";
  11.                         os = "linux";
  12.                         compression = "gzip";
  13.                         load = <0x80000>;
  14.                         entry = <0x80000>;
  15.                         hash@1 {
  16.                                 algo = "sha256";
  17.                         };
  18.                 };
  19.                 fdt@system-top.dtb {
  20.                         description = "FlattenedDevice Tree blob";
  21.                         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");
  22.                         type = "flat_dt";
  23.                         arch = "arm64";
  24.                         compression = "none";
  25.                         
  26.                         hash@1 {
  27.                                 algo = "sha256";
  28.                         };
  29.                 };
  30.     };

  31.         configurations {
  32.                 default = "conf@system-top.dtb";
  33.                 conf@system-top.dtb {
  34.             description = "1Linux kernel, FDT blob";
  35.             kernel = "kernel@1";
  36.             fdt = "fdt@system-top.dtb";
  37.             
  38.             
  39.                         hash@1 {
  40.                                 algo = "sha256";
  41.                         };
  42.                 };
  43.     };
  44. };
复制代码
可以看出该文件的内容与我们使用“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文件内容如下:
  1. /dts-v1/;

  2. / {
  3.         description = "U-BootfitImage for Alientek ZYNQ MPSoc";
  4.         #address-cells = <1>;

  5.         images {
  6.                 kernel-1 {
  7.                         description = "Linuxkernel";
  8.                         data = /incbin/("arch/arm64/boot/Image");
  9.                         type = "kernel";
  10.                         arch = "arm64";
  11.                         os = "linux";
  12.                         compression = "none";
  13.                         load = <0x80000>;
  14.                         entry = <0x80000>;
  15.                         hash-1 {
  16.                                 algo = "sha256";
  17.                         };
  18.                 };
  19.                 fdt-1 {
  20.                         description = "FlattenedDevice Tree blob";
  21.                         data = /incbin/("arch/arm64/boot/dts/xilinx/system-top.dtb");
  22.                         type = "flat_dt";
  23.                         arch = "arm64";
  24.                         compression = "none";
  25.                         
  26.                         hash-1 {
  27.                                 algo = "sha256";
  28.                         };
  29.                 };
  30.         };

  31.         configurations {
  32.                 default = "config-1";
  33.                
  34.                 config-1 {
  35.                     description = "1Linux kernel, FDT blob";
  36.                     kernel = "kernel-1";
  37.                     fdt = "fdt-1";
  38.                 };
  39.         };
  40. };
复制代码
保存文件内容后,在终端中输入命令“mkimage -f fit-image.its image.ub”,如下图所示:
image068.png
图 13.8.4 生成image.ub文件

在内核源码根目录下可以找到生成的image.ub文件,如下图所示:
image070.png
图 13.8.5 生成的image.ub文件

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

至此,我们终于知道了image.ub是怎么来的,怎么生成的了。另外image.ub既然是U-Boot fitImage,那U-Boot fitImage又是什么呢?限于篇幅就不再介绍了,可自行上网搜索,笔者找到一篇不错的介绍,推荐下,链接如下:

从该链接可知U-Boot fitImage主要来源于Unify Kernel的思想,其思想如下:
“在编译linux kernel的时候,不必特意的指定具体的架构和SOC,只需要告诉kernel本次编译需要支持哪些板级的platform即可,最终将会生成一个Kernel image,以及多个和具体的板子(哪个架构、哪个SOC、哪个版型)有关的FDT image(dtb文件)。

bootloader在启动的时候,根据硬件环境,加载不同的dtb文件,即可使linux kernel运行在不同的硬件平台上,从而达到unify kernel的目标。”

关于fit更多的介绍和使用方法请参考本章的扩展阅读部分。

13.9 CPU调频策略
1、设置MPSoC开发板的CPU调频策略
我们知道:主频越高,功耗也越高。为了节省CPU的功耗和减少发热,我们有必要根据当前CPU的负载状态,动态地提供刚好足够的主频给CPU。调频或称变频技术应运而生。变频技术作为电源管理技术以节能为目的加入linux内核。我们可以通过配置内核来选择不同的调频策略。

我们来看一下如何通过图形化界面配置Linux内核的CPU调频策略,输入“make menuconfig”打开Linux内核的图形化配置界面,如下图所示:
image073.png
图 13.9.1 Linux内核图形化配置界面

进入如下路径:
  1.     CPU PowerManagement
  2.          ->CPU Frequency scaling
  3.            ->Default CPUFreq governor
复制代码
打开默认调频策略选择界面,如下图所示:
image075.png
图 13.9.2默认调频策略选择

可以看到Linux内核一共有6种调频策略,
①     Performance,最高性能,直接用最高频率,不考虑耗电。
②     Powersave,省电模式,通常以最低频率运行,系统性能会受影响,一般不会用这个。
③     Userspace,可以在用户空间手动调节频率,可以看到这是默认的配置。
④     Ondemand,定时检查负载,然后根据负载来调节频率。负载低的时候降低CPU频率以省电,负载高的时候提高CPU频率,增加性能。
⑤     conservative:保守模式,类似于ondemand,但调整相对较缓。
⑥     schedutil:4.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内核移植成功以后就要开始根文件系统的构建。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

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

本版积分规则



关闭

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

正点原子公众号

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

GMT+8, 2024-6-8 20:44

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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