You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何gpiod_get_array()无法获取gpiod_count()识别到的GPIO描述符?

问题分析与解决方案

核心问题:GPIO属性放错了节点

你把my-gpios和my-gpio-names放在了&am33xx_pinmux(pinmux控制器节点)里,但gpiod_get系列函数是给功能设备节点用的,pinmux节点本身没资格请求GPIO。pinmux的职责只是配置引脚复用模式(比如把引脚设成GPIO功能),不是直接用GPIO的。

为啥gpiod_count能拿到数,但拿不到描述符?

  • gpiod_count只是单纯解析设备树属性里的GPIO数量,不做合法性校验,所以哪怕属性放错节点,它也能统计出个数。
  • devm_gpiod_get_array/devm_gpiod_get_index会做严格校验:检查节点是不是合法的GPIO使用者,pinmux节点不属于这类,直接返回错误。

修复步骤

1. 调整设备树结构

把my-gpios和my-gpio-names移到实际要用GPIO的功能设备节点里,同时在pinmux节点里加对应的引脚复用配置,确保这些引脚被设为GPIO功能:

&am33xx_pinmux {
    pinctrl-names = "default";
    // 配置引脚为GPIO功能的pinmux条目(偏移地址根据AM335X引脚手册调整)
    my_gpio_pins: my-gpio-pins {
        pinctrl-single,pins = <
            0x110 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpio2_4 */
            0x114 (PIN_INPUT_PULLUP | MUX_MODE7) /* gpio2_3 */
            0x11C (PIN_INPUT_PULLUP | MUX_MODE7) /* gpio2_0 */
        >;
    };
};

// 自定义一个功能设备节点,用来挂载GPIO属性
my_gpio_device: my-gpio-device {
    compatible = "my,gpio-device";
    pinctrl-names = "default";
    pinctrl-0 = <&my_gpio_pins>; // 绑定pinmux配置
    my-gpios = <&gpio2 4 GPIO_ACTIVE_HIGH>,
               <&gpio2 3 GPIO_ACTIVE_HIGH>,
               <&gpio2 0 GPIO_ACTIVE_HIGH>;
    my-gpio-names = "name1", "name2", "name3";
    status = "okay";
};

2. 调整驱动代码

让你的驱动绑定到上面的my-gpio-device节点(或者你实际要控制GPIO的设备节点),再调用gpiod系列函数就能正常拿描述符了:

// 假设dev是my-gpio-device对应的device结构体
int gpio_count, gpio_name_count;
struct gpio_descs *gpiodescs;
struct gpio_desc *desc;
int i;

gpio_count = gpiod_count(dev, "my");
if (gpio_count <= 0) {
    dev_err(dev, "没找到GPIO\n");
    return -ENODEV;
}

gpio_name_count = of_property_count_strings(dev->of_node, "my-gpio-names");
if (gpio_name_count != gpio_count) {
    dev_warn(dev, "GPIO数量和名称数量不匹配\n");
}

gpiodescs = devm_gpiod_get_array(dev, "my", GPIOD_OUT_LOW);
if (IS_ERR(gpiodescs)) {
    dev_err(dev, "获取GPIO数组失败:%ld\n", PTR_ERR(gpiodescs));
    return PTR_ERR(gpiodescs);
}

// 导出每个GPIO并关联名称
for (i = 0; i < gpiodescs->ndescs; i++) {
    char name[32];
    desc = gpiodescs->desc[i];
    
    if (gpiod_export(desc, false) < 0) {
        dev_warn(dev, "导出GPIO %d失败\n", i);
        continue;
    }
    
    if (of_property_read_string_index(dev->of_node, "my-gpio-names", i, name) == 0) {
        if (gpiod_export_link(dev, name, desc) < 0) {
            dev_warn(dev, "为GPIO %d创建名称链接失败\n", i);
        }
    }
}

额外说明

  • 导出后用gpioinfo就能看到这些GPIO标记为used,因为gpiod_get系列函数会把GPIO标记为内核驱动正在使用。
  • 要确保驱动和目标设备节点正确绑定,通过compatible属性匹配或者平台设备注册的方式都行。

内容的提问来源于stack exchange,提问作者Glen G

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 13:27:50