GPIO 驱动与控制
1. 概述
1.1 功能简介
GPIO(General Purpose Input/Output)通用输入输出接口,是嵌入式系统中最基本的外设接口。RK3576 拥有丰富的 GPIO 资源,支持复用功能配置、中断触发、上下拉控制等特性。通过 GPIO 可以控制外部设备的电平状态(输出模式)或读取外部信号的电平状态(输入模式)。
1.2 应用场景
- LED 控制:通过 GPIO 输出高低电平控制 LED 灯亮灭
- 按键检测:通过 GPIO 输入模式检测按键状态
- 外设使能:控制外部芯片的使能引脚(EN)或复位引脚(RST)
- 中断信号:配置为中断模式,检测外部事件触发
- 模拟通信协议:软件模拟 I2C、SPI、1-Wire 等时序
1.3 工作原理
RK3576 的 GPIO 控制器通过 Pin-Ctrl 子系统进行引脚功能复用管理。每个引脚可以配置为 GPIO 模式或其他功能模式(如 I2C、UART、SPI 等)。GPIO 的内部结构包括:
- 方向控制寄存器(DDR):控制引脚为输入或输出模式
- 数据寄存器(DR):读取或设置引脚电平值
- 复用功能寄存器(IOMUX):配置引脚功能模式
- 驱动能力寄存器(DS):控制引脚输出驱动能力
- 上下拉寄存器(PU/PD):控制内部上拉或下拉电阻
RK3576 共有 5 组 GPIO 控制器(GPIO0~GPIO4),每组 32 个引脚,合计 160 个 GPIO。M4-R2 底板 40PIN 接口已引出大部分 GPIO,全部为 3.3V 电平。
详见 RK 官方文档:[《Rockchip_Developer_Guide_Linux_Pinctrl_CN.pdf》]
2. 硬件准备
2.1 硬件清单
| 组件 | 型号/规格 | 数量 | 备注 |
|---|---|---|---|
| 主控板 | C-3576BQ 核心板 + M4-R2 底板 | 1 | |
| 调试串口线 | USB 转 TTL(3.3V) | 1 | 波特率 1500000 |
| LED 模块 | 5mm 发光二极管 + 330Ω 限流电阻 | 1 | 或面包板搭建 |
| 杜邦线 | 母对母 | 若干 | |
| 按键模块(可选) | 轻触按键 | 1 | 用于输入检测 |
| 电源适配器 | 5V 电源适配器(Type-C 或 6pin 输入) | 1 | 空载最小 1000mA |
2.2 引脚连接
以 M4-R2 底板 40PIN 的 GPIO3_C1(Pin7)为例:
| 主控板引脚 | 外设引脚 | 功能说明 |
|---|---|---|
| GPIO3_C1(40PIN Pin7) | LED 正极(经 330Ω 电阻) | GPIO 输出控制 LED |
| GND(40PIN Pin9) | LED 负极 | 共地 |
| GPIO3_C1(40PIN Pin7) | 按键一端 | GPIO 输入检测 |
| GND(40PIN Pin9) | 按键另一端 | 共地 |
实际操作时应选择未被其他功能占用的 GPIO 引脚,M4-R2 底板 40PIN 引脚表见 40PIN 引脚定义。
2.3 硬件确认
确认 GPIO 引脚电压域正确(3.3V),避免烧毁引脚。M4-R2 底板 40PIN 接口为 3.3V 电平,外设 IO 电平不能高于 3.3V。
3. 软件准备
3.1 内核配置
RK3576 的 GPIO 驱动通常默认使能,无需额外配置。确认以下配置已启用:
CONFIG_GPIOLIB=y
CONFIG_GPIO_GENERIC=y
CONFIG_PINCTRL=y
CONFIG_PINCTRL_RK3576=y
CONFIG_OF_GPIO=y
CONFIG_PINCTRL_RK3576是 RK3576 专用的 Pin-Ctrl 驱动。
3.2 设备树
RK3576 的 GPIO 控制器在设备树中定义为 5 个节点(GPIO0~GPIO4):
gpio0: gpio@fdd60000 {
compatible = "rockchip,gpio-bank";
reg = <0x0 0xfdd60000 0x0 0x100>;
interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&cru PCLK_GPIO0>;
gpio-controller;
#gpio-cells = <2>;
gpio-ranges = <&pinctrl 0 0 32>;
interrupt-controller;
#interrupt-cells = <2>;
};以上节点地址为 RK 平台通用结构示例,具体寄存器基地址与中断号以实际发布的 RK3576 SDK 设备树为准(待板上确认)。
4. 操作步骤
4.1 通过 sysfs 控制 GPIO
4.1.1 查看可用 GPIO
# 查看 GPIO 芯片信息
cat /sys/class/gpio/gpiochip*/label
# 查看 GPIO 数量
ls /sys/class/gpio/gpiochip* | wc -l4.1.2 导出并控制 GPIO
# 导出 GPIO(以 GPIO3_C1 为例,编号需计算)
echo 97 > /sys/class/gpio/export # GPIO3_C1 = 3*32 + 2*8 + 1 = 97
# 设置方向为输出
echo out > /sys/class/gpio/gpio97/direction
# 输出高电平
echo 1 > /sys/class/gpio/gpio97/value
# 输出低电平
echo 0 > /sys/class/gpio/gpio97/value
# 释放 GPIO
echo 97 > /sys/class/gpio/unexportGPIO 编号计算公式:
组号 * 32 + 组内偏移。GPIO3_C1 = 3 * 32 + 2 * 8 + 1 = 97。
4.1.3 读取 GPIO 输入
# 导出并设置为输入
echo 97 > /sys/class/gpio/export
echo in > /sys/class/gpio/gpio97/direction
# 读取电平
cat /sys/class/gpio/gpio97/value
# 输出 0 或 14.2 通过 debugfs 查看 GPIO 状态
# 查看所有 GPIO 控制器的 pin 状态
cat /sys/kernel/debug/gpio
# 输出示例(以实际板卡为准):
# gpiochip0: GPIOs 0-31, parent: platform/fdd60000.gpio, GPIO0:
# gpio-0 ( |led-green ) out hi
# gpio-3 ( |usb-host-pwr-en ) out hi4.3 通过 pinctrl 查看引脚状态
# 查看引脚复用状态
cat /sys/kernel/debug/pinctrl/fdd60000.pinctrl/pinmux-pins
# 查看引脚可用状态
cat /sys/kernel/debug/pinctrl/fdd60000.pinctrl/pinsdebugfs 中的 pinctrl 路径与寄存器基地址相关,以上为示例路径,以实际板卡输出为准。
4.4 设备树中配置 GPIO
在设备树中使用 GPIO 的标准方式:
my_device {
compatible = "my,device";
// GPIO3_C1(40PIN Pin7),高电平有效
enable-gpios = <&gpio3 17 GPIO_ACTIVE_HIGH>;
// GPIO4_C7(40PIN Pin32,PWM0 复用),低电平有效
reset-gpios = <&gpio4 23 GPIO_ACTIVE_LOW>;
};RK3576 GPIO 编号规则:每组 GPIO 有 32 个 pin,编号为 0-31。GPIO3_C1 表示 GPIO3 的 C 组第 1 个 pin,即 3 * 32 + 2 * 8 + 1 = 97。
5. 代码详解
5.1 内核中 GPIO 驱动的注册
// RK3576 GPIO 控制器驱动(简化)
// drivers/pinctrl/pinctrl-rk3576.c
static struct rockchip_pin_bank rk3576_pin_banks[] = {
RK3576_PIN_BANK_FLAGS(0, 32, "gpio0"),
RK3576_PIN_BANK_FLAGS(1, 32, "gpio1"),
RK3576_PIN_BANK_FLAGS(2, 32, "gpio2"),
RK3576_PIN_BANK_FLAGS(3, 32, "gpio3"),
RK3576_PIN_BANK_FLAGS(4, 32, "gpio4"),
};
static struct rockchip_pinctrl_info rk3576_pinctrl_info = {
.pin_banks = rk3576_pin_banks,
.nr_banks = ARRAY_SIZE(rk3576_pin_banks),
};5.2 用户空间 GPIO 操作的内核调用链
用户空间 echo 97 > /sys/class/gpio/export
→ gpio_export()
→ gpio_request_one()
→ gpio_direction_output()
→ rockchip_gpio_direction_output()
→ 设置 GPIO 寄存器6. 常见问题
6.1 GPIO 被其他功能占用
现象: 导出 GPIO 时提示 busy 或设备树中 GPIO 已分配给其他设备
解决方案:
# 查看 GPIO 被谁占用
cat /sys/kernel/debug/gpio
# 查看 pinctrl 状态
cat /sys/kernel/debug/pinctrl/fdd60000.pinctrl/pinmux-pins在设备树中将占用该 GPIO 的设备节点 status 设为 "disabled"。
6.2 GPIO 编号计算错误
现象: 控制了错误的 GPIO 引脚
解决方案:
# 通过 debugfs 确认实际 GPIO 编号
cat /sys/kernel/debug/gpioRK3576 GPIO 编号规则:组号 * 32 + 组内偏移(A 组 0-7,B 组 8-15,C 组 16-23,D 组 24-31)。
6.3 GPIO 电压域不匹配
现象: GPIO 输出电平不正确,或外设工作异常
解决方案: 确认 GPIO 引脚的电压域(1.8V 或 3.3V),确保与外设电平匹配。M4-R2 底板 40PIN 为 3.3V 电平,具体电压域配置参考核心板规格书和底板原理图。
