源码来源:各个arm官网下载,不同的CPU去对应的官网下载
我们在做系统移植的过程中,从各个arm官网上下载的kernel源码一般都是只有一些常规的驱动的,很多时候需要我们添加一些新的其他IC的驱动,这里就简单说明一下。
0. 准备工作
下载kernel源码,解压在自己的文件夹。
/*Linux内核源码目录分析*/ 路径 存放内容 /arch 不同CPU架构下的核心代码。其中的每一个子目录都代表Linux支持的CPU架构 ,比如arm,x86,MIPS,PPC等 /block block目录下放的是一些linux存储体系中关于块设备管理的代码;譬如说SD卡、iNand、Nand、硬盘等都是块设备。你几乎可以认为块设备就是存储设备 /crypto 常见的加密算法的C语言实现代码,譬如crc32、md5、sha1等 /Documentation 说明文档,对每个目录的具体作用进行说明 /drivers 内核中所有设备的驱动程序,其中的每一个子目录对应一种设备驱动 /firmware 固件代码,固件其实是软件,不过这个软件是固话到IC里面运行的,所以叫固件 /fs Linux支持的文件系统代码,及各种类型的文件的操作代码。每个子目录都代表Linux支持的一种文件系统类型 /include 头文件目录,公共的(各种CPU架构共用的)头文件都在这里。每种CPU架构特有的一些头文件在arch/arm/include目录及其子目录下 /init init是初始化的意思,这个目录下的代码就是linux内核启动时初始化内核的代码 /ipc 内核中进程间的通信代码 /kernel Linux核心功能源码,主要包括程序调度,控制进程,模块化等等 /lib lib是库的意思,这里面都是一些公用的有用的库函数,注意这里的库函数和C语言的库函数不一样的。在内核编程中是不能用C语言标准库函数,
这里的lib目录下的库函数就是用来替代那些标准库函数的。
比如在内核中要把字符串转成数字用atoi,但是内核编程中只能用lib目录下的atoi函数,不能用标准C语言库中的atoi。
再比如在内核中要打印信息时不能用printf,而要用printk,这个printk就是我们这个lib目录下的 /mm 内存管理代码,譬如页式存储管理内存的分配和释放等 /net 网络通信相关代码 ,譬如TCP/IP协议栈等都在这里 /samples 内核编程的示例代码 /scripts 脚本,这个目录下全部是脚本文件,这些脚本文件不是linux内核工作时使用的,而是用来辅助对linux内核进行配置编译生成的,比如裁剪内核等等 /security 安全性相关的代码 /sound 音频设备的驱动程序 /tools Linux中的常用工具 /usr 内核启动相关的代码 /virt 内核虚拟机相关的代码 /Kbuild Kbuild是kernel build的意思,就是内核编译的意思。这个文件就是linux内核特有的内核编译体系需要用到的文件 /Makefile 这个是linux内核的总makefile,整个内核工程是用这个Makefile来管理的 /*注意,最后两个Kbuild和Makefile和上面提到的不一样,它们两个是文件,不是文件夹*/
最后,还要补充两个重要的目录,这里以arm架构为例(注意,前提是内核源码经过了编译,才会在这些目录下生成这些文件):
arch/arm/boot/ :Linux内核编译完成以后,在此目录下生成image,zImage镜像文件
arch/arm/boot/dts:存放Linux内核所有设备树文件,包括dts编译后对应的.dtb文件
1. 配置Kernel编译环境
主要就是配置交叉编译器。
如果是 arm 的产品,就是 export ARCH=arm
如果是 ARM64 的产品,就是 export ARCH=arm64
其他的配置按常规交叉编译环境配置即可
2. 找到对应CPU的Kernel配置的配置
这个文件夹里有一堆板载的配置文件,我们一般在这里选择跟我们CPU相近的来配置;如果在kernel官网下载的源码,里面可能不会有你这个CPU对应的配置文件,为此我们一般去各个厂家官网下载他们提供的源码,他们的源码里会有对应的配置文件。
找到编译 Kernel需要的配置。如果是 ARM 架构的 CPU ,一般位置在 Kernel 目录下的:arch/arm/configs/
如果是 ARM64, 一般配置的位置在kernel目录下的:arch/arm64/configs/
3. 加载配置
像 Amlogic的 A311D 芯片,通过上步的路径找到他的配置 arch/arm64/configs/aplex_cmi_aa158_defconfig (注意:路径是:arch/arm64/configs/ ,管网下载的源码里该芯片的配置文件文件名并不是这个aplex_cmi_aa158_defconfig,这个文件名是我修改过的,初始文件名是 一般是板子CUP的命名加defconfig )
接着加载配置的方法就是:make aplex_cmi_aa158_defconfig ARCH=arm64(ARCH=arm64是指定编译64位的,一般这个 ARCH=arm64 会放在 ~/.bashrc 里面,放在编译这里也行)。
make aplex_cmi_aa158_defconfig ARCH=arm64,这个步骤就是把 arch/arm64/configs/aplex_cmi_aa158_defconfig 里面的配置写到了,Linux 代码目录下的 .config 文件里面;要执行这一步后,后面执行make编译kernel才会编译生成对应的dtb文件。
4. 打开 menuconfig
执行 make menuconfig ARCH=arm64 (或者是32位平台的话,执行 make menuconfig ARCH=arm 根据你的平台来决定) ,把 menuconfig 操作就是把 .config 文件里面的配置读取出来,然后显示在一个可视化的界面里:
如果没有执行 make aplex_cmi_aa158_defconfig ARCH=arm64 的话,那么执行 make menuconfig 可能加载的就是 X86 架构的配置。在 make menuconfig 里面,可以配置自己想要添加的驱动,Exit的时候要选择保存。
如果你只是编译kernel还是要执行一次这个操作,不过只需要打开menuconfig再保存退出即可,不然后面编译容易报一些错误。
5. 保存配置
如果是 ARM32 的CPU ,就在 Kernel 目录执行 make savedefconfig ARCH=arm。
如果是 ARM64 的CPU ,就在 Kernel目录执行 make savedefconfig ARCH=arm64。
执行完毕之后,会生成一个保存的配置文件为: defconfig 。
再把 defconfig 文件配置覆盖先前的配置(步骤3加载的配置)。执行指令 cp defconfig arch/arm64/configs/aplex_cmi_aa158_defconfig -rf 这样,配置就保存下来了。
6. menuconfig 添加 HYM8653 RTC 驱动举例
如果你只是编译kernel的话,这步可以跳过。
先加载原始的配置:make aplex_cmi_aa158_defconfig 在打开 make menuconfig 找到 RTC 的驱动。
按 Enter是选择目录。按空格键 是切换是否选择, * 代表驱动加载到 Kernel里面去,M 代表编译成模块。空白表示不操作。退出之后保存。执行 make savedefconfig 指令保存配置,再将保存好的 defconfig文件保存在arch/arm64/configs/ 目录下的对应文件:执行指令 cp defconfig arch/arm64/configs/aplex_cmi_aa158_defconfig -rf 进行保存,这样 make 编译的时候就会将 RTC HYM8563 的驱动编译进去。
7. 配置 HYM8653 RTC 驱动的设备树 dts
如果你只是编译kernel的话,这步可以跳过。
这一步步骤放在4、5、6步骤前后操作都可以,设备树文件一般的位置:
像 ARM 的CPU ,一般的位置在 Kernel 的 arch/arm/boot/dts/ 目录下。
像 ARM64 的CPU,一般的位置在 Kernel 的 arch/arm64/boot/dts/ 目录下。
不同设备的设备树配置不同,需要看该设备挂载在哪个节点上,再在相对应的节点添加改驱动的设备节点信息,一些设备信息配置官网会给出相应的文档,一些没有的就需要自己去查,还有一些设备信息可以在Linux 源码目录 /Documentation/devicetree/bindings里查看。
例如, 这里举例的例子的设备树就在 :arch/arm64/boot/dts/aplex/ (aplex文件夹是我自己添加的,一般官网下载的源码,设备树文件都保存到dts文件夹)目录下:
关于设备树的说明可以参考我另一个文档:https://www.cnblogs.com/xingboy/p/14898899.html
例如 添加 RTC 的设备节点就在: arch/arm64/boot/dts/aplex/cmi_aa158.dts 如下位置:
8. 编译Kernel
一般官网下载的Kernel的编译都有其写好对应的脚本,每个Kernel编译的方法都有一点点不同,如果系统全部是你自己制作的,编译一般是直接make,如果需要开多线程编译,可以执行 make -j** 指令(**是指你需要开启的线程数)。
编译后会在arch/arm/boot文件夹生成一个zImage文件,还会在arch/arm/boot/dts文件夹生成一个 ***.dtb 文件(***是你编译的内核名,跟前面编译配置文件时配置文件前的***一致,修改该文件夹里的Makefile文件可以添加编译的dtb文件) ,这两个文件后续做系统镜像需要用到。
编译后的烧录镜像制作可以参考我另一个博客文章:https://www.cnblogs.com/xingboy/p/14858853.html。