GPIO 子系统全面解析:旧版 GPIO 编号 API 与新版 Descriptor API 对比与实战

支持作者新书《Yocto项目实战教程:高效定制嵌入式Linux系统》,点击京东购买

GPIO 子系统全面解析:旧版 GPIO 编号 API 与新版 Descriptor API 对比与实战

一、GPIO 子系统的基本概念

1. 什么是 GPIO?

GPIO(General Purpose Input/Output)即“通用输入输出”,是一种可通过软件控制的引脚,可用于读取电平(输入)或设置电平(输出)。在嵌入式系统中,GPIO 是最常见的外设控制手段之一。

在这里插入图片描述

2. 为什么要有 GPIO 子系统?

Linux 为不同硬件平台提供统一的软件接口抽象,GPIO 子系统是 Linux 内核为控制 GPIO 而设计的一个驱动子系统,它使得上层驱动程序可以不关心底层硬件差异。

在驱动开发中,GPIO 通常用于:

  • 控制 LED 状态
  • 读取按键输入
  • 控制设备的上电/复位
  • EEPROM 写保护(如 wp-gpios)等。

二、传统 GPIO 编号 API 与 Descriptor API 的演进

1. 传统方式(GPIO 编号 API)

传统方式以 int gpio_num 表示某个 GPIO 引脚,通过编号进行操作。

int wp_gpio = of_get_named_gpio(np, "wp-gpios", 0);
devm_gpio_request_one(dev, wp_gpio, GPIOF_OUT_INIT_HIGH, "eeprom-wp");

缺点:

  • 编号不具可移植性
  • 不易支持动态命名和状态追踪
  • 编号方式难以管理设备间的依赖

2. 现代方式(Descriptor API)

Descriptor API 使用 struct gpio_desc * 对 GPIO 引脚抽象,提供更清晰的语义和设备关系。

struct gpio_desc *wp_desc;
wp_desc = gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH);

优势:

  • 与设备绑定,具备更强的设备树兼容能力
  • 更安全,易于调试
  • 自动管理资源(通过 devm_ 系列函数)

三、两种 API 对比总结

对比维度编号 APIDescriptor API
表示方式int 类型 GPIO 编号struct gpio_desc * 指针
与设备关系松散强绑定:绑定 struct device
面向设备树兼容性差,需要手动解析完美支持 gpiod_get_optional()
自动释放资源需要手动释放使用 devm_ 系列自动释放
API 示例gpio_request() / of_get_named_gpio()gpiod_get() / gpiod_set_value()

四、实战:配置 EEPROM 的写保护 GPIO(以 at24.c 为例)

设备树配置

&i2c3 {
    eeprom@50 {
        compatible = "atmel,24c02";
        reg = <0x50>;
        wp-gpios = <&gpio4 17 GPIO_ACTIVE_LOW>; // 写保护引脚
    };
};

驱动代码(基于 Descriptor API)

struct gpio_desc *wp_desc;
wp_desc = gpiod_get_optional(dev, "wp", GPIOD_OUT_HIGH);
if (!IS_ERR_OR_NULL(wp_desc)) {
    dev_info(dev, "EEPROM WP GPIO 配置成功\n");
    gpiod_set_value(wp_desc, 0);  // 解除写保护
} else {
    dev_warn(dev, "未定义 WP 引脚\n");
}

五、关键概念讲解

1. gpiod_get_optional() 是做什么的?

  • 从设备树中解析 <gpio-name>-gpios 属性(如 “wp-gpios”)
  • 返回一个 GPIO 描述符(struct gpio_desc *
  • 如果未定义此属性,不报错,返回 NULL

适合对 GPIO 可选的场景(如 EEPROM 写保护引脚)

2. devm_ 系列函数的作用?

  • 自动释放资源,无需手动调用 gpio_free()
  • 与设备生命周期绑定

比如:

devm_gpio_request_one(dev, gpio_num, GPIOF_OUT_INIT_HIGH, "eeprom-wp");

3. gpio_desc 是什么?

  • 是 GPIO 的内核抽象封装结构,代替传统编号
  • 包含 GPIO 控制器信息、状态、电平、方向等

六、常见面试问答示例

问:你怎么理解新版 GPIO Descriptor API 的设计?

✅ 答:新版 Descriptor API 引入 gpio_desc * 结构体,代替原来的数字编号,更贴近设备的抽象模型。它与设备树结合更紧密,能更清晰地表示设备和 GPIO 的绑定关系,资源管理更安全,调试更方便。

问:什么时候使用 gpiod_get_optional()?

✅ 答:当某个 GPIO 并非设备工作所必需,比如 EEPROM 写保护引脚、可选 LED 控制引脚,可以使用 gpiod_get_optional(),避免在设备树未提供该属性时报错。

问:旧版 gpio_request() 和新版 gpiod_get() 有什么根本区别?

✅ 答:旧版直接基于编号管理 GPIO,无设备绑定,需手动释放;新版使用描述符结构绑定设备,支持资源自动管理,更加符合现代设备驱动架构。

七、练习建议与参考资源

推荐练习

  • 在已有驱动中查找 gpio_request(),尝试用 Descriptor API 替换
  • 编写一个简单平台设备,添加可选 GPIO 控制(如 LED、MUTE)
  • 阅读 drivers/gpio/ 目录下的核心 GPIO 控制器实现

推荐阅读

  • Linux 内核源码文档:Documentation/gpio/
  • LWN 文章《The new GPIO descriptor interface》
  • EEPROM 示例驱动:drivers/misc/eeprom/at24.c

📘。配套视频请见 B 站 “嵌入式 Jerry”。

支持作者新书《Yocto项目实战教程:高效定制嵌入式Linux系统》,点击京东购买

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值