当前位置: 首页 > news >正文

RK3568 GPIO子系统

文章目录

  • 一、gpio子系统的概念
      • **GPIO 子系统概念讲解**
    • **1. GPIO 子系统的基本概念**
    • **2. GPIO 子系统的组成**
      • **2.1 GPIO 控制器(GPIO Controller)**
      • **2.2 GPIO 设备(GPIO Device)**
      • **2.3 GPIO 子系统 API**
    • **3. GPIO 设备树(Device Tree)配置**
    • **4. 用户空间访问 GPIO**
      • **4.1 旧的 sysfs 方式(已弃用)**
      • **4.2 使用 libgpiod(推荐)**
    • **5. GPIO 中断(IRQ)处理**
    • **6. GPIO 子系统的优势**
    • **总结**
  • 二、RK3568 GPIO命名规则
      • **RK3568 GPIO 命名规则解析**
        • **1. 命名格式**
        • **2. GPIO 编号计算**
        • **3. 实例解析**
        • **4. GPIO 在设备树中的表示**
        • **5. 复用模式(MUX 配置)**
        • **6. 总结**
  • 三、GPIO的两套控制函数
      • **Linux GPIO 子系统的两套 API:`gpio` 和 `gpiod`**
    • **1. `gpio` API(老版)**
      • **1.1 `gpio` API 主要函数**
      • **1.2 `sysfs` 方式(已废弃)**
    • **2. `gpiod` API(新版,推荐)**
      • **2.1 `gpiod` API 主要函数**
      • **2.2 `libgpiod`(用户空间)**
    • **3. `gpio` vs `gpiod` 对比**
    • **4. 设备树(Device Tree) GPIO 描述**
    • **5. 结论**


一、gpio子系统的概念

GPIO 子系统概念讲解

GPIO(General-Purpose Input/Output,通用输入/输出)是嵌入式系统和计算机架构中广泛使用的一种通用数字信号接口。Linux 内核提供了 GPIO 子系统,用于管理和控制 GPIO 资源,使驱动程序能够通过统一的接口访问 GPIO 设备。


1. GPIO 子系统的基本概念

GPIO 子系统的主要作用是提供一个标准化的接口,使不同的硬件平台可以以相同的方式访问 GPIO 资源。它主要用于:

  • 输入(如读取按钮状态)
  • 输出(如控制 LED、继电器等)
  • 中断(GPIO 触发的事件,如按键按下时触发中断)
  • 复用功能(GPIO 可作为 I2C、SPI、PWM 等功能引脚)

2. GPIO 子系统的组成

Linux 内核的 GPIO 子系统主要由以下几个部分组成:

2.1 GPIO 控制器(GPIO Controller)

GPIO 控制器是具体管理 GPIO 硬件的驱动程序,每个 SoC(如 Rockchip、Allwinner、NXP 等)都会有自己的 GPIO 控制器,负责:

  • GPIO 的配置(输入/输出模式)
  • GPIO 的电平控制(高/低)
  • GPIO 的中断管理(上升沿、下降沿、中断屏蔽等)

在设备树(Device Tree,DT)中,GPIO 控制器通常被定义为一个 pinctrl 设备节点。例如:

gpio: gpio-controller@ff720000 {
    compatible = "rockchip,gpio";
    reg = <0xff720000 0x100>;
    gpio-controller;
    #gpio-cells = <2>;
};
  • compatible = "rockchip,gpio"; 说明这是一个 Rockchip 平台的 GPIO 控制器。
  • gpio-controller; 说明这个设备节点是一个 GPIO 控制器。
  • #gpio-cells = <2>; 表示 GPIO 设备的参数格式。

2.2 GPIO 设备(GPIO Device)

每个 GPIO 控制器管理一组 GPIO 引脚,驱动程序可以通过 GPIO 子系统 API 访问这些 GPIO 设备。例如:

leds {
    compatible = "gpio-leds";
    led1 {
        gpios = <&gpio 23 GPIO_ACTIVE_HIGH>;
        label = "led1";
    };
};

这表示 led1 连接到 gpio 控制器的 GPIO 23,高电平点亮。

2.3 GPIO 子系统 API

Linux 提供了一套 API 供内核驱动访问 GPIO 设备,主要包括:

  • 请求和释放 GPIO
    int gpio_request(unsigned int gpio, const char *label);
    void gpio_free(unsigned int gpio);
    
  • 配置 GPIO 方向
    int gpio_direction_input(unsigned int gpio);
    int gpio_direction_output(unsigned int gpio, int value);
    
  • 读取/设置 GPIO
    int gpio_get_value(unsigned int gpio);
    void gpio_set_value(unsigned int gpio, int value);
    
  • 中断处理
    int gpio_to_irq(unsigned int gpio);
    

3. GPIO 设备树(Device Tree)配置

在 Linux 设备树中,GPIO 设备通常以 pinctrl 方式配置,示例如下:

&pinctrl {
    leds_pins: leds-pins {
        rockchip,pins = <1 RK_PA0 0 &pcfg_pull_up>;
    };
};

leds {
    compatible = "gpio-leds";
    led {
        gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>;
        label = "status-led";
    };
};
  • rockchip,pins = <1 RK_PA0 0 &pcfg_pull_up>; 表示 GPIO1_PA0 作为 LED 设备引脚,并启用上拉电阻。
  • compatible = "gpio-leds"; 说明使用 gpio-leds 驱动管理 LED。
  • gpios = <&gpio1 0 GPIO_ACTIVE_HIGH>; 绑定 LED 到 GPIO1 的第 0 个引脚,并在 高电平 时点亮。

4. 用户空间访问 GPIO

Linux 4.8 之前,用户态可以通过 /sys/class/gpio 访问 GPIO。但从 Linux 4.8 开始,推荐使用 libgpiod

4.1 旧的 sysfs 方式(已弃用)

echo 23 > /sys/class/gpio/export
echo out > /sys/class/gpio/gpio23/direction
echo 1 > /sys/class/gpio/gpio23/value  # 设置高电平
echo 0 > /sys/class/gpio/gpio23/value  # 设置低电平

4.2 使用 libgpiod(推荐)

安装 libgpiod

sudo apt install gpiod

查询 GPIO:

gpiodetect

控制 GPIO:

gpioset gpiochip0 23=1  # 设置 GPIO 23 为高

5. GPIO 中断(IRQ)处理

GPIO 除了用于输入和输出,还可以用于 中断(Interrupt)。驱动程序可以注册一个 GPIO 触发的中断,例如:

static irqreturn_t button_irq_handler(int irq, void *dev_id)
{
    printk(KERN_INFO "Button Pressed!\n");
    return IRQ_HANDLED;
}

static int __init my_gpio_init(void)
{
    int irq_number;
    irq_number = gpio_to_irq(23);
    request_irq(irq_number, button_irq_handler, IRQF_TRIGGER_FALLING, "gpio_irq", NULL);
    return 0;
}
  • gpio_to_irq(23); 获取 GPIO 23 的中断号。
  • request_irq 注册中断,IRQF_TRIGGER_FALLING 说明在下降沿触发中断。

6. GPIO 子系统的优势

  • 抽象性:不同的硬件平台可以通过统一的 API 访问 GPIO。
  • 灵活性:支持多种 GPIO 配置方式,如设备树、sysfs、libgpiod
  • 安全性:通过 GPIO 子系统 管理 GPIO 资源,避免多个驱动争用 GPIO。

总结

Linux 内核 GPIO 子系统的主要作用是 提供一个统一的接口 让用户可以访问 GPIO 设备。其核心组成包括:

  1. GPIO 控制器(管理所有 GPIO 引脚)
  2. GPIO 设备(具体的 GPIO 硬件资源)
  3. GPIO API(提供标准化的 GPIO 访问方式)
  4. 设备树配置(用于指定 GPIO 设备的连接方式)
  5. 用户空间访问方式(如 libgpiod

在嵌入式系统中,GPIO 常用于 控制 LED、按键检测、中断触发 等功能,是驱动开发中常见的模块之一。

二、RK3568 GPIO命名规则

RK3568 GPIO 命名规则解析

Rockchip RK3568 SoC 具有 五组 GPIO(GPIO0 ~ GPIO4),每组 GPIO 由多个 bank(A, B, C, D 等)组成,每个 bank 内包含 8 个 GPIO 引脚

1. 命名格式
GPIOx_Yz
  • GPIOx : GPIO 组,x 取值范围 0~4,共 5 组(GPIO0、GPIO1、GPIO2、GPIO3、GPIO4)。
  • Y : GPIO 组内的 Bank,A、B、C、D,对应每组中的 4 个 Bank
  • z : GPIO 组内的引脚编号,取值 0~7(每个 Bank 有 8 个引脚)。

2. GPIO 编号计算

RK3568 的 GPIO 总共 160 个(5 组 × 32 个),其全局编号计算方式如下:

GPIO 编号 = (组号 × 32) + (Bank 号 × 8) + (引脚号)

其中:

  • 组号(x):GPIO0 = 0, GPIO1 = 1, GPIO2 = 2, GPIO3 = 3, GPIO4 = 4
  • Bank 号(Y):A = 0, B = 1, C = 2, D = 3
  • 引脚号(z):0 ~ 7

3. 实例解析
GPIO 名称组号Bank引脚编号全局编号计算
GPIO0_A00A (0)0(0×32) + (0×8) + 0 = 0
GPIO0_B30B (1)3(0×32) + (1×8) + 3 = 11
GPIO1_C71C (2)7(1×32) + (2×8) + 7 = 55
GPIO2_D42D (3)4(2×32) + (3×8) + 4 = 100
GPIO3_C33C (2)3(3×32) + (2×8) + 3 = 123
GPIO4_A54A (0)5(4×32) + (0×8) + 5 = 133

4. GPIO 在设备树中的表示

设备树(Device Tree) 中,Rockchip 的 GPIO 通过 <bank pin mux-config pull-config> 方式定义。例如:

&pinctrl {
    gpio3c3_pins: gpio3c3 {
        rockchip,pins = <3 RK_PC3 0 &pcfg_pull_none>;
    };
};

解析:

  • 3 RK_PC3 : GPIO 组 3,Bank C,Pin 3
  • 0 : 引脚复用模式(mux)
  • &pcfg_pull_none : 无上拉/下拉

5. 复用模式(MUX 配置)

RK3568 的 GPIO 可用于 多种功能(如 GPIO、I2C、SPI、UART、PWM 等),其 复用模式(MUX) 取值如下:

模式
0纯 GPIO
1复用功能 1
2复用功能 2
3复用功能 3
4复用功能 4
5复用功能 5
6复用功能 6

示例:

rockchip,pins = <3 RK_PC3 1 &pcfg_pull_none>;

表示 GPIO3_C3 复用功能 1(具体功能取决于硬件手册)。


6. 总结
  • GPIO 组:RK3568 共有 5 组(GPIO0 ~ GPIO4)。
  • GPIO Bank:每组有 4 个 Bank(A ~ D),每个 Bank 8 个引脚
  • GPIO 命名GPIOx_Yz,其中 x 为 GPIO 组号,Y 为 Bank(A=0, B=1, C=2, D=3),z 为 Bank 内引脚号(0~7)。
  • 全局 GPIO 编号 = (组号 × 32) + (Bank 号 × 8) + (引脚号)
  • 设备树定义:使用 <bank pin mux-config pull-config> 方式指定 GPIO 功能。

三、GPIO的两套控制函数

Linux GPIO 子系统的两套 API:gpiogpiod

在 Linux 内核中,GPIO(通用输入输出)子系统提供了两种不同的 API 来操作 GPIO:

  1. 旧版 gpio API(传统 sysfs 接口 + gpio 内核 API)
  2. 新版 gpiod API(基于 gpiolibgpiod 内核 API)

1. gpio API(老版)

gpio API 是 较早版本的 GPIO 控制接口,主要基于 sysfslinux/gpio.h 头文件,主要用于 内核驱动开发

1.1 gpio API 主要函数

这些函数主要用于 直接控制 GPIO,适用于 早期的内核驱动

#include <linux/gpio.h>
函数作用
gpio_request(gpio, label)申请一个 GPIO
gpio_free(gpio)释放 GPIO
gpio_direction_input(gpio)设置 GPIO 为输入模式
gpio_direction_output(gpio, value)设置 GPIO 为输出模式,并指定初始值
gpio_set_value(gpio, value)设置 GPIO 输出值
gpio_get_value(gpio)读取 GPIO 输入值
gpio_to_irq(gpio)将 GPIO 号转换为中断号
gpio_is_valid(gpio)检查 GPIO 是否可用

1.2 sysfs 方式(已废弃)

传统上,用户空间程序可以通过 sysfs 访问 GPIO:

# 导出 GPIO 23
echo 23 > /sys/class/gpio/export

# 设置 GPIO 方向
echo out > /sys/class/gpio/gpio23/direction

# 设置 GPIO 输出高电平
echo 1 > /sys/class/gpio/gpio23/value

# 释放 GPIO
echo 23 > /sys/class/gpio/unexport

⚠️ 注意sysfs 方式在 Linux 5.10 之后被废弃,建议使用 gpiod


2. gpiod API(新版,推荐)

gpiod(GPIO descriptor API)是 Linux 4.8 及以后推荐的 GPIO 操作方式,它是基于 gpiolib GPIO 子系统的,取代了 gpio API 和 sysfs

2.1 gpiod API 主要函数

#include <linux/gpio/consumer.h>
函数作用
gpiod_get(dev, con_id, flags)申请一个 GPIO
gpiod_put(desc)释放 GPIO
gpiod_direction_input(desc)设置 GPIO 为输入模式
gpiod_direction_output(desc, value)设置 GPIO 为输出模式
gpiod_set_value(desc, value)设置 GPIO 输出值
gpiod_get_value(desc)读取 GPIO 输入值
gpiod_to_irq(desc)将 GPIO 号转换为中断号

示例代码

struct gpio_desc *desc;

desc = gpiod_get(NULL, "my_gpio", GPIOD_OUT_LOW);
if (IS_ERR(desc)) {
    pr_err("Failed to get GPIO descriptor\n");
    return PTR_ERR(desc);
}

gpiod_set_value(desc, 1);  // 设置 GPIO 高电平
msleep(1000);
gpiod_set_value(desc, 0);  // 设置 GPIO 低电平

gpiod_put(desc);  // 释放 GPIO

2.2 libgpiod(用户空间)

用户空间,推荐使用 libgpiod 库,它提供了更强大的功能。

安装 libgpiod

sudo apt install libgpiod-dev gpiod

使用 gpiod 控制 GPIO:

# 列出所有 GPIO
gpiodetect

# 读取 GPIO 23 的值
gpioget gpiochip0 23

# 设置 GPIO 23 输出高电平
gpioset gpiochip0 23=1

用户空间 C 语言示例

#include <gpiod.h>
#include <stdio.h>

int main() {
    struct gpiod_chip *chip;
    struct gpiod_line *line;

    // 打开 GPIO 芯片(/dev/gpiochip0)
    chip = gpiod_chip_open_by_name("gpiochip0");
    line = gpiod_chip_get_line(chip, 23);

    // 设置 GPIO 方向并输出高电平
    gpiod_line_request_output(line, "example", 1);

    // 释放资源
    gpiod_chip_close(chip);
    return 0;
}

3. gpio vs gpiod 对比

对比项gpio API(旧)gpiod API(新)
适用版本旧内核(<4.8)新内核(≥4.8,推荐)
内核驱动✅ 可用✅ 可用
用户空间❌(sysfs 方式已废弃)libgpiod
GPIO 表示方式整数编号(GPIO 号)struct gpio_desc *
接口gpio_requestgpio_set_valuegpiod_getgpiod_set_value
安全性❌ 直接使用 GPIO 号,容易冲突✅ 使用 GPIO descriptor,更安全

4. 设备树(Device Tree) GPIO 描述

使用 gpiod 时,GPIO 在 设备树 中的定义:

leds {
    compatible = "gpio-leds";
    led1 {
        gpios = <&gpio2 5 GPIO_ACTIVE_HIGH>;
        label = "led1";
    };
};

设备树中 gpios 语法:

gpios = <&gpioX Y FLAGS>;
  • &gpioX:GPIO 控制器
  • Y:GPIO 号(相对编号)
  • FLAGS
    • GPIO_ACTIVE_HIGH(高有效)
    • GPIO_ACTIVE_LOW(低有效)

5. 结论

情况推荐使用
内核驱动开发(新内核)gpiod API
内核驱动开发(旧内核)gpio API
用户空间程序libgpiod
设备树 GPIO 定义gpios = <&gpioX Y GPIO_ACTIVE_HIGH>;

gpiod 是目前 Linux 推荐的 GPIO 操作方式,它比 gpio API 更安全、易用,并且支持 用户空间操作。建议在 新项目避免使用旧的 gpio API

http://www.dtcms.com/a/98490.html

相关文章:

  • 自然语言模型的演变与未来趋势:从规则到多模态智能的跨越
  • 混合知识表示系统框架python示例
  • PyQt6实例_批量下载pdf工具_主线程停止线程池
  • PERL开发环境搭建>>Windows,Linux,Mac OS
  • 【JavaScript】九、JS基础练习
  • torch.tensor 用法
  • OpenAI API - 快速入门开发
  • 链表(C++)
  • WPF 自定义行为AssociatedObject详解
  • 全包圆玛奇朵样板间亮相,极简咖啡风引领家装新潮流
  • 程序化广告行业(39/89):广告投放的数据分析与优化秘籍
  • 腾讯系AI应用,可以生视频,3D模型...
  • 北森测评的经验
  • 二层框架组合实验
  • linux压缩指令
  • 数据结构与算法:算法分析
  • 轮询和长轮询
  • html5基于Canvas的动态时钟实现详解
  • 论文内可解释性分析
  • 《ZooKeeper Zab协议深度剖析:构建高可用分布式系统的基石》
  • 0101-vite创建react_ts-环境准备-仿低代码平台项目
  • latex笔记
  • 复现文献中的三维重建图像生成,包括训练、推理和可视化
  • StarRocks 存算分离在京东物流的落地实践
  • GOC L2 第四课模运算和周期
  • 软件工程之需求工程(需求获取、分析、验证)
  • Unity顶点优化:UV Splits与Smoothing Splits消除技巧
  • 基于 Python 深度学习 lstm 算法的电影评论情感分析可视化系统(2.0 系统全新升级,已获高分通过)
  • CUDA专题3:为什么GPU能改变计算?深度剖析架构、CUDA®与可扩展编程
  • 软件信息安全性测试工具有哪些?安全性测试报告如何获取?