完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
1)实验平台:正点原子领航者ZYNQ开发板 2)平台购买地址:https://item.taobao.com/item.htm?&id=606160108761 3)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/FPGA/zdyz_linhanz.html 4)对正点原子FPGA感兴趣的同学可以加群讨论:876744900 5)关注正点原子公众号,获取最新资料 第十六章Linux内核顶层Makefile详解 前几章我们重点讲解了如何移植uboot到领航者开发板上,从本章开始我们就开始学习如何移植Linux内核。同uboot一样,在具体移植之前,我们先来学习一下Linux内核的顶层Makefile文件,因为顶层Makefile控制着Linux内核的编译流程。 1.1Linux内核获取 关于Linux的起源以及发展历史,这里就不啰嗦了,网上相关的介绍太多了。即使写到这里也只是水一下教程页数而已,没有任何实际的意义。有限的时间还是放到有意义的事情上吧,Linux由Linux基金会管理与发布,Linux官网为https://www.kernel.org,所以你想获取最新的Linux版本就可以在这个网站上下载,网站界面如下图所示: 图 27.1.1 linux官网 从上图可以看出最新的稳定版Linux已经到了5.1.4,大家没必要追新,因为4.x版本的Linux和5.x版本没有本质上的区别,5.x更多的是加入了一些新的平台、新的外设驱动而已。 Xilinx会从https://www.kernel.org下载某个版本的Linux内核,然后将其移植到自己的芯片平台上,测试成功以后就会将其开放给Xilinx的芯片平台开发者。开发者下载Xilinx提供的Linux内核,然后将其移植到自己的产品上。后面的移植我们使用Xilinx提供的Linux源码,Xilinx提供的Linux源码已经放到了开发板光盘中,路径为:ZYNQ开发板资料盘(A盘)4_SourceCodeZYNQ_70203_Embedded_Linux资源文件kernellinux-xlnx-xilinx-v2018.3.tar.gz。 1.2Linux内核编译初次编译 先看一下如何编译Linux源码,这里编译一下领航者开发板移植好的Linux源码,已经放到了开发板光盘中,路径为:ZYNQ开发板资料盘(A盘)4_SourceCodeZYNQ_70203_Embedded_Linux资源文件kernel linux-4.14.0-atk-v2018.3.tar.gz。可以在Ubuntu中新建一个名为“alientek_linux”的文件夹,然后将linux- linux-4.14.0-atk-v2018.3.tar.gz这个压缩包拷贝到新建的alientek_linux文件夹中并解压。此处我们使用20.1节下载的linux内核。进入到下载到内核目录处,查看内核目录结构,命令如下:
可以看到Linux源码根目录如下图所示: 图 27.2.1正点原子提供的Linux源码根目录 其中oe-logs和oe-workdir是Petalinux工具生成的链接目录,不是linux内核的源码目录。 现在我们讲解一下如何编译出对应的Linux镜像文件。新建名为“zynq.sh”的shell脚本,然后在这个shell脚本里面输入如下所示内容: 示例代码 zynq.sh文件内容
第2行,执行“make distclean”,清理工程,所以zynq.sh每次都会清理一下工程。如果通过图形界面配置了Linux,但是还没保存新的配置文件,那么就要慎重使用zynq.sh编译脚本了,因为它会把你的配置信息都删除掉。 第3行,执行“make xxx_defconfig”,配置工程。 第4行,执行“make menuconfig”,打开图形配置界面,对Linux进行配置,如果不想每次编译都打开图形配置界面的话可以将这一行删除掉。 第5行,执行“make”,编译Linux源码。 可以看出,Linux的编译过程基本和uboot一样,都要先执行“make xxx_defconfig”来配置一下,然后在执行“make”进行编译。如果需要使用图形界面配置的话就执行“make menuconfig”。 使用chmod给予zynq.sh可执行权限,然后运行此shell脚本,命令如下:
编译的时候会弹出Linux图形配置界面,如下图所示: 图 27.2.2 Linux图形配置界面 Linux的图行界面配置和uboot是一样的,这里我们不需要做任何的配置,直接按两下ESC键退出,退出图形界面以后会自动开始编译Linux。等待编译完成,完成以后如下图所示: 图 27.2.3 Linux编译完成 编译完成以后就会在arch/arm/boot这个目录下生成一个叫做zImage的文件,zImage就是我们要用的Linux镜像文件。另外也会在arch/arm/boo/dts下生成很多.dtb文件,这些.dtb就是设备树文件,比如zynq-altk.dtb就是领航者开发板对应的设备树。 1.3Linux工程目录分析 将正点原子提供的Linux源码进行解压,解压完成以后的目录如下图所示: 图 27.3.1未编译的Linux源码目录 上图就是正点原子提供的未编译的Linux源码目录文件,我们在分析Linux之前一定要先在Ubuntu中编译一下Linux,因为编译过程会生成一些文件,而生成的这些恰恰是分析Linux不可或缺的文件。编译后的Linux目录如下图所示: 图 27.3.2编译后的Linux目录 上图中重要的文件夹或文件的含义如下表所示: 表 26.2.2.1 Linux目录 上表中的很多文件夹和文件我们都不需要去关心,我们要关注的文件夹或文件如下: 1、arch目录 这个目录是和架构有关的目录,比如arm、arm64、avr32、x86等等架构。每种架构都对应一个目录,在这些目录中又有很多子目录,比如boot、common、configs等等,以arch/arm为例,其子目录如下图所示: 图 27.3.3 arch/arm子目录 上图是arch/arm的一部分子目录,这些子目录用于控制系统引导、系统调用、动态调频、主频设置等。arch/arm/configs目录是不同平台的默认配置文件:xxx_defconfig,如下图所示: 图 27.3.4配置文件 在arch/arm/configs中就包含有领航者开发板的默认配置文件:xilinx_zynq_defconfig,执行“make xilinx_zynq_defconfig”即可完成配置。arch/arm/boot/dts目录里面是对应开发平台的设备树文件,正点原子领航者开发板对应的设备树文件如下图所示: 图 27.3.5正点原子领航者开发板对应的设备树 arch/arm/boot目录中有编译出来的Image和zImage镜像文件,而zImage就是我们要用的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目录 头文件目录。 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源码的目录信息,建议仔细阅读一下此文件。 关于Linux源码目录就分析到这里,接下来分析一下Linux的顶层Makefile。 1.4VSCode工程创建 在分析Linux的顶层Makefile之前,先创建VSCode工程,创建过程和uboot一样。创建好以后将文件.vscode/settings.json改为如下所示内容: 示例代码 settings.json文件内容
创建好VSCode工程以后就可以开始分析Linux的顶层Makefile了。 1.5顶层Makefile详解 Linux的顶层Makefile和uboot的顶层Makefile非常相似,因为uboot参考了Linux,前610行几乎一样,所以前面部分我们大致看一下就行了。 1、版本号 顶层Makefile一开始就是Linux内核的版本号,如下所示: 示例代码 顶层Makefile代码段
可以看出,Linux内核版本号为4.14.0。 2、MAKEFLAGS变量 MAKEFLAGS变量设置如下所示: 示例代码 顶层Makefile代码段
3、命令输出 Linux编译的时候也可以通过“V=1”来输出完整的命令,这个和uboot一样,相关代码如下所示: 示例代码 顶层Makefile代码段
4、静默输出 Linux编译的时候使用“make -s”就可实现静默编译,编译的时候就不会打印任何的信息,同uboot一样,相关代码如下: 示例代码 顶层Makefile代码段
5、设置编译结果输出目录 Linux编译的时候使用“O=xxx”即可将编译产生的过程文件输出到指定的目录中,相关代码如下: 示例代码 顶层Makefile代码段
6、代码检查 Linux也支持代码检查,使用命令“make C=1”使能代码检查,检查那些需要重新编译的文件。“make C=2”用于检查所有的源码文件,顶层Makefile中的代码如下: 示例代码 顶层Makefile代码段
7、模块编译 Linux允许单独编译某个模块,使用命令“make M=dir”即可,旧语法“make SUBDIRS=dir”也是支持的。顶层Makefile中的代码如下: 示例代码 顶层Makefile代码段
外部模块编译过程和uboot也一样,最终导出srctree、objtree和VPATH这三个变量的值,其中srctree=.,也就是当前目录,objtree同样为“.”。 8、设置目标架构和交叉编译器 同uboot一样,Linux编译的时候需要设置目标板架构ARCH和交叉编译器CROSS_COMPILE,在顶层Makefile中代码如下: 示例代码 顶层Makefile代码段
有时为了方便,可以直接修改顶层Makefile中的ARCH和CROSS_COMPILE,将其设置为对应的架构和编译器,比如本教程可以将ARCH设置为arm,CROSS_COMPILE设置为arm-linux-gnueabihf-,如下所示: 示例代码 顶层Makefile代码段
设置好以后就可以使用如下命令编译Linux了:
9、调用scripts/Kbuild.include文件 同uboot一样,Linux顶层Makefile也会调用文件scripts/Kbuild.include,顶层Makefile相应代码如下: 示例代码 顶层Makefile代码段
10、交叉编译工具变量设置 顶层Makefile中其他和交叉编译器有关的变零设置如下: 示例代码 顶层Makefile代码段
LA、LD、CC等这些都是交叉编译器所使用的工具。 11、头文件路径变量 顶层Makefile定义了两个变量保存头文件路径:USERINCLUDE和LINUXINCLUDE,相关代码如下: 示例代码 顶层Makefile代码段
第380~386行的USERINCLUDE是UAPI相关的头文件路径,第390~395行的LINUXINCLUDE是Linux内核源码的头文件路径。重点来看下LINUXINCLUDE,其中srctree=.,objtree=.,hdr-arch=arm,KBUILD_SRC为空,因此,将USERINCLUDE和LINUXINCLUDE展开以后为:
12、导出变量 顶层Makefile会导出很多变量给子Makefile使用,导出的这些变量如下: 示例代码 顶层Makefile代码段
1.5.1 make xxx_defconfig过程 第一次编译Linux之前都要先使用“make xxx_defconfig”配置Linux内核,在顶层Makefile中有“%config”这个目标,如下所示: 示例代码 27.5.117.5.1顶层Makefile代码段
第491~514行和uboot一样,都是设置定义变量config-targets、mixed-targets和dot-config的值,最终这三个变量的值为:
因为config-targets=1,因此第541行~548行成立。第541行引用arch/arm/Makefile这个文件,这个文件很重要,以为zImage、uImage等这些文件就是由arch/arm/Makefile来生成的。 第542行导出变量KBUILD_DEFCONFIG KBUILD_KCONFIG。 第544行,没有目标与之匹配,因此不执行。 第547行,“make xxx_defconfig”与目标“%config”匹配,因此被执行。“%config”依赖scripts_basic、outputmakefile和FORCE,真正有意义的依赖是scripts_basic。scripts_basic的规则如下: 示例代码 27.5.217.5.2 顶层Makefile代码段
build定义在文件scripts/Kbuild.include中,值为build := -f $(srctree)/scripts/Makefile.build obj,因此将上述示例代码展开就是:
接着回到Makefile的目标“%config”处,内容如下:
将命令展开就是:
1.5.2Makefile.build脚本分析 从上一小节可知,“make xxx_defconfig“配置Linux的时候如下两行命令会执行脚本scripts/Makefile.build:
我们依次来分析一下: 1、scripts_basic目标对应的命令 scripts_basic目标对应的命令为:@make -f ./scripts/Makefile.build obj=scripts/basic。打开文件scripts/Makefile.build,有如下代码: 示例代码 27.5.317.5.3 Makefile.build代码段
将kbuild-dir展开后为:
将kbuild-file展开后为:
最后将45行展开,即:
继续分析scripts/Makefile.build,如下代码: 示例代码 27.5.417.5.4 Makefile.build代码段
__build是默认目标,因为命令“@make -f ./scripts/Makefile.build obj=scripts/basic”没有指定目标,所以会使用到默认目标__build。在顶层Makefile中,KBUILD_BUILTIN为1,KBUILD_MODULES为空,因此展开后目标__build为:
可以看出目标__build有5个依赖:builtin-target、lib-target、extra-y、subdir-ym和always。这5个依赖的具体内容如下:
只有always有效,因此__build最终为:
__build依赖于scripts/basic/fixdep和scripts/basic/bin2c,所以要先将scripts/basic/fixdep.c和scripts/basic/bin2c.c这两个文件编译成fixdep和bin2c。 综上所述,scripts_basic目标的作用就是编译scripts/basic/fixdep和scripts/basic/bin2c这两个文件。 2、 %config目标对应的命令 %config目标对应的命令为:@make -f ./scripts/Makefile.build obj=scripts/kconfig xxx_defconfig,此命令会使用到的各个变量值如下:
可以看出,Makefilke.build会读取scripts/kconfig/Makefile中的内容,此文件有如下所示内容: 示例代码 27.5.517.5.5 scripts/kconfig/Makefile代码段
目标%_defconfig与 xxx_defconfig匹配,所以会执行这条规则,将其展开就是:
%_defconfig依赖scripts/kconfig/conf,所以会编译scripts/kconfig/conf.c生成conf这个软件。此软件就会将%_defconfig中的配置输出到.config文件中,最终生成Linux kernel根目录下的.config文件。 |
|
相关推荐
|
|
ElfBoard ELF 1板卡-开发板启动后打印random: nonblocking pool is initialized
354 浏览 0 评论
G2D图像处理硬件调用和测试-基于米尔-全志T113-i开发板
1501 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡- 减少uboot阶段的等待时间
1199 浏览 0 评论
嵌入式学习-飞凌ElfBoard ELF 1板卡 - 重新打包文件系统发现ftp无法正常连接
1686 浏览 0 评论
飞凌嵌入式ElfBoard ELF 1板卡-6ull设置两个ip
2294 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-4-18 08:20 , Processed in 0.600315 second(s), Total 54, Slave 45 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号