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

Linux内核v5.4与v6.1间GPIO管理API变更问题咨询

Linux Kernel 5.4到6.1的GPIO管理API核心变更及适配方案

你的问题核心是legacy GPIO子系统API在6.1内核中已被逐步弃用,且默认配置可能禁用了相关兼容支持,导致原gpio_request()、gpio_export()等函数看似“生效”但实际无作用。以下是关键变更点及适配建议:

1. Legacy GPIO API的弃用状态

  • 5.4内核中,gpio_request()、gpio_direction_output()等属于legacy GPIO API,仍被广泛支持;但在6.1内核中,这类API已被标记为deprecated(已弃用),部分CONFIG选项默认关闭了兼容支持(如CONFIG_GPIO_SYSFS,对应gpio_export()依赖的sysfs GPIO接口)。
  • 若强制使用legacy API,需确保内核配置中开启CONFIG_LEGACY_GPIO和CONFIG_GPIO_SYSFS,但官方不推荐长期依赖。

2. 核心API替换(Descriptor-based GPIO子系统)

6.1内核推荐使用基于GPIO描述符(gpiod)的新API,替代所有legacy函数:

Legacy API函数替代的gpiod函数说明
gpio_request(gpio, label)gpiod_get(dev, con_id, flags)通过设备(或NULL表示全局)、连接ID(如设备树属性)获取GPIO描述符
gpio_request_one(gpio, flags, label)gpiod_get(dev, con_id, flags)直接在flags中指定方向/初始电平,无需额外调用方向设置函数
gpio_direction_output(gpio, value)gpiod_direction_output(gpiod, value)设置GPIO为输出模式并指定初始电平
gpio_set_value(gpio, value)gpiod_set_value(gpiod, value)设置输出GPIO电平
gpio_get_value(gpio)gpiod_get_value(gpiod)获取输入GPIO电平
gpio_export(gpio, direction_may_change)gpiod_export(gpiod, direction_may_change)导出GPIO到sysfs(不推荐,sysfs GPIO已弃用)
gpio_request_irq(gpio, irq_flags, handler, dev_id, label)gpiod_request_irq(gpiod, irq_flags, handler, dev_id, label)申请GPIO中断

3. 关键适配细节

(1)GPIO编号方式变化

Legacy API依赖全局GPIO编号(如BBB上的60、49等),但新的gpiod API不推荐硬编码全局编号,建议通过**设备树(Device Tree)**获取GPIO:

  • 在设备树中为驱动节点添加GPIO属性,例如:
    my_driver_node {
        compatible = "my,vendor-driver";
        led-gpios = <&gpio1 28 GPIO_ACTIVE_HIGH>; // BBB上的GPIO60对应gpio1组第28号
        key-gpios = <&gpio0 30 GPIO_ACTIVE_LOW>;
    };
    
  • 驱动中通过连接ID(con_id)获取:
    struct gpio_desc *led_gpiod = gpiod_get(dev, "led", GPIOD_OUT_LOW);
    struct gpio_desc *key_gpiod = gpiod_get(dev, "key", GPIOD_IN);
    if (IS_ERR(led_gpiod) || IS_ERR(key_gpiod)) {
        // 错误处理,返回对应的错误码
        return PTR_ERR(led_gpiod);
    }
    

(2)错误处理逻辑变化

Legacy API返回0/-errno表示成功/失败;gpiod API返回struct gpio_desc*指针,失败时返回ERR_PTR(errno),需用IS_ERR()检查:

struct gpio_desc *gpiod = gpiod_get(NULL, "gpio60", GPIOD_OUT_LOW);
if (IS_ERR(gpiod)) {
    pr_err("Failed to get GPIO: %ld\n", PTR_ERR(gpiod));
    return PTR_ERR(gpiod);
}

(3)sysfs GPIO接口的弃用

gpio_export()依赖的sysfs GPIO接口在6.1内核中已被标记为弃用,官方推荐使用libgpiod用户空间库(工具如gpiodetect、gpioinfo、gpioset)替代直接操作sysfs节点。若必须保留导出功能,需确保内核开启CONFIG_GPIO_SYSFS,并使用gpiod_export()替代gpio_export()。

4. 适配示例(原代码改造)

原5.4内核代码(legacy API)

#include <linux/gpio.h>

#define LED_GPIO 60
#define KEY_GPIO 49

static int __init my_driver_init(void) {
    int ret;
    // 请求LED GPIO
    ret = gpio_request(LED_GPIO, "my_led");
    if (ret) return ret;
    gpio_direction_output(LED_GPIO, 0);
    gpio_export(LED_GPIO, false);
    
    // 请求按键GPIO
    ret = gpio_request(KEY_GPIO, "my_key");
    if (ret) goto err_led;
    gpio_direction_input(KEY_GPIO);
    gpio_export(KEY_GPIO, false);
    
    return 0;
err_led:
    gpio_free(LED_GPIO);
    return ret;
}

适配6.1内核的代码(gpiod API)

#include <linux/gpio/consumer.h>

static struct gpio_desc *led_gpiod;
static struct gpio_desc *key_gpiod;

static int __init my_driver_init(void) {
    // 通过全局GPIO编号获取(不推荐,建议用设备树)
    led_gpiod = gpiod_get(NULL, "gpio60", GPIOD_OUT_LOW);
    if (IS_ERR(led_gpiod)) {
        pr_err("Failed to get LED GPIO: %ld\n", PTR_ERR(led_gpiod));
        return PTR_ERR(led_gpiod);
    }
    gpiod_export(led_gpiod, false);

    key_gpiod = gpiod_get(NULL, "gpio49", GPIOD_IN);
    if (IS_ERR(key_gpiod)) {
        pr_err("Failed to get KEY GPIO: %ld\n", PTR_ERR(key_gpiod));
        goto err_led;
    }
    gpiod_export(key_gpiod, false);

    return 0;
err_led:
    gpiod_put(led_gpiod);
    return PTR_ERR(key_gpiod);
}

static void __exit my_driver_exit(void) {
    gpiod_put(key_gpiod);
    gpiod_put(led_gpiod);
}

5. 额外注意事项

  • BeagleBone Black的6.1内核设备树可能调整了GPIO组的映射关系,硬编码全局编号可能导致GPIO对应错误,务必通过设备树属性获取。
  • 编译驱动时,需确保使用6.1内核的头文件,避免混合不同版本的API定义。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 05:04:59