主机环境
与编译 U-Boot 时不同,前几天把使用的 Ubuntu 升级到了 Ubuntu 22.04 LTS,交叉编译工具链仍然是 ARM 发布的 10.3 版。在编译 Kernel 的过程中,我们可能还需要安装其他一些依赖工具,这个在后面用到的时候缺啥装啥就可以(出现各种错误的时候再安装相应工具即可)。
过程
在开始编译之前,我们先介绍两个命令:make clean 用于清空编译中间文件 和 make distclean 用于清除所有编译产生的文件。如果我们想要重新编译,可以使用以上两个命令清理环境。这两个命令均定义在 Kernel 源码根目录的 Makefile 中。
第一步肯定是获取 Kernel 的源代码,我这里采用的是最新的 LTS 版:5.15.45:wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.52.tar.xz。下载后直接解压:tar xvJf linux-5.15.52.tar.xz。
- 可能需要相关工具才可以直接从 Kernel 官网下载
- 最好不要选用 Mainline 分支的版本
- 解压过程时间较长,耐心等待
[color=rgba(0, 0, 0, 0.501960784313726)]
[color=rgba(0, 0, 0, 0.501960784313726)]
成功下载并解压源代码之后,我们需要进入解压的 Kernel 源码目录下,使用命令:cd linux-5.15.52。此后就在 Kernel 源码目录下进行各种操作。
第二步就是生成配置,直接使用命令:ARCH=arm CROSS_COMPILE=arm-none-eabi- make O=build_stm32 stm32_defconfig。其中,参数 O=xx 用于指定编译的输出路径,这样,所有编译输出都放到指定目录下,方便查看。
第三步修改配置(裁剪)。直接使用命令:ARCH=arm CROSS_COMPILE=arm-none-eabi- make O=build_stm32 menuconfig。其中,参数 O=xx 用于指定编译的输出路径,这样,所有编译输出都放到指定目录下,方便查看。
需要特殊注意的是,每一步命令都必须带有 ARCH=arm CROSS_COMPILE=arm-none-eabi- 这俩参数,否则不能正常按照我们指定的架构来显示配置。正常就会进入下面左侧的配置界面了。
这里我们需要更改一些参数: “System Type” > “DRAM Base” = 0xc0000000 and “DRAM Size” = 0x02000000,以及将 “Boot options” -> “Kernel Execute-In_Place From ROM” 前面的型号去掉。最后保存退出即可。
第四步就是真正的编译了,直接使用命令:ARCH=arm CROSS_COMPILE=arm-none-eabi- make O=build_stm32 -j$(nproc),然后就是漫长的等待… 其中,参数 O=xx 用于指定编译的输出路径,这样,所有编译输出都放到指定目录下,方便查看。
5.正常编译完成之后,就会在 Kernel 源码的对应架构目录下生成我们真正需要的 arch/arm/boot/zImage 和 arch/arm/boot/dts/stm32f769-disco.dtb 这两个文件了。
Image 说明
在构建 Kernel 镜像时,我们可以为内核镜像选择多种格式。具体就看在 make menuconfig 这一步的配置。某些格式的镜像可能是针对特定架构的,下面来介绍一下常见的镜像格式。
vmlinux:vm 是 Virtual Memory 的缩写,它是由用户对内核源码编译出来的最原始的内核文件,是一个 ELF( Executable and Linkable Format)格式的文件。当我们编译完 Kernel 后,在源码根目录下就会生成该文件。vmlinux 是最原始的镜像文件,其他镜像文件都有它来生成。所有其他未压缩的镜像都直接或者间接由它生成。
vmlinux 这个名字来自于 Unix。在上世纪 60 年代,Unix 开发者简单地称他们的内核为 “unix”,所以,Linux 在上世纪 90 年代诞生后,Linus 开始称他们的内核为 “Linux”。当虚拟内存被开发为更容易的多任务处理能力时,“vm”被放在文件的前面,以表明内核支持虚拟内存。有一段时间,Linux 内核被称为 vmlinux。
在 Ubuntu 中,内核镜像文件就是 vmlinux 这个格式,存储在 /boot 文件夹中,名字的格式为 vmlinuz-A.B.C.D。A.B.C 是 Stable Kernel 的版本号,D 表示 PATCH 版本号。
注意,在 ./arch/arm/boot/compressed 下,还有个经过压缩之后的 vmlinux 。所有其他与压缩有关的镜像都直接或者间接由它生成。
vmlinuz:随着内核变得越来越大,无法容纳到可用的引导内存中,因此压缩了内核镜像,命名上则将最后 x 改为 z,以表示它是用 zlib 压缩压缩的。这种压缩并不总是被使用,而是经常被 LZMA 或 BZIP2 取代。
Image:它是基于根目录下未压缩的 vmlinux 生成的,编译完 Kernel 后,在对应架构的 boot(例如,arch\arm\boot) 目下就会生成该文件。
它经过 objcopy 处理的只包含二进制数据的内核代码,就是将 vmlinux 中的 ELF 头和尾部的符号表等去掉之后剩余的内容。
zImage:它是基于压缩过的 vmlinux 生成的,编译完 Kernel 后,在对应架构的 boot(例如,arch\arm\boot) 目下就会生成该文件。
生成方式与上面的 Image 是一模一样的(掐头去尾)。这里就不多上图了。
zImage 是 ARM linux 常用的一种压缩镜像文件
这种格式的 Linux 镜像文件多存放在 NAND 上
bzImage:bz 表示 big zImage,其格式与 zImage 类似,但采用了不同的压缩算法,bzImage 的压缩率更高。
uImage:这是 uboot 专用的镜像文件,它是在 zImage 之前加上一个长度为 0x40 的头信息(tag),在头信息内说明了该镜像文件的类型、加载位置、生成时间、大小等信息。换句话说,若直接从 uImage 的 0x40 位置开始执行,则 zImage 和 uImage 没有任何区别。
编译完 Kernel 后,在对应架构的 boot(例如,arch\arm\boot) 目下就会生成该文件
这种格式的 Linux 镜像文件多存放在 NAND 上
xipImage:它是基于根目录下未压缩的 vmlinux 生成的,编译完 Kernel 后,在对应架构的 boot(例如,arch\arm\boot) 目下就会生成该文件。
生成方式与上面的 Image 是一模一样的(掐头去尾)。这里就不多上图了。
xip 是 Execute In Place 的缩写,这种格式的 Linux 镜像文件多存放在 NorFlash 上,运行时不需要拷贝到内存 SDRAM 中,可以直接在 NorFlash 中运行。
Image 使用
Kernel 镜像的使用与我们在 make menuconfig 中的配置是有关系的。当然也与 U-Boot 相关。在上面的编译中,我们实际需要的文件是 linux-5.15.52/build_stm32/arch/arm/boot/zImage 和 linux-5.15.52/build_stm32/arch/arm/dts/stm32f769-disco.dtb 这两个文件。
zImage:这个通常需要使用 U-Boot 的相关命令来将它下载开发板的对应存储器中。例如,我这里就需要使用命令 fatload mmc 0 0xc0000000 zImage 将 zImage 下载到 MMC 中
stm32f769-disco.dtb:这个需要直接烧录到 MCU 的内部 FLASH 中,地址是 0x81c0000。这个其实在 U-Boot 中有对应的配置项。
[color=rgba(0, 0, 0, 0.501960784313726)]
|