一、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内核
- 随机文章
- 热门文章
- 热评文章
- 金价“疯”涨之谜 金价走势与实际利率“背离”
- IMAX与博纳影业集团扩展合作 新建3家激光影院
- 原广州军区司令员李希林上将逝世,享年94岁
- 黄金突破关键阻力?2432美元/盎司成为下一目标!
- EBC GROUP平台外汇行情播报|伊朗和委内瑞拉被点名 新制裁推升油价
- 塞纳河畔的旧书摊(环球走笔)
- 韩国就岸田文雄向靖国神社献祭品深表失望和遗憾
- 华林证券净利降九成,屡遭监管暴露内控缺陷
- 证监会党委理论学习中心组在《人民日报》发文表示 增强资本市场制度包容性 依法全面加强监管
- “疫苗茅”智飞生物暴跌15%!什么情况?多只明星基金已提前减仓
- 今晚强势返场!杭州人早点回家!阳光你真的不考虑销假吗?
- 重庆住房“换新购”实施近3个月:效果尚不明显
- 天齐锂业:境外少数股东收益暴增,SQM核心锂业务面临变动风险!
- 1“赛事+”提升城市“流量” 陕西商洛拓经济发展新“赛道”
- 2“五一”临近 持基过节的投资者要注意这几点
- 3华发股份:成功入选“人民优选”品牌 五一黄金周热销30亿
- 4到2027年产业规模达到2000亿元 浙江发布历史经典产业高质量发展计划
- 5钟鼓楼老街区的古都新事
- 6非常危险!女子摔成粉碎性骨折!又是因为洞洞鞋,夏天多人中招……
- 7IDC:24Q1全球PC出货量恢复增长 达到疫情前水平
- 8金税四期试点上线,财税体制改革拉开帷幕!或有资金借道信创ETF基金(562030)逢跌进场布局
- 9初步数据:我国一季度经常账户顺差392亿美元
- 10“发现山西之美”TDC旅游发现者大会举办:共话文旅新生态 邀客体验新玩法
- 11国门“夫妻档” 国庆共坚守
- 12北交所一周审核动态:2家企业更新进展 胜业电气二轮问询回复中称家电头部客户对价格敏感度较低
- 13甘肃白银县域经济:从“一枝独秀”到“多点开花”
- 1大裁员下,特斯拉两名顶级高管离职
- 2奇瑞将与欧洲高端品牌签署技术平台授权协议
- 32024中国长三角青年企业家交流大会在杭州举办
- 4雷克萨斯GX中东版 全部在售 2023款 2022款 2020款 2019款 2018款成都远卓名车雷克萨斯GX中东版团购钜惠20万 欢迎上门试驾
- 5零跑C16将搭载中创新航磷酸铁锂电池
- 6Q1净利微增7%,宁德时代股东总数较2023年年末减少10728户
- 7哪吒,需要背水一战
- 8“新”中有“机”!创新服务承接新流量 撬动消费升级
- 9非创始版SU7何时交付 小米:工厂生产爬坡 全力提高产能
- 10央媒评卧铺挂帘:谁买的票谁做主
- 11江西南昌首部“多规合一”国土空间总体规划获批
- 12方程豹旗舰硬派越野!豹8正式亮相:仰望U8“青春版”登场
- 13583家族/造型霸气 方程豹豹8量产版发布




