# 前言

完整的 linux 系統需要以下部分:

  • Bootloader
    • boot.img
  • Linux Kernel(Linux 内核)
    • Device tree blob
  • Root Filesystem(根目录文件系統)

# bootloader

bootloader(引导装载程序)就是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境设置成一个合适的状态,以便为最终调用操作系统内核准备好正确的环境。

常见的 bootloader 有 PC 平台的 Grub;嵌入式平台的 vivi, RedBoot, u-boot 等,其中 u-boot 在使用上最广泛,因此在嵌入式中又常称 linux 系统构成为 u-boot、kernel、rootfs。

bootloader 是严重地依赖于硬件而实现的,特别是在嵌入式系统。因此,在嵌入式系统里建立一个通用的 bootloader 几乎是不可能的。尽管如此,我们仍然可以对 bootloader 归纳出一些通用的概念来,以指导用户进行特定的 bootloader 设计与实现。

在嵌入式系统中,bootloader 的意义与作用相当于 PC 平台中的 BIOS + Grub,它对开发板上的主要部件如 CPU、SDRAM、FLASH、串口等进行了初始化,可以使用 bootloader 下载文件到开发板,可以浏览目录,可以烧录 flash,可以启动系统等,实际上,一个功能比较强大的 bootloader 已经相当于一个微型的操作系统了。

总体上 bootloader 需要完成以下工作:

  • 初始化 CPU 速度;

  • 初始化内存,包括初始化内存配置寄存器等;

  • 初始化中断控制器,在系统启动时,关闭中断,关闭看门狗;

  • 初始化串行端口(如果在目标上有的话);

  • 启用指令 / 数据高速缓存;

  • 设置堆栈指针;

  • 设置参数区域并构造参数结构和标记(这是重要的一步,因为内核在标识根设备、页面大小、内存大小以及更多内容时可能需要使用引导参数);

  • 执行 POST(加电自检)来标识存在的设备并报告有何问题;

  • 为电源管理提供挂起 / 恢复支持;

  • 传输操作系统内核镜像文件到目标机。也可以将操作系统内核镜像文件事先存放在 Flash 中,这样就不需要 bootLoader 和主机传输操作系统内核镜像文件,这通常是在做成产品的情况下使用。而一般在开发过程中,为了调试内核的方便,不将操作系统内核镜像文件固化在 Flash 中,这就需要主机和目标机进行文件传输;

  • 跳转到内核的开始,在此又分为 ROM 启动和 RAM 启动。所谓 ROM 启动就是用 XIP 技术直接在 Flash 中执行操作系统镜像文件;所谓 RAM 启动就是指把内核镜像从 Flash 复制到 RAM 中,然后再将 PC 指针跳转到 RAM 中的操作系统启动地址。

目前使用的主流嵌入式平台,几乎都是用 u-boot 作为启动引导,u-boot 有哪些突出的优点呢?

① 开放源码:https://github.com/u-boot/u-boot;

② 支持多种嵌入式操作系统内核,如 Linux、NetBSD, VxWorks, QNX, RTEMS, ARTOS, LynxOS, android;

③ 支持多个处理器系列,如 PowerPC、ARM、x86、MIPS;

④ 较高的可靠性和稳定性;

⑤ 高度灵活的功能设置,适合 u-boot 调试、操作系统不同引导要求、产品发布等;

⑥ 丰富的设备驱动源码,如串口、以太网、SDRAM、FLASH、LCD、NVRAM、EEPROM、RTC、键盘等;

⑦ 较为丰富的开发调试文档与强大的网络技术支持。

# kernel

kernel 即 linux 内核。内核源代码可以免费从官网获取,这是一个通用的内核,里面包含着内核支持的所有的硬件平台及驱动的所有代码,是一个大而全的内核源代码。

在使用层面上,当嵌入式平台使用 linux 系统,那么最重要的就是 kernel 中驱动的移植;一般都不会从一个纯净的 kernel 中去进行移植操作,而是根据芯片厂商提供的 kernel 对特定的硬件平台及设备进行各种外设驱动相关的适配工作。

# Device Tree

设备树(Device Tree)是描述计算机的特定硬件设备信息的数据结构,以便于操作系统的内核可以管理和使用这些硬件,包括 CPU 或 CPU,内存,总线和其他一些外设。

老版本的 linux kernel 是没有设备树概念的,后来因为 SOC 的发展,kernel 中需要对这些新增的 SOC 进行支持,而这些代码都会编译到 kernel 中,会导致 kernel 日渐臃肿,于是后面就引入了在 PowerPC 等架构就已经采用的设备树。

1、dts (device tree source 设备树源文件)
dts 文件是一种 ASCII 文本格式的设备树描述文件,此文件适合人类阅读主要是给用户看的。一个 .dts 文件对应一个 ARM 的设备,一般放置在 arch/arm/boot/dts/ 中。

2、dtsi (device tree source include 设备树头文件)
由于 .dts 中包含了很多公共部分,linux 内核为了简化,将 Soc 公共部分提炼为 .dtsi 文件,类似 c 语言中的 .h 文件。当然,和 C 语言的头文件类似,.dtsi 也可以 include 其他的 .dtsi ,譬如几乎所有的 ARM SoC 的 .dtsi 都引用了 skeleton.dtsi 。对于同一个节点的设置情况, .dts 中的配置会覆盖 .dtsi 中的配置;因此, .dtsi 一般写 Soc 共性部分,而 .dts 一般写目标单板特性部分,所以一般 .dts 包含并重写部分 .dtsi

3、dtb (device tree blob 设备树二进制文件)
.dts 通过 dtc 编译工具编译成 .dtb 文件,被编译后的设备树文件与内核一同放入到存储介质中,当内核启动时读取设备树文件,就可以动态的将板级信息写入到内核中。

# rootfs

rootfs(Root Filesystem)即根目录文件系统,是 kernel 启动后挂载的第一个文件系统。rootfs 和 kernel 是分开的,但单独的 kernel 没有 rootfs 是没法正常工作的。在系统终端执行 cd / 即可看到当前的文件系统内容了。

现在有许多制作 rootfs 的工具,如 busybox,buildroot,Yocto 等。其中 buildroot 中包含了 busybox 的功能,只需要简单的操作就可以生成一个 rootfs 了。

# 参考

完整的 linux 系統:bootloader、linux kernel(linux 內核)、rootfile(根文件系統)

嵌入式 linux 应用开发

Linux 筆記 2

What is the difference between .dts file and .dtsi file?

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

夏沫の浅雨 微信支付

微信支付

夏沫の浅雨 支付宝

支付宝