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下降沿触发
};
相关推荐
AC赳赳老秦4 小时前
OpenClaw+Power Apps 实战:自动生成 Power Apps 应用、连接 Excel 数据源
大数据·开发语言·python·serverless·excel·deepseek·openclaw
提笔了无痕4 小时前
如何用Go实现整套RAG流程
开发语言·后端·golang
(Charon)4 小时前
【C++ 面试高频基础:指针、引用、const、static、new/delete 总结】
java·开发语言
Yeats_Liao5 小时前
Feed流系统设计(三):数据模型与存储设计,从表结构到Redis收件箱
java·javascript·redis
我是真菜5 小时前
彻底理解js中的深浅拷贝
前端·javascript
2601_961875245 小时前
法考考试时间安排及科目|时间表|资料已整理
开发语言·c#·inverted-index·suffix-tree·sstable·r-tree·lsm-tree
AI科技星5 小时前
数术工坊第八卷:算力革命
c语言·开发语言·网络·量子计算·agi
geovindu5 小时前
go: Generators Pattern
开发语言·后端·设计模式·golang·生成器模式
码云骑士6 小时前
13-列表append的底层真相(上)-listobject源码中的预分配策略
开发语言·python
尽兴-7 小时前
4.1 智能体核心:Agent、Sub-Agent、ReAct、规划执行
前端·javascript·react.js·agent·react·subagent