Linux GPIO 子系统
从硬件看,GPIO(General Purpose Input/Output)是引脚的一种工作模式;从软件看,它就是一条数字线:可配置为输入或输出,电 平只有高 / 低两种状态。
内核 GPIO 子系统提供申请、配置方向、读写电平、去抖、映射为 IRQ 等能力。使用前应先向内核申请所有权,避免多个驱动争用同一引脚。
两套接口
| 接口 | 特点 | 建议 |
|---|---|---|
| 整数编号接口(legacy) | GPIO 用 unsigned 编号标识 | 已过时,仅维护旧代码时接触 |
| 描述符接口(descriptor / gpiod) | 用不透明描述符 + 专用 API | 新驱动首选 |
本文先讲仍常见于旧代码与教材中的整数接口,并在文末说明推荐方向。头文件:
#include <linux/gpio.h> /* legacy */
#include <linux/gpio/consumer.h> /* gpiod */
Legacy:申请与配置
static int gpio_request(unsigned gpio, const char *label);
void gpio_free(unsigned int gpio);
static bool gpio_is_valid(int number);
gpio:GPIO 编号label:内核 / debugfs(如/sys/kernel/debug/gpio)中的标签- 成功返回 0,失败返回负错误码
- 不确定编号是否有效时,可先用
gpio_is_valid()
申请成功后设置方向:
static int gpio_direction_input(unsigned gpio);
static int gpio_direction_output(unsigned gpio, int value);
输出方向的 value 表示方向生效后的初始电平。这些调用最终落到提供该 GPIO 的控制器驱动(struct gpio_chip)的回调上。
部分控制器支持输入去抖(平台相关):
static int gpio_set_debounce(unsigned gpio, unsigned debounce); /* 单位:ms */
备注
申 请与配置通常应在可能睡眠的上下文中完成(例如驱动 probe),不要在硬中断顶半部里做。
Legacy:读 / 写电平
访问前先判断控制器回调是否可能睡眠:
int gpio_cansleep(unsigned gpio);
读写 API不返回错误码,因此必须在申请 / 配置阶段检查返回值。
原子上下文(不可睡眠)
片内、纯 MMIO 的 GPIO 控制器通常不会睡眠,gpio_cansleep() 为 false。可在 IRQ 处理函数中使用:
static int gpio_get_value(unsigned gpio);
void gpio_set_value(unsigned int gpio, int value);
0 表示低,非 0 表示高。