当前位置: 首页 > backend >正文

深度解析Linux设备树(DTS):设计原理、实现框架与实例分析

文章目录

    • 深度解析Linux设备树(DTS):设计原理、实现框架与实例分析
      • 一、设备树诞生的根本原因:ARM生态的"碎片化困境"
        • 传统BSP开发模式的问题:
      • 二、设备树设计框架:分层硬件描述模型
        • 设备树框架架构图:
        • 典型设备树结构示例:
      • 三、设备树核心机制深度解析
        • 1. 地址映射机制
        • 2. 中断映射机制
      • 四、设备树编译与运行时流程
        • 完整生命周期:
      • 五、高级应用:设备树覆盖(Overlay)实战
        • Overlay框架图:
      • 六、设备树与传统开发模式对比
        • 架构差异图:
        • 开发流程对比表:
      • 七、设备树设计最佳实践
      • 总结:设备树的技术本质与价值

深度解析Linux设备树(DTS):设计原理、实现框架与实例分析

一、设备树诞生的根本原因:ARM生态的"碎片化困境"

传统BSP开发模式的问题:
内核源码
mach-boardA.c
开发板A
board-specifc.h
mach-boardB.c
开发板B
board-specifc.h
mach-boardC.c
开发板C
board-specifc.h
ARM SoC

典型问题案例
三星S3C2410 ARM9处理器在内核中的实现:

  • arch/arm/mach-s3c2410/mach-smdk2410.c (1500+行代码)
  • 硬编码资源定义:
static struct resource smdk2410_uart0_resources[] = {[0] = {.start = S3C2410_PA_UART0,.end   = S3C2410_PA_UART0 + 0x3fff,.flags = IORESOURCE_MEM,},[1] = {.start = IRQ_S3CUART_RX0,.end   = IRQ_S3CUART_ERR0,.flags = IORESOURCE_IRQ,}
};

后果:内核中仅ARM架构就有200+个mach-目录,每次硬件变更都需要重新编译内核。


二、设备树设计框架:分层硬件描述模型

设备树框架架构图:
内核解析层
编译/运行层
DTS设计层
物理连接
dts -> dtb
传递DTB
OF Core
device_node树
platform_device
驱动匹配
DTB二进制
DTC编译器
Linux内核
Bootloader
dtsi - SoC级定义
设备树源文件
dts - 板级定义
CPU核心
内存映射
时钟体系
外设配置
扩展接口
硬件层
典型设备树结构示例:
// ----- SoC级定义 (sun20i-d1.dtsi) -----
/ {#address-cells = <2>;#size-cells = <2>;cpus {cpu0: cpu@0 {compatible = "riscv";reg = <0>;};};soc {ranges;serial0: serial@2500000 {compatible = "snps,dw-apb-uart";reg = <0x0 0x02500000 0x0 0x400>;interrupts = <GIC_SPI 2 IRQ_TYPE_LEVEL_HIGH>;clocks = <&ccu CLK_BUS_UART0>;};};
};// ----- 板级定义 (board.dts) -----
#include "sun20i-d1.dtsi"/ {memory@40000000 {device_type = "memory";reg = <0x0 0x40000000 0x0 0x20000000>; // 512MB RAM};leds {compatible = "gpio-leds";led0 {label = "board:red:status";gpios = <&pio 2 3 GPIO_ACTIVE_HIGH>; // PC3};};
};

三、设备树核心机制深度解析

1. 地址映射机制
#address-cells=2
#size-cells=1
父节点
子节点
reg属性
cell0: 片选0
cell1: 偏移0x30000000
cell2: 长度0x1000000

实际案例

soc {#address-cells = <2>;  // 地址用2个32位数表示#size-cells = <1>;     // 大小用1个32位数表示ethernet@10000000 {compatible = "davicom,dm9000";reg = <00x10000000   // 高32位地址0x10000000   // 低32位地址0x1000>;     // 寄存器区大小4KB};
};
2. 中断映射机制
设备节点中断控制器内核驱动interrupts = <0 23 1>0:中断类型23:中断号1:触发方式转换为全局中断号request_irq(global_irq)设备节点中断控制器内核驱动

代码实现

// 驱动获取中断号
int irq = platform_get_irq(pdev, 0);// 内核内部转换
unsigned int irq_of_parse_and_map(struct device_node *dev, int index)
{struct of_phandle_args oirq;if (of_irq_parse_one(dev, index, &oirq))return 0;return irq_create_of_mapping(&oirq);
}

四、设备树编译与运行时流程

完整生命周期:
DTB地址
dts/dtsi源码
DTC编译器
DTB二进制
Bootloader
Linux内核
unflatten_device_tree
device_node树
of_platform_populate
platform_device
驱动匹配
probe函数

关键步骤详解

  1. 编译阶段

    # 编译命令
    dtc -I dts -O dtb -o board.dtb board.dts# 反编译查看
    fdtdump board.dtb
    
  2. 启动阶段

    // ARM启动协议
    r0 = 0, r1 = 机器ID, r2 = DTB物理地址
    
  3. 内核解析

    // 初始化流程
    start_kernel()-> setup_arch()-> unflatten_device_tree()  // 构建device_node树-> of_platform_default_populate() // 创建平台设备
    
  4. 驱动匹配

    // 驱动声明匹配表
    static const struct of_device_id my_drv_ids[] = {{ .compatible = "vendor,my-device" },{}
    };// 平台驱动注册
    platform_driver_register(&my_driver);
    

五、高级应用:设备树覆盖(Overlay)实战

Overlay框架图:
写入路径
基础DTB
运行时内存
Overlay DTBO
用户空间
sys/kernel/config/device-tree/overlays
合并设备树
内核生效

全志D1开发板添加PWM设备

// pwm-overlay.dts
/dts-v1/;
/plugin/;&pio {pwm7_pin: pwm7 {pins = "PD22";function = "pwm7";};
};&pwm {pinctrl-names = "default";pinctrl-0 = <&pwm7_pin>;status = "okay";
};

加载流程

# 编译overlay
dtc -@ -I dts -O dtb -o pwm7.dtbo pwm-overlay.dts# 加载overlay
mkdir /config/device-tree/overlays/pwm7
cat pwm7.dtbo > /config/device-tree/overlays/pwm7/dtbo

六、设备树与传统开发模式对比

架构差异图:
设备树架构
通用内核
硬件H1
硬件H2
DTB1
DTB2
传统架构
内核镜像K1
硬件H1
硬件H2
内核镜像K2
包含板级代码
包含板级代码
开发流程对比表:
阶段传统模式设备树模式
硬件变更修改内核源码,重新编译修改.dts,单独编译DTB
驱动获取参数从platform_data结构体读取通过OF API解析设备树节点属性
多板卡支持每个板卡需独立内核镜像单一内核+不同DTB文件
外设扩展修改内核并重新编译动态加载DT Overlay

驱动代码对比

// 传统模式(硬编码)
struct mydev_platform_data {u32 clock_rate;u8 mode;
};static struct mydev_platform_data board_data = {.clock_rate = 50000000,.mode = 0x2,
};// 设备树模式
const struct of_device_id mydev_ids[] = {{ .compatible = "vendor,mydev" },{}
};static int mydev_probe(struct platform_device *pdev)
{struct device_node *np = pdev->dev.of_node;u32 clock_rate;u8 mode;of_property_read_u32(np, "clock-frequency", &clock_rate);of_property_read_u8(np, "operating-mode", &mode);
}

七、设备树设计最佳实践

  1. 分层设计原则

    ├── arch/
    │   └── arm/
    │       └── boot/
    │           └── dts/
    │               ├── vendor-soc.dtsi  // SoC通用定义
    │               ├── vendor-board.dts // 基础板级
    │               └── variants/
    │                   ├── board-1.dts  // 派生版本1
    │                   └── board-2.dts  // 派生版本2
    
  2. 兼容性声明规范

    // 精确到具体型号
    compatible = "ti,bq25601", "ti,bq25600";// 芯片系列通用
    compatible = "nvidia,tegra210-i2c";
    
  3. 引脚控制设计

    &i2c1 {pinctrl-names = "default", "sleep";pinctrl-0 = <&i2c1_pins_a>;pinctrl-1 = <&i2c1_pins_b>;status = "okay";
    };
    

总结:设备树的技术本质与价值

设备树通过结构化数据描述(DTS)、标准化编译链(DTC)、运行时解析框架(OF API)三位一体的设计,实现了:

  1. 硬件抽象层

    物理硬件
    设备树描述
    内核通用驱动
    用户空间
  2. 核心价值点

    • 解耦性:硬件描述与内核代码分离
    • 可扩展性:Overlay支持动态配置
    • 可维护性:减少80%板级特定代码
    • 标准化:跨ARM架构统一硬件接口
  3. 性能数据

    • 内核镜像大小减少:35-60%
    • 启动时间减少:15-30% (省去硬编码初始化)
    • 支持硬件变体数量:无限扩展
http://www.xdnf.cn/news/17444.html

相关文章:

  • 算术运算符指南
  • 如何用分析方法解决工作中的问题?
  • Day11 原理篇
  • 滚动条开始滚动时,左侧导航固定,当左侧内容触底到footer时左侧内容取消固定并跟随滚动条滚动
  • 【Python 小脚本·大用途 · 第 2 篇】
  • 女子试穿4条裤子留下血渍赔50元引争议:消费责任边界在哪?
  • 【星闪】Hi2821 | UART通用异步收发器 + 串口中断收发例程
  • 【人工智能99问】BERT的原理什么?(23/99)
  • 开启单片机
  • 编程基础之多维数组——矩阵交换行
  • 【YOLOv8改进 - C2f融合】C2f融合Outlook Attention:将细粒度特征编码到 token 中, 提高在图像分类和语义分割等任务中的性能
  • 【算法题】:斐波那契数列
  • 【Python】常用内置模块
  • 安全运维工具链全解析
  • Android快速视频解码抽帧FFmpegMediaMetadataRetriever,Kotlin(2)
  • 大模型开发工具的汇总
  • SQL Server从入门到项目实践(超值版)读书笔记 23
  • cursor, vscode黄色波浪线警告问题
  • 从零到精通:嵌入式BLE开发实战指南
  • 计算机网络:(十四)传输层(下)详细讲解TCP报文段的首部格式,TCP 可靠传输的实现与TCP 的流量控制
  • Mybatis和MybatisPlus的对比区分理解法
  • 基于 RabbitMQ 死信队列+TTL 实现延迟消息+延迟插件基本使用
  • 给AI装上“翻译聚光灯”:注意力机制的机器翻译革命
  • Docker 镜像常见标签(如 `标准`、`slim`、`alpine` 和 `noble`)详细对比
  • 编程基础之字符串——统计数字字符个数
  • TypeScript 中的as const是什么?
  • React:useEffect 与副作用
  • token危机解决?扩散模型数据潜力3倍于自回归,重训480次性能仍攀升
  • 浏览器CEFSharp88+X86+win7 之多页面展示(四)
  • LLaMA-Adapter Efficient Fine-tuning of Language Models with Zero-init Attention