linux驱动中的desc_to_gpio函数详解

在Linux内核的GPIO子系统中,desc_to_gpio函数用于将GPIO描述符(gpio_desc)转换为全局唯一的GPIO编号。以下是该函数的详细解析:


1. 函数原型

int desc_to_gpio(const struct gpio_desc *desc);
  • 参数desc(指向gpio_desc的指针)
  • 返回值
    • 成功时返回全局GPIO编号(整数,如105)。
    • 失败时返回负数错误码(如-EINVAL表示无效描述符)。

2. 核心作用

  • 编号转换:将抽象的gpio_desc转换为全局GPIO编号,便于:
    • 调试时输出人类可读的编号。
    • 与遗留代码或某些子系统(如pinctrl)交互。
  • 内部实现

    static inline int desc_to_gpio(const struct gpio_desc *desc)
    {
        if (!desc || !desc->chip || !desc->chip->base)
            return -EINVAL;
        return desc->chip->base + desc->offset;
    }
    • 通过desc->chip->base(控制器起始编号)和desc->offset(引脚在控制器内的偏移量)计算全局编号。

3. 典型使用场景

(1) 调试输出

struct gpio_desc *led_gpio = gpiod_get(dev, "led", GPIOD_OUT_HIGH);
if (!IS_ERR(led_gpio)) {
    int gpio_num = desc_to_gpio(led_gpio);
    dev_info(dev, "LED GPIO number: %d\n", gpio_num);
}
(2) 与pinctrl子系统交互

// 获取GPIO编号后配置引脚复用
int gpio = desc_to_gpio(led_gpio);
if (gpio >= 0) {
    pinctrl_gpio_direction_output(pmx, gpio);
}

4. 关键注意事项

(1) 避免硬编码全局编号
  • 风险:全局编号是动态分配的(由内核根据gpio_chip注册顺序决定),不同系统或不同启动时可能不同。
  • 正确做法:始终通过gpio_desc操作GPIO,仅在必要时(如调试)使用desc_to_gpio
(2) 错误处理
  • 检查返回值

    int gpio_num = desc_to_gpio(invalid_desc);
    if (gpio_num < 0) {
        dev_err(dev, "Invalid GPIO descriptor\n");
    }
(3) 性能考量
  • 直接使用描述符更高效gpio_desc已包含所有必要信息,频繁调用desc_to_gpio可能增加开销。

5. 反向操作:gpio_to_desc

  • 函数原型

    struct gpio_desc *gpio_to_desc(unsigned gpio);

  • 作用:将全局GPIO编号转换为gpio_desc,用于安全操作引脚。
  • 示例

    struct gpio_desc *desc = gpio_to_desc(105);
    if (!IS_ERR(desc)) {
        gpiod_set_value(desc, 1);
    }

6. 总结

函数方向作用典型场景
desc_to_gpio描述符 → 编号获取全局GPIO编号(调试/兼容性)日志输出、遗留代码交互
gpio_to_desc编号 → 描述符安全操作GPIO(推荐方式)驱动主体逻辑

最佳实践

  • 优先使用gpio_desc进行GPIO操作,避免直接操作全局编号。
  • 仅在必要时(如调试)使用desc_to_gpio,并严格处理错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值