GPIO子系统
1. GPIO 子系统的作用
GPIO 子系统的核心任务是 “硬件抽象”。它将底层不同 SoC 厂家的 GPIO 控制器寄存器操作隐藏起来,为驱动开发者提供一套统一的 API。
- 引脚管理:防止多个驱动程序同时操作同一个 GPIO 引脚造成冲突。
- 输入/输出控制:设置引脚方向,读取电平或输出高低电平。
- 中断映射:将 GPIO 引脚转换为虚拟中断号(IRQ),方便处理按键或传感器触发。
- 电气属性:配合 Pinctrl 子系统处理上下拉、驱动能力等。
2. 核心数据结构
2.1 struct gpio_desc (GPIO 描述符)
struct gpio_desc {
struct gpio_device *gdev; /* 指向该引脚所属的 GPIO 设备实例 */
unsigned long flags; /* 标志位:存储引脚方向、极性(Active Low)、是否被占用等状态 */
const char *label; /* 标签:通常记录哪个驱动程序申请了该 GPIO(用于 debugfs) */
const char *name; /* 引脚名称:来自设备树或硬件手册的特定名称 */
};
2.2 struct gpio_chip (GPIO 控制器)
struct gpio_chip {
const char *label; /* 控制器的名称(如 "gpiochip1" 或 "pinctrl-stm32") */
struct device *parent; /* 指向该控制器的父设备(通常是平台设备) */
struct module *owner; /* 拥有该驱动的模块指针 */
/* 核心操作函数表(钩子函数) */
int (*request)(struct gpio_chip *chip, unsigned offset); /* 申请引脚时的回调 */
void (*free)(struct gpio_chip *chip, unsigned offset); /* 释放引脚时的回调 */
int (*get_direction)(struct gpio_chip *chip, unsigned offset); /* 获取引脚当前方向 */
int (*direction_input)(struct gpio_chip *chip, unsigned offset); /* 设置为输入模式 */
int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value); /* 设置为输出并赋初值 */
int (*get)(struct gpio_chip *chip, unsigned offset); /* 读取物理电平值 */
void (*set)(struct gpio_chip *chip, unsigned offset, int value); /* 设置物理电平值 */
int (*to_irq)(struct gpio_chip *chip, unsigned offset); /* 将引脚偏移转换为中断号 */
int base; /* 该控制器的起始 GPIO 编号(旧的整数空间中使用) */
u16 ngpio; /* 该控制器管理的引脚总数(例如一个 Bank 有 32 个引脚) */
const char *const *names; /* 包含所有引脚名称的数组 */
bool can_sleep; /* 标志位:操作该硬件是否可能进入休眠(如通过 I2C 扩展的 GPIO) */
};
2.3 struct gpio_device (内部设备)
struct gpio_device {
int id; /* 该 GPIO 设备的唯一标识 ID */
struct device dev; /* 继承自内核标准设备模型,用于在 /dev 下创建节点 */
struct cdev chrdev; /* 字符设备结构,用于用户态通过 ioctl (GPIO V2) 控制 */
struct list_head list; /* 用于将当前设备挂载到内核全局 gpio_devices 链表中 */
struct gpio_chip *chip; /* 指向具体的硬件操作结构体(即上面提到的 gpio_chip) */
struct gpio_desc *descs; /* 指向该设备下所有描述符的数组(长度为 chip->ngpio) */
int base; /* 全局范围内的起始编号 */
u16 ngpio; /* 拷贝自 chip->ngpio,引脚总数 */
const char *label; /* 拷贝自 chip->label */
void *data; /* 存储私有数据指针 */
};
| 结构体 | 角色 | 核心意义 | 作用域 |
|---|---|---|---|
gpio_desc |
引脚名片 | 描述 单一引脚 的逻辑状态(逻辑电平、方向)。 | 驱动消费者 (Consumer) |
gpio_chip |
硬件手册 | 定义 如何操作寄存器(读、写、设方向)。 | 芯片原厂 (Provider) |
gpio_device |
管理中枢 | 维护 芯片与引脚的对应关系,处理用户态接口。 | GPIO 核心层 (Core) |
3. 常用函数与宏 (API 手册)
3.1 struct gpio_desc *devm_gpiod_get(struct device *dev, const char *con_id, enum gpiod_flags flags)
作用:根据设备树属性申请一个 GPIO。带 devm_ 前缀,资源随设备生命周期自动管理。
参数:
- dev:申请资源的设备指针。
- con_id:连接 ID。对应 DTS 中的前缀,如 con_id 为 "reset",则匹配 reset-gpios。如果 DTS 中直接叫 gpios,则传 NULL。
- flags:初始配置标志(如 GPIOD_OUT_LOW, GPIOD_IN)。
返回值:
- 成功:返回 gpio_desc 指针。
- 失败:返回错误指针(需用 IS_ERR() 检查)。
3.2 void devm_gpiod_put(struct device *dev, struct gpio_desc *desc)
作用:显式释放已申请的 GPIO 描述符。
参数:
- dev:拥有该资源的设备指针。
- desc:要释放的 GPIO 描述符。
3.3 int gpiod_direction_input(struct gpio_desc *desc)
作用:将指定的 GPIO 引脚配置为输入模式。
参数:desc 目标引脚描述符。
返回值:成功返回 0,失败返回负数错误码。
3.4 int gpiod_direction_output(struct gpio_desc *desc, int value)
作用:将指定的 GPIO 引脚配置为输出模式,并设置初始电平。
参数:
- desc:目标引脚描述符。
- value:初始逻辑电平(0 或 1)。
返回值:成功返回 0,失败返回负数错误码。
3.5 int gpiod_get_value(const struct gpio_desc *desc)
作用:获取引脚的当前逻辑电平。
参数:desc 引脚描述符。
返回值:返回 0 或 1。
3.6 void gpiod_set_value(struct gpio_desc *desc, int value)
作用:设置引脚的逻辑电平。
参数:
- desc:引脚描述符。
- value:要设置的逻辑电平。
3.7 void gpiod_set_raw_value(struct gpio_desc *desc, int value)
作用:设置引脚的物理电平。
参数:value 为物理高低电平。
3.8 int gpiod_to_irq(const struct gpio_desc *desc)
作用:将 GPIO 描述符映射为 Linux 系统的虚拟中断号。
参数:desc 引脚描述符。
返回值:
- 成功:返回正整数(中断号),可直接传给 request_irq。
- 失败:返回负数错误码。
4. 常用宏
4.1 GPIOD_IN
作用:将 GPIO 设置为输入模式。
场景:按键、传感器中断引脚、状态检测引脚。
特点:这是最基础的配置。如果是用于中断,通常拿到描述符后,紧接着会调用 gpiod_to_irq。
4.2 GPIOD_OUT_LOW
作用:设置为输出模式,并初始化为逻辑低电平 (Logic 0)。
逻辑说明:
- 如果设备树(DTS)配了 GPIO_ACTIVE_HIGH,物理输出为 0V。
- 如果 DTS 配了 GPIO_ACTIVE_LOW,物理输出为 高电平 (VCC)。
场景:用于控制 LED 灭、关闭使能信号、或者初始化时保持复位状态。
4.3 GPIOD_OUT_HIGH
作用:设置为输出模式,并初始化为逻辑高电平 (Logic 1)。
逻辑说明:
- 如果 DTS 配了 GPIO_ACTIVE_HIGH,物理输出为 高电平 (VCC)。
- 如果 DTS 配了 GPIO_ACTIVE_LOW,物理输出为 0V。
场景:点亮 LED、打开电源使能、让芯片退出复位状态。
4.4 GPIOD_OUT_LOW_OPEN_DRAIN
作用:设置为开漏输出 (Open Drain) 模式,并初始化为逻辑低电平。
原理:引脚内部只接 N 管到地。输出 0 时引脚接地;输出 1 时引脚呈高阻态,依赖外部上拉电阻拉高。
场景:I2C 总线、多个设备共享的中断线、或者需要电平转换的信号线。
| 宏名称 | 方向 | 逻辑值 | 物理行为(假设 Active High) |
|---|---|---|---|
GPIOD_IN |
输入 | N/A | 高阻态/读模式 |
GPIOD_OUT_LOW |
输出 | 0 | 拉低到地 |
GPIOD_OUT_HIGH |
输出 | 1 | 拉高到 VCC |
GPIOD_OUT_LOW_OPEN_DRAIN |
输出 | 0 | 开漏接地 |

浙公网安备 33010602011771号