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 开漏接地
posted @ 2026-04-16 11:11  r5ett  阅读(74)  评论(0)    收藏  举报