一、GPIO基本概念
1.1什么是GPIO?
GPIO(General Purpose Input/Output,通用输入输出)是嵌入式系统中最基础的外设接口。每个GPIO引脚可以被配置为:
•输入模式:读取外部信号(如按键、传感器)
•输出模式:控制外部设备(如LED、继电器)
•中断模式:检测边沿变化触发中断
1.2 RK3576 GPIO资源
RK3576芯片共有5组GPIO(GPIO0~GPIO4),每组包含32个引脚(A0-A7, B0-B7, C0-C7, D0-D7)。
从设备树可以看到:
gpio0 = &gpio0; gpio1 = &gpio1; gpio2 = &gpio2; gpio3 = &gpio3; gpio4 = &gpio4;
1.3 GPIO命名规则
RK平台使用GPIOx_PYz的命名方式:
•x: GPIO组号(0-4)
•Y:端口(A、B、C、D)
•z:引脚号(0-7)
例如:GPIO0_PB4表示GPIO0组的B端口第4号引脚
二、GPIO工作原理
2.1内部结构
2.2工作模式
模式 |
说明 |
典型应用 |
输入模式 |
高阻态,读取外部电平 |
按键检测 |
输出模式 |
驱动外部电路 |
LED控制 |
中断模式 |
边沿/电平触发 |
事件通知 |
复用模式 |
作为其他功能(UART/I2C等) |
引脚复用 |
三、GPIO设备树配置
3.1在设备树中添加GPIO节点
编辑设备树文件(如ido-evb7609-v1a.dtsi):
// 定义 LED 设备节点 / { leds: leds { status = "okay"; compatible = "gpio-leds"; pinctrl-names = "default"; pinctrl-0 = <&leds_gpio>; work_led: work { gpios = <&gpio4 RK_PC7 GPIO_ACTIVE_HIGH>; linux,default-trigger = "heartbeat"; }; hub_rst { gpios = <&gpio4 RK_PD0 GPIO_ACTIVE_HIGH>; default-state="on"; }; }; // USB 电源控制 cgpio:cgpios{ status = "okay"; compatible = "cust,cgpio"; usb_pwr { //SD-card、USB-A、Wi-Fi gpios = <&gpio0 RK_PB6 GPIO_ACTIVE_HIGH>; init-status = <1>; }; }; };
3.2 pinctrl引脚配置
&pinctrl { // LED 引脚配置 led_pins: led-pins { rockchip,pins = <0 RK_PB4 RK_FUNC_GPIO &pcfg_pull_none>; }; // 按键引脚配置 key_pins: key-pins { rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; }; };
3.3 GPIO上下拉配置详解
RK3576的GPIO支持多种上下拉配置,通过rockchip,pins属性的最后一个参数指定。
上下拉配置类型
配置 |
设备树值 |
说明 |
典型应用 |
上拉 |
&pcfg_pull_up |
引脚默认上拉到高电平 |
按键输入、I2C SDA/SCL |
下拉 |
&pcfg_pull_down |
引脚默认下拉到低电平 |
复位信号、使能信号 |
无上下拉 |
&pcfg_pull_none |
浮空输入,无上拉电阻 |
LED输出、GPIO输出 |
保持 |
&pcfg_pull_bus |
总线保持器 |
低功耗场景 |
实际设备树配置示例
&pinctrl { /* LED 引脚 - 无上拉(输出模式不需要) */ leds_gpio: leds-gpio { rockchip,pins = <4 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>, /* work_led */ <4 RK_PD0 RK_FUNC_GPIO &pcfg_pull_none>; /* hub_rst */ }; /* USB 电源 - 无上拉 */ usb_pwr: usb-pwr { rockchip,pins = <0 RK_PB6 RK_FUNC_GPIO &pcfg_pull_none>; }; /* 耳机检测 - 上拉(按键检测) */ hp_det: hp-det { rockchip,pins = <3 RK_PB0 RK_FUNC_GPIO &pcfg_pull_up>; }; /* WiFi 唤醒 - 下拉 */ wifi_host_wake_irq: wifi-host-wake-irq { rockchip,pins = <0 RK_PB0 RK_FUNC_GPIO &pcfg_pull_down>; }; /* 按键输入 - 上拉 */ adc_keys_pins: adc-keys-pins { rockchip,pins = <0 RK_PA0 RK_FUNC_GPIO &pcfg_pull_up>; }; /* I2C 引脚 - 上拉(I2C 标准需要) */ i2c2m0_xfer: i2c2m0-xfer { rockchip,pins = <1 RK_PB3 9 &pcfg_pull_up>, /* i2c2_sda_m0 */ <1 RK_PB4 9 &pcfg_pull_up>; /* i2c2_scl_m0 */ }; };
上下拉选择原则
注意事项
1.输出模式:通常使用&pcfg_pull_none,因为GPIO输出是推挽驱动
2.输入按键:必须使用&pcfg_pull_up,确保按键未按下时读到高电平
3.I2C总线:必须使用&pcfg_pull_up,I2C是开漏输出需要上拉电阻
4.中断引脚:根据触发方式选择,上升沿触发用下拉,下降沿触发用上拉
四、GPIO驱动代码示例
4.1内核空间GPIO操作
#include #include #include struct my_gpio_dev { int gpio_led; int gpio_key; }; static int my_gpio_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct my_gpio_dev *priv; int ret; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); if (!priv) return -ENOMEM; /* 从设备树获取 GPIO 描述符 */ priv->gpio_led = of_get_named_gpio(np, "led-gpios", 0); if (!gpio_is_valid(priv->gpio_led)) { dev_err(&pdev->dev, "Failed to get LED GPIO\n"); return priv->gpio_led; } /* 申请并配置 GPIO */ ret = devm_gpio_request_one(&pdev->dev, priv->gpio_led, GPIOF_OUT_INIT_LOW, "led"); if (ret) { dev_err(&pdev->dev, "Failed to request LED GPIO\n"); return ret; } /* 设置 GPIO 输出高电平(点亮 LED) */ gpio_set_value(priv->gpio_led, 1); /* 按键 GPIO 配置为输入 */ priv->gpio_key = of_get_named_gpio(np, "key-gpios", 0); ret = devm_gpio_request_one(&pdev->dev, priv->gpio_key, GPIOF_IN, "key"); if (ret) return ret; /* 读取 GPIO 输入值 */ int val = gpio_get_value(priv->gpio_key); dev_info(&pdev->dev, "Key value: %d\n", val); return 0; } static const struct of_device_id my_gpio_of_match[] = { { .compatible = "mycompany,my-gpio-device", }, { } }; static struct platform_driver my_gpio_driver = { .probe = my_gpio_probe, .driver = { .name = "my-gpio", .of_match_table = my_gpio_of_match, }, };
4.2 GPIO中断处理
static irqreturn_t gpio_irq_handler(intirq, void *dev_id) { struct my_gpio_dev *priv = dev_id; /* 消抖处理 */ priv->key_pressed = !priv->key_pressed; return IRQ_HANDLED; } static int setup_gpio_irq(struct platform_device *pdev, struct my_gpio_dev *priv) { int irq, ret; /* 将 GPIO 转换为 IRQ */ irq = gpio_to_irq(priv->gpio_key); if (irq < 0) return irq; /* 申请中断 */ ret = devm_request_irq(&pdev->dev, irq, gpio_irq_handler, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "gpio-key", priv); if (ret) dev_err(&pdev->dev, "Failed to request IRQ\n"); return ret; }
4.3用户空间GPIO操作(sysfs)
# 导出 GPIO(以 GPIO4_PA2 为例) # 计算 GPIO 编号:4 * 32 + 1 * 8 + 2 = 138 echo 138 > /sys/class/gpio/export # 设置方向为输出 echo out > /sys/class/gpio/gpio138/direction # 设置输出高电平(点亮 LED) echo 1 > /sys/class/gpio/gpio138/value # 设置输出低电平(熄灭 LED) echo 0 > /sys/class/gpio/gpio138/value # 释放 GPIO echo 138 > /sys/class/gpio/unexport
五、调试方法
5.1查看GPIO状态
# 查看 GPIO 占用情况 cat /sys/kernel/debug/gpio # 查看 pinmux 配置 cat /sys/kernel/debug/pinctrl/pinctrl-rockchip/pinmux-pins # 查看 pin 状态 cat /sys/kernel/debug/pinctrl/pinctrl-rockchip/pins
5.2常用调试命令
# 查看中断统计 cat /proc/interrupts | grep gpio # 使用 devmem 直接读取寄存器 devmem 0xFE740000 # GPIO0 基地址 # 使用 io 命令(如有) io -r -4 0xFE740000
六、常见问题
6.1 GPIO申请失败
•检查GPIO是否已被其他驱动占用
•查看设备树中的status = "disabled"是否未使能
6.2 GPIO输出无效
•确认pinctrl配置正确
•检查IO电压域是否正常
•确认GPIO未被复用为其他功能
6.3 GPIO中断不触发
•检查中断触发方式(上升沿/下降沿/双边沿/高电平/低电平)
•确认GPIO已正确配置为输入
•检查中断是否被正确映射
七、进阶学习
1.GPIO子系统:学习Linux的GPIO子系统架构
2.GPIO字符设备:使用/dev/gpiochip0接口
3.libgpiod:用户空间GPIO库
4.Device Tree:深入理解设备树语法和绑定文档
参考文档
•[RKDocs/common/gpio/](RKDocs/common/gpio/)
•[Documentation/devicetree/bindings/gpio/gpio.txt](kernel-6.1/Documentation/devicetree/bindings/gpio/gpio.txt)
•[Documentation/gpio/gpio.txt](kernel-6.1/Documentation/gpio/gpio.txt)
本教程适用于触觉智能RK3576)开发板Purple Pi OH2 ,基于Android 14 / Linux 6.1内核
- 随机文章
- 热门文章
- 热评文章
- 可持续方法论|上海涉外企业ESG新政如何优化ESG生态
- 六大消费季覆盖全年 “相聚上海”活动指南发布
- 春暖花开,近八成私募基金3月实现正收益
- 美元走强削弱美豆竞争力,大豆价格徘徊在四年低点附近
- Mysteel:需求端定价时,何类政策能够推动行情变化?
- 油价急跌3美元!业界有点懵,事实上盘面早有危险信号
- 投资者惊呼!这几国要联手干预汇市?后市展望如何?
- 和谐共生|解码“地球之肾”,中国湿地何以美出圈?
- 以色列引汇市波动,鲍威尔继续影响市场!下周哪些央行可能干预市场?
- 官宣!西安银行新任党委书记落定 由党委副书记、行长梁邦海出任
- 小学生磕掉牙,班主任第一时间把牙放进鲜奶?医生提醒
- 紧急召回!这一公司被约谈,事关电梯质量安全
- 创纪录水平!日元空头头寸暗示日元大幅反弹的可能性增加
- 1“赛事+”提升城市“流量” 陕西商洛拓经济发展新“赛道”
- 2“五一”临近 持基过节的投资者要注意这几点
- 3华发股份:成功入选“人民优选”品牌 五一黄金周热销30亿
- 4到2027年产业规模达到2000亿元 浙江发布历史经典产业高质量发展计划
- 5IDC:24Q1全球PC出货量恢复增长 达到疫情前水平
- 6钟鼓楼老街区的古都新事
- 7非常危险!女子摔成粉碎性骨折!又是因为洞洞鞋,夏天多人中招……
- 8金税四期试点上线,财税体制改革拉开帷幕!或有资金借道信创ETF基金(562030)逢跌进场布局
- 9初步数据:我国一季度经常账户顺差392亿美元
- 10“发现山西之美”TDC旅游发现者大会举办:共话文旅新生态 邀客体验新玩法
- 11国门“夫妻档” 国庆共坚守
- 12北交所一周审核动态:2家企业更新进展 胜业电气二轮问询回复中称家电头部客户对价格敏感度较低
- 13甘肃白银县域经济:从“一枝独秀”到“多点开花”
- 1小方制药两专利受让信披出错,产品挂网价申报出差池
- 2高考在即,如何拿出最好状态?这份“锦囊”请收好
- 3【央视快评】继续弘扬“爱国、革命”的黄埔精神 为同心共圆中国梦广泛凝心聚力
- 4EBC GROUP平台外汇行情播报|科技股疲态和过热情绪引起不安
- 5父母“上瘾”,凌晨3点都不睡!儿女一查账单惊呆了……
- 6我国最大海上公务执法船“海巡09”巡航惠州港
- 7星环科技:9月10日召开业绩说明会,投资者参与
- 8四川双江口水电站库周交通工程“8·18”较大坍塌事故调查报告公布
- 9红旗天工08正式上市 售价23.98万元起
- 10国证2000指数表现亮眼 景顺长城量化策略助力捕获超额收益
- 112025年华北地区联合招聘活动在京举办
- 12小摩:料宁德时代(03750)股价短期或回调 目标价400港元 维持“增持”评级
- 139月首周港股三大指数收涨 机构对后续持乐观态度,9月首周港股三大指数收涨 机构对后续持乐观态度




