Linux驱动开发(3)——设备树

一、驱动和设备分离

设备树可以统一管理设备,存放所有设备信息。

1、设备树文件类型:

  • dts:设备树源文件
  • dtsi:设备树头文件
  • dtb:编译好的二进制设备树文件,可直接使用
  • DTC:编译工具

2、设备树节点语法:

cs 复制代码
设备名{
    #address-cells = <1>;//每个地址所占字节
    #size-cells = <1>;//地址大小所占字节
   
    // 寄存器物理地址 + 长度  可以写多组
    reg = <地址1 长度1
           地址2 长度2
           地址3 长度3>;

    status = "okey";//设备可用状态
}

3、设备树函数接口:

1).函数:struct device_node *of_find_node_by_path(const char *path);

  • 功能:通过路径获得设备树节点
  • 参数:@path --- 设备树节点全路径(比如'/myled')

2).函数:int of_property_read_string(struct device_node *np, const char *propname, const char **out_string);

  • 功能:读取属性中的字符串值
  • 参数:@np --- 设备树节点,@propname --- 要读的属性名,@out_string --- 存放缓冲区

3).函数:void __iomem *of_iomap(struct device_node *np, int index);

  • 功能:设备树中的物理地址映射为内核虚拟地址
  • 参数:@np --- 设备树节点,@index --- reg数组的下标,从0开始)

二、驱动分层:

设备有4 类寄存器:

  • 引脚复用
  • 电气属性
  • GPIO 方向
  • GPIO 数据

将寄存器的配置移入设备树(Device Tree),由 Linux 内核的 pinctrl 子系统GPIO 子系统完成。

1、pinctrl子系统:操作iomuxrc的寄存器

1).pinctrl方案定义

cs 复制代码
pinctrl_myled:myledgrp{//方案名:组名
    fsl,pins = <
        //引脚配置宏   电器属性参数
    >;
}

2).pinctrl方案使用

cs 复制代码
设备树节点{
    pinctrl-names = "default";//默认按照pinctrl方案定义配置
    pinctrl-0 = <&pinctrl方案名>;
};

2、GPIO子系统:操作GPIO的寄存器

cs 复制代码
设备树节点{
    gpio-led = <&gpio控制器编号 gpio引脚号 有效电平>;
};

1).函数:int of_get_named_gpio(struct device_node *np, const char *propname, int index);

  • 功能:从设备树节点中解析并获取指定GPIO硬件编号
  • 参数:@np --- 设备树节点,@propname --- GPIO子系统名,@index --- 方案编号,从0开始
  • 返回值:成功返回引脚编号,失败返回-1

2).函数:int devm_gpio_request(struct device *dev, unsigned gpio, const char *label);

  • 功能:或得单个GPIO描述符,设备卸载时自动释放
  • 参数:@dev --- 设备,@gpio --- 要占用的引脚编号,@label --- 标明占用资源的驱动

3).函数:int gpio_direction_output(unsigned gpio, int value);

  • 功能:将GPIO引脚设置为输出模式
  • 参数:@gpio --- 引脚编号,@value --- 初始电平

4).函数:int gpio_direction_input(unsigned gpio);

  • 功能:将GPIO引脚设置为输入模式

5).函数:int gpio_get_value(unsigned int gpio);

  • 功能:读取输入引脚电平

6).函数:void gpio_set_value(unsigned int gpio, int value);

  • 功能:设置输出引脚电平

三、Linux中断

Linux 内核有中断子系统,专门管理所有硬件中断,不用我们直接操作寄存器配置中断。中断子系统分为:顶半部 + 底半部。

顶半部:

  • 硬件一触发中断立刻执行
  • 执行时间必须很短,只做最简单的事:标记中断、读取按键电平
  • 不能延时、不能睡眠、不能做耗时操作

底半部:

  • 耗时、复杂的任务挪到底半部执行
  • 顶半部快速退出,不占用 CPU,提高系统响应速度
  • 常见实现:工作队列、tasklet 等
cs 复制代码
设备节点{
    interrupt-parent = <&gpio1>;//中断控制器
    interrupts = <15 IRQ_TYPE_EDGE_FALLING>;//触发方式,例如15下降沿触发
};
相关推荐
Dust-Chasing12 小时前
Claude Code源码剖析 - Phase3
开发语言·人工智能·学习
XS03010612 小时前
并发编程三
开发语言·c#
idingzhi12 小时前
A股量化策略日报(2026年05月22日)
android·开发语言·python·kotlin
来恩100312 小时前
jQuery选择器
前端·javascript·jquery
前端繁华如梦12 小时前
树上挂苹果还是挂玻璃球?Three.js 程序化果实的完整实现指南
前端·javascript
江上清风山间明月12 小时前
如何将python开发的window应用打包成exe
开发语言·python·exe·打包
SXJR13 小时前
Java中的Cross-Encoder模型解决方案
java·开发语言
彦为君13 小时前
JavaSE-11-BIO/NIO/AIO(多人聊天室)
java·开发语言·python·ai·nio
CDwenhuohuo13 小时前
优惠券组件直接用 uview plus
前端·javascript·vue.js
为何创造硅基生物13 小时前
C 语言 typedef 结构体私有化
c语言·开发语言·算法