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下降沿触发
};
相关推荐
图码1 小时前
如何用多种方法判断字符串是否为回文?
开发语言·数据结构·c++·算法·阿里云·线性回归·数字雕刻
U盘失踪了1 小时前
python curl转python脚本
开发语言·chrome·python
charlie1145141912 小时前
Linux 字符设备驱动:cdev、设备号与设备模型
linux·开发语言·驱动开发·c
handler012 小时前
Linux 内核剖析:进程优先级、上下文切换与 O(1) 调度算法
linux·运维·c语言·开发语言·c++·笔记·算法
FQNmxDG4S2 小时前
Java泛型编程:类型擦除与泛型方法的应用场景
java·开发语言·python
我星期八休息2 小时前
IT疑难杂症诊疗室:AI时代工程师Superpowers进化论
linux·开发语言·数据结构·人工智能·python·散列表
热心网友俣先生2 小时前
2026年第二十三届五一数学建模竞赛C题超详细解题思路+各问题可用模型推荐+部分模型结果展示
c语言·开发语言·数学建模
01漫游者2 小时前
JavaScript函数与对象增强知识
开发语言·javascript·ecmascript
IGAn CTOU2 小时前
Java高级开发进阶教程之系列
java·开发语言