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

Linux kernel devm_gpiod_get()函数详解

devm_gpiod_get() 是 Linux 内核中用于通过设备树(Device Tree)获取 GPIO 描述符(GPIO Descriptor)​的设备资源管理(Managed Device Resources, Devres)函数。它是现代 Linux 驱动开发中推荐使用的 GPIO 操作接口,替代了传统的 gpio_request() 等函数,具备更安全、更简洁的资源管理能力。

核心作用

从设备树中解析指定的 GPIO 资源,生成一个 gpio_desc 结构体(GPIO 描述符),并通过 Devres 机制自动管理其生命周期(设备移除时自动释放)。

函数原型

#include <linux/gpio/consumer.h>struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags);

参数说明

  1. ​**struct device *dev**​
    设备指针,表示当前要获取 GPIO 的设备(通常是驱动中 probe() 函数传入的 pdev)。内核通过此设备找到设备树中对应的 GPIO 节点。

  2. ​**const char *con_id**​
    GPIO 的“连接标识符”,用于在设备树中匹配具体的 GPIO 属性。

    • 若设备树中 GPIO 属性名为 gpios(最常见的通用情况),则 con_id 通常设为 NULL(表示默认的 gpios 属性)。
    • 若设备树中为 GPIO 定义了别名(如 reset-gpiosirq-gpios),则 con_id 应设为对应的名称(如 "reset""irq")。
  3. ​**enum gpiod_flags flags**​
    GPIO 的配置标志,用于指定方向、初始状态等。常见取值:

    enum gpiod_flags {GPIOD_ASIS	= 0,GPIOD_IN	= GPIOD_FLAGS_BIT_DIR_SET,GPIOD_OUT_LOW	= GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT,GPIOD_OUT_HIGH	= GPIOD_FLAGS_BIT_DIR_SET | GPIOD_FLAGS_BIT_DIR_OUT |GPIOD_FLAGS_BIT_DIR_VAL,GPIOD_OUT_LOW_OPEN_DRAIN = GPIOD_OUT_LOW | GPIOD_FLAGS_BIT_OPEN_DRAIN,GPIOD_OUT_HIGH_OPEN_DRAIN = GPIOD_OUT_HIGH | GPIOD_FLAGS_BIT_OPEN_DRAIN,
    };
    • GPIOD_IN:输入模式(不指定初始值)。
    • GPIOF_DIR_OUT:输出模式。
    • GPIOD_OUT_LOW:输出模式下初始电平为低。
    • GPIOD_OUT_HIGH:输出模式下初始电平为高。
    • GPIOD_OUT_LOW_OPEN_DRAIN:开漏输出模式下初始电平为低。
    • GPIOD_OUT_HIGH_OPEN_DRAIN:开漏输出模式下初始电平为高。

返回值

  • 成功:返回指向 gpio_desc 结构体的指针(有效 GPIO 描述符)。
  • 失败:返回 ERR_PTR(-errno)(如 -ENOENT 表示未找到 GPIO 资源,-EINVAL 表示参数错误等)。需用 IS_ERR() 宏检查是否为错误指针。

工作原理

  1. 设备树关联​:驱动通过 dev 参数关联到具体设备,内核根据设备的 of_node(设备树节点)查找 con_id 对应的 GPIO 属性(如 gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;)。
  2. 资源分配​:内核为该 GPIO 分配一个 gpio_desc 描述符,并根据 flags 配置其方向和初始状态。
  3. Devres 管理​:devm_ 前缀表示该资源由 Devres 机制管理。当设备被移除(如 remove() 函数调用或热拔插)时,内核会自动调用 gpiod_put() 释放该 GPIO 描述符,无需手动干预。

典型使用场景

在驱动的 probe() 函数中获取 GPIO 描述符,后续通过 gpio_desc 操作 GPIO(如设置方向、读写电平、注册中断等)。例如:

// 驱动 probe 函数示例
static int my_driver_probe(struct platform_device *pdev)
{struct gpio_desc *reset_gpio;int ret;// 获取名为 "reset" 的 GPIO(设备树中对应 reset-gpios)reset_gpio = devm_gpiod_get(&pdev->dev, "reset", GPIOD_OUT_HIGH);if (IS_ERR(reset_gpio)) {dev_err(&pdev->dev, "Failed to get reset GPIO: %ld\n", PTR_ERR(reset_gpio));return PTR_ERR(reset_gpio);}// 使用 GPIO(例如:拉高电平触发复位)gpiod_set_value_cansleep(reset_gpio, 1);// ... 其他初始化逻辑 ...return 0;
}// 无需手动释放 reset_gpio!Devres 自动处理

相关函数

  • ​**devm_gpiod_get_optional()**​:获取可选的 GPIO(设备树中可能不存在)。若 GPIO 不存在,返回 NULL(而非错误),适用于非必需的 GPIO(如调试引脚)。
  • ​**devm_gpiod_put()**​:手动释放 GPIO 描述符(通常无需调用,Devres 自动释放)。
  • ​**gpiod_direction_input()/gpiod_direction_output()**​:动态修改 GPIO 方向(需确保未被其他逻辑占用)。
  • ​**gpiod_get_value_cansleep()/gpiod_set_value_cansleep()**​:安全读写 GPIO 电平(支持睡眠,适用于中断上下文外的场景)。

注意事项

  1. 设备树配置​:必须确保设备树中为设备正确配置了 GPIO 属性(如 gpios 或自定义名称的 *-gpios),否则 devm_gpiod_get() 会返回 -ENOENT 错误。
    示例设备树节点:

    my_device {compatible = "my,driver";reset-gpios = <&gpio0 12 GPIO_ACTIVE_HIGH>;  // con_id="reset"irq-gpios = <&gpio1 5 GPIO_ACTIVE_LOW>;      // con_id="irq"
    };
  2. 标志位组合​:flags 需正确组合方向和初始状态(如 GPIOD_OUT_HIGH),避免无效配置。

  3. 并发访问​:同一 gpio_desc 不可被多个驱动或同一驱动的不同实例重复获取,否则会导致资源冲突。

  4. 错误处理​:必须检查 devm_gpiod_get() 的返回值(通过 IS_ERR()),避免对空指针进行操作。

总结

devm_gpiod_get() 是现代 Linux 驱动开发中管理 GPIO 资源的标准接口,通过 Devres 机制自动管理生命周期,结合设备树实现了更清晰的硬件抽象。它替代了传统的 gpio_request() 等函数,是驱动开发中 GPIO 操作的首选方案。

http://www.lryc.cn/news/584844.html

相关文章:

  • 彻底解决JavaFx在Linux中文无法正常显示的问题(究其根本原因)
  • 飞书CEO谢欣:挑战巨头,打造AI新时代的Office
  • 锁的艺术:从Mutex到ReentrantLock,掌握并发编程的脉搏
  • 分布式系统高可用性设计-负载均衡与容错机制深度解析
  • Shader面试题100道之(81-100)
  • 模拟实现unordered_map
  • 如何使用 Python 删除 Excel 中的行、列和单元格 – 详解
  • 如何从0开始构建自己的第一个AI应用?(Prompt工程、Agent自定义、Tuning)
  • 格密码--数学基础--02基变换、幺模矩阵与 Hermite 标准形
  • AI金融风控:识别欺诈,量化风险的新利器
  • pandas销售数据分析
  • python 在 Linux CentOS 上安装 playwright 的完整步骤
  • Pandas:常见的转换函数(rename,set_index,reset_index)
  • MD2Doc转换器(基于Python)
  • [Reverse1] Tales of the Arrow
  • 飞算 JavaAI 深度体验:开启 Java 开发智能化新纪元
  • 闲庭信步使用图像验证平台加速FPGA的开发:第八课——图像数据的行缓存
  • Locust 负载测试工具使用教程
  • 为什么选择Selenium自动化测试?
  • [特殊字符]远程服务器配置pytorch环境
  • ajax和XMLHttpRequest以及fetch
  • STM32-DAC数模转换
  • day21——特殊文件:XML、Properties、以及日志框架
  • C#元组:从基础到实战的全方位解析
  • 实现在线预览pdf功能,后台下载PDF
  • 使用gdal读取shp及filegdb文件
  • 通过ETL工具,高效完成达梦数据库数据同步至数仓Oracle的具体实现
  • Primer Premier 5分子生物学引物设计软件 PCR引物设计工具
  • Swift 解 LeetCode 324:一步步实现摆动排序 II,掌握数组重排的节奏感
  • 智能文本抽取在合同管理实战应用