BSP底层驱动设备树配置与启动引导实战 - 第1节

1.1 什么是BSP——板级支持包的本质

BSP,全称 Board Support Package,中文叫板级支持包。说白了,它就是一块「胶水」,把硬件和操作系统粘在一起。

我刚开始做嵌入式那会儿,对BSP的理解特别肤浅。觉得不就是几个驱动文件加一段启动代码嘛。后来踩了坑才明白——BSP的真正价值,是让上层操作系统「看不见」硬件的差异。

你想想看,同样是Linux内核,为什么能在ARM、RISC-V、x86上跑?就是因为每个平台都有自己的BSP,把CPU、内存、外设这些底层细节给封装好了。

BSP的核心组成

组件 作用 我见过的坑
Bootloader 初始化硬件,加载内核 DDR时序配错,板子直接黑屏
设备树 描述硬件拓扑和资源 中断号写错,外设死活不干活
内核驱动 操作具体外设 时钟没使能,I2C通信超时
配置文件 内核编译选项、分区表 分区大小算错,文件系统装不下

关键认知:BSP不是一套通用的「驱动库」,它是针对某一块具体板子的「定制方案」。换一块板子,BSP就得重新适配。

1.2 设备树的起源——为什么Linux需要它?

在设备树出现之前,Linux内核是怎么知道硬件信息的?答案是——硬编码。

早期ARM平台,每个板子都在 arch/arm/mach-xxx 下面写一堆C文件,里面全是 platform_device 结构体,手动注册每个外设的地址、中断、时钟。我翻过一些老代码,一个板子的硬件描述文件能写到上千行。

问题来了:

  • 换一个板子,就得改内核源码,重新编译
  • 同一个SoC的不同板子,代码大量重复
  • 社区维护成本爆炸,Linus Torvalds 都发过火

所以2005年左右,PowerPC平台先搞出了设备树的概念。后来ARM社区一看,这玩意儿好啊,2011年左右开始大规模迁移。到2012年,Linux 3.x 内核基本完成了设备树的普及。

我的经验:设备树本质上就是一个「硬件描述数据库」,用文本文件(.dts)把板子上有什么外设、接在哪个总线、用哪个中断、时钟频率多少,全部写清楚。内核启动时解析这个文件,动态构建设备模型。

1.3 设备树在Linux启动流程中的位置

这部分我建议你画个图来理解。启动流程其实就三步:

  1. Bootloader 初始化硬件,加载设备树和内核镜像到内存
  2. 内核早期启动 解析设备树,建立内存映射,初始化关键外设
  3. 内核驱动加载 根据设备树信息,匹配并初始化各个驱动

设备树在中间扮演的角色,就是「硬件配置单」。Bootloader把它传给内核,内核照着它干活。

设备树在Linux启动流程中的位置 Bootloader 初始化DDR、时钟、串口 加载设备树(.dtb)到内存 传递 内核早期启动 解析设备树 建立内存映射、中断控制器 驱动匹配 驱动加载 probe() 注册设备 设备树(Device Tree) 描述硬件拓扑:CPU、内存、外设地址、中断、时钟、GPIO 格式:.dts → .dtb(二进制)→ 内核解析 关键节点:/、chosen、memory、cpus、soc 关键说明 • Bootloader 负责将 .dtb 文件加载到内存,并通过寄存器 r2(ARM)传递地址 • 内核在 start_kernel() 之前就解析设备树,建立 early platform devices • 驱动通过 compatible 属性匹配设备树节点,触发 probe()

注意:设备树不是「配置文件」,它是在内核启动早期被解析的。一旦内核初始化完成,设备树的信息就被转换成了内核内部的 device 结构体。这时候你再改 .dtb 文件,已经没用了。

1.4 设备树解决了什么实际问题?

我举个例子你就明白了。

以前做一块新板子,如果换了串口芯片,从16550换成了PL011,你得:

  • 修改 arch/arm/mach-xxx.c,把 platform_device 的 name 改掉
  • 重新编译内核
  • 烧录整个内核镜像

有了设备树之后,只需要改 .dts 文件:

uart0: serial@101f0000 {
    compatible = "arm,pl011";
    reg = <0x101f0000 0x1000>;
    interrupts = <0 12 4>;
    clock-frequency = <24000000>;
};

然后重新编译 .dtb,替换这个文件就行。内核不用动。你想想看,这对产品迭代效率的提升有多大。

核心价值:设备树实现了「内核与硬件描述的分离」。硬件变了,改 .dts 就行;内核升级了,.dts 基本不用动。这也是为什么现在几乎所有嵌入式Linux平台都在用设备树。

1.5 本章小结

这一章我们聊了三件事:

  • BSP是板级支持包,是硬件和操作系统之间的桥梁
  • 设备树是为了解决硬件描述硬编码问题而生的,它把硬件信息从内核源码里抽离出来
  • 设备树在启动流程中处于Bootloader和内核驱动之间,是硬件配置的「中间人」