[1]罗名驹. 基于ARM Cortex-A9的嵌入式Linux内核移植研究与实现[D].广东工业大学,2017.
移植环境搭建
1. ubuntu 安装
嵌入式开发通常是在宿主机上编写好程序,使用交叉编译工具生成目标板上可以执行的二进制代码,再将编译好的二进制代码下载或者烧写到目标板指定的存储位置,目标板上电后可以从指定的存储位置读取代码开始执行。
2. Linaro ARM 交叉编译工具链
根据虚拟机里的 Ubuntu 系统的位数来选择 64 位的交叉编译器工具链还是 32 位的交叉编译工具链。
设备树
在 Linux 内核 3.x 版本引入了设备树。在 ARM Linux 内核中使用设备树后,Linux 内核可以直接通过设备树文件来获取板级硬件的细节信息,大大减少 ARM Linux 内核中的冗余代码。
ARM Linux 内核和 U-boot 中引入设备树后,不但使 U-boot 和 Linux 内核可以使用同一个 ARM 架构芯片的设备树文件,而且用一个内核镜像去引导同一类 ARM 架构芯片的硬件平台成为了可能,可以大大减少 Linux 系统移植和驱动开发的工作量。
在设备树中,可描述板级硬件的信息包括:
- CPU 的数量和类别
- 内存基地址和大小
- 总线和桥
- 中断控制器
- Clock 控制器
- GPIO 控制器
- 外围设备
dts 由节点和属性组成,每个节点可包含子节点和属性。每个设备树源码文件里面有且仅有一个根节点 “/”,且节点名必须是 “/”。chosen 节点不是用来描述硬件资源的信息,而是向 Linux 内核传递一些运行时的参数。使用 chosen 节点可以取代 Bootloader 通过 tag list 传递运行参数给 Linux 内核。例如:bootargs 这个属性传递的是 command line 的信息;initrd-start 这个属性传递是 initrd 的开始地址。
配置 Linux 内核时选中 CONFIG_DTC 选项,Linux 内核在编译的过程中会自动编译生成设备树编译器。在 Linux 内核源码根目录下运行 make dtbs 命令时,设备树源码编译器会把选中的 .dts 编译成 .dtb。
使用设备树源码编译器把 .dts 格式的设备树源码文件编译成.dtb 格式的设备树二进制文件(Device tree blob)。在制作板级硬件制作启动镜像时,通常会在指定区域存放 .dtb 文件,U-boot 在引导内核的过程中会把该.dtb 二进制文件读取到内存特定的区域中。
如果 U-boot 传递给内核的设备树中根结点的 compatible 属性出现在某个板级硬件的 .dt_compat 表中,相关的板级硬件就与对应的设备树匹配,被执行相关板级硬件的初始化函数。
设备树编译工具:apt-get install device-tree-compiler
uboot
它的主要工作是初始化硬件设备,例如关闭芯片看门狗、屏蔽所有中断、禁用 MMU 和缓存,初始化内存芯片,初始化输出显示设备等;规划好系统运行的内存空间,准备好系统的运行环境;从启动设备上拷贝操作系统和文件系统到内存指定的地方,跳转到内存指定的地方执行内核。
1. 了解处理器芯片
对目标板上处理器芯片的启动方式、系统时钟初始化、串口初始化、内存初始化以及目标板的内存地址空间分配有一个比较清楚的认识,特别是要了解芯片的启动过程。
2. uboot 源码
U-boot 源码目录一般可以分为三大类:第一类目录是与处理器体系结构或开发板硬件直接相关;第 2 类目录是一些通用的函数或者驱动程序;第 3 类目录是 U-Boot 的应用程序、工具或者文档。
U-boot 从 v2014.04 这个版本开始加入了对设备树的支持,引入了驱动模型(driver model),简称为 DM。与 Linux 内核的设备驱动模型类型,U-boot 的驱动模型和设备树相互配合使用,不仅统一设备驱动框架、提供设备树视图,还降低设备驱动的开发复杂度。U-boot 的驱动模型主要有四个组成部分,分别是 udevice、driver、uclass 和 uclass_driver。
SPL 是 U-boot 中 独 立 的 一 个 代 码 分 支 , 复 用 了 U-boot 的 代 码 , 由CONFIG_SPL_BUILD 配置项控制,它把 U-boot 的执行分为了 2 个阶段。SPL 是 U-boot 第一阶段执行的代码,完成芯片级、板级的一些初始化操作,最主要的是初始化时钟和片外内存、加载 U-boot 第二阶段的代码并跳转到内存中去执行这部分代码。
3. uboot 启动流程分析
以 armv7 架构的 CPU 为例,U-boot 在启动过程中主要做的事情分为 2 部分:
- 一是 CPU 架构级的初始化工作;CPU 架构级的初始化工作主要包括关闭中断,设置 svc 模式,禁用 MMU、TLB,设置时钟、看门狗等。
- 二是板级相关的初始化工作;板级相关的初始化工作主要包括堆栈环境的设置;代码重定向之前的板级初始化,包括串口、环境变量等初始化工作;代码重定向之后的板级初始化,例如 eMMc、Nand Flash、网卡、LCD 显示屏等的初始化工作;
- 最后进入命令行状态,等待终端输入命令以及对命令进行处理。
4. u-boot在目标板上的移植
- 选择和目标板类似的配置文件。
- 修改配置文件
- 在源码根目录下生成 u-boot-spl.bin 和 u-boot.bin 文件,将其烧写到 SD 卡。
如果有需要,设置时钟和串口。
内核移植
U-boot 启动 Linux 内核是通过 bootm_headers_t images 这个数据结构来传递参数的,这个结构体数据会存放在内存指定的位置。U-boot 会获取 Linux 内核、文件系统和设备树的相关信息,然后把它们加载到指定的内存位置,设置好启动参后就跳转到内核所在的地址开始执行。
Init 进程通过 U-boot 传递过来的命令行参数或者是设备树提供的参数来挂载根文件系统,执行用户指定的命令。
移植引入设备树的 ARM Linux 内核只需要添加相应的配置文件,而不用去大量修改内核源码目录下板级相关文件,大大简化了 Linux 内核移植的工作。
在移植 Linux-4.4 内核到目标板前,要在 Linux 内核源码下添加目标板的设备树文件和目标板的配置文件。对 于 ARM 架 构 的 芯 片 ,设备树文件存放在 Linux 内核源码根目录下的 arch/arm/boot/dts 目录下,目标板配置文件存放在 Linux内核源码根目录下的 arch/arm/configs 目录下。
- 通过修改 Linux 内核源码根目录下的 arch/arm/boot/dts/Makefile 文件,使内核在编译过程中编译新添加的 exynos4412-tiny4412SDK.dts 文件。
make ARCH=arm xxxx_deconfig make ARCH=arm menuconfig - 修改 xxx.dts 文件,在 chosen 中修改 bootargs 设置。
make ARCH=arm uImage CROSS_COMPILE=arm-linux-gnueabi-
编译完成后,会在 Linux 内核源码根目录下的 arch/arm/boot 目录下生成 uImage 二进制内核镜像,在 arch/arm/boot/dts/目录下会生成目标板上用的设备树镜像文件 exynos4412-tiny4412SDK.dtb。
根文件系统构建
Linux 系统启动后, Linux 内核会挂载一个设备到根目录上,这个设备中的文件系统被称为根文件系统。根文件系统中存放了所有的系统命令、系统配置以及其他文件系统的挂载点以及嵌入式系统使用的所有应用程序和库 。Linux 系统启动时,第一个必须挂载的是根文件系统;若不能从指定设备上挂载根文件系统,Linux 系统会出错而终止启动过程。
- busyBox 工具。构建根文件系统。
- 制作 RamDisk 文件系统。
|