RK3568驱动指南|第十二篇 GPIO子系统-第131章 GPIO子系统API函数的引入

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。


【公众号】迅为电子

【粉丝群】824412014(加群获取驱动文档+例程)

【视频观看】嵌入式学习之Linux驱动(第十二篇 GPIO子系统_全新升级)_基于RK3568

【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板


第131章 GPIO子系统API函数的引入

事实上,在前面中断课程中,已经简单接触到了GPIO子系统中的API函数,其中用来获取gpio中断编号的gpio_to_irq函数就属于GPIO子系统中的API函数,在本章节中将对GPIO子系统进行简单的介绍。

在目前的Linux内核主线中,GPIO(通用输入/输出)子系统存在两个版本,这里将两个版本区分为新版本和旧版本。新版本GPIO子系统接口是基于描述符(descriptor-based)来实现的,而旧版本的GPIO子系统接口是基于整数(integer-based)来实现的,在Linux内核中为了保持向下的兼容性,旧版本的接口在最新的内核版本中仍然得到支持,而随着时间的推移,新版本的GPIO子系统接口会越来越完善,最终完全取代旧版本,所以在本课程中主要讲解新版本的GPIO子系统接口。

新的GPIO子系统接口需要与与设备树(Device Tree)结合使用。使用设备树和新的GPIO接口可以更加灵活地配置和管理系统中的GPIO资源,提供了更好的可扩展性和可移植性。所以如果没有设备树,就无法使用新的GPIO接口。

那要如何对新旧GPIO子系统接口进行区分呢,一个明显的区别是新的GPIO子系统接口使用了以 "gpiod_"作为前缀的函数命名约定,而旧的GPIO子系统接口使用了以"gpio_"作为前缀的函数命名约定。

一些区分新旧 GPIO 子系统接口的示例如下所示:

新的 GPIO 子系统接口示例如下所示:

gpiod_set_value()
gpiod_direction_input()
gpiod_direction_output()
gpiod_get_value()
gpiod_request()

旧的 GPIO 子系统接口示例:

gpio_set_value()
gpio_direction_input()
gpio_direction_output()
gpio_get_value()
gpio_request()

上面也提到了新的 GPIO 子系统接口是基于描述符(descriptor-based)来实现的,由struct gpio_desc结构体来表示,该结构体定义在内核源码的“drivers/gpio/gpiolib.h”目录下。具体内容如下所示:

struct gpio_desc {
    struct gpio_device gdev;    // GPIO设备结构体
    unsigned long flags;        // 标志位,用于表示不同的属性
    /* 标志位符号对应的位号 */
    #define FLAG_REQUESTED 0        // GPIO已请求
    #define FLAG_IS_OUT 1           // GPIO用作输出
    #define FLAG_EXPORT 2           // 受sysfs_lock保护的导出标志
    #define FLAG_SYSFS 3            // 通过/sys/class/gpio/control导出的标志
    #define FLAG_ACTIVE_LOW 6       // GPIO值为低电平时激活
    #define FLAG_OPEN_DRAIN 7       // GPIO为开漏类型
    #define FLAG_OPEN_SOURCE 8      // GPIO为开源类型
    #define FLAG_USED_AS_IRQ 9      // GPIO连接到中断请求(IRQ)
    #define FLAG_IS_HOGGED 11       // GPIO被独占占用
    #define FLAG_TRANSITORY 12      // GPIO在休眠或复位时可能失去值
    /* 连接标签 */
    const char *label;            // GPIO的名称
    const char *name;             // GPIO的名称
};

(1)struct gpio_device gdev是一个 struct gpio_device 类型的字段,用于表示 GPIO 设备的相关信息。struct gpio_device 结构体通常包含设备的底层硬件控制器等信息。

(2)unsigned long flags:用于表示 GPIO 的标志位,以表示不同的属性。通过使用位操作,每个标志位可以单独设置或清除。

(3)第5-14行用于表示不同标志位的符号常量,与 flags 字段中的位号相对应。例如,在 flags 字段中的第 0 位表示 FLAG_REQUESTED,第 1 位表示 FLAG_IS_OUT,以此类推

(4)const char *label: 这是一个指向字符串的指针,表示 GPIO 的标签或名称。

(5)const char *name: 这是一个指向字符串的指针,表示 GPIO 的名称。

上面需要重点关注的是然后struct gpio_device结构体,该结构体同样定义在内核源码的“drivers/gpio/gpiolib.h”目录下,具体内容如下所示:

struct gpio_device {
    int id;                             // GPIO设备ID
    struct device *dev;                 // 对应的设备结构体指针
    struct cdev chrdev;                 // 字符设备结构体
    struct device *mockdev;             // 模拟设备结构体指针
    struct module *owner;               // 拥有该GPIO设备的内核模块指针
    struct gpio_chip *chip;             // 对应的GPIO芯片结构体指针
    struct gpio_desc *descs;            // GPIO描述符数组指针
    int base;                           // GPIO编号的起始值
    u16 ngpio;                          // GPIO的数量
    const char *label;                  // GPIO设备的标签
    void *data;                         // 与GPIO设备相关的数据指针
    struct list_head list;              // 用于将GPIO设备结构体连接到链表中
#ifdef CONFIG_PINCTRL
    /*
     * 如果启用了CONFIG_PINCTRL选项,GPIO控制器可以选择描述它们在SoC中服务的实际引脚范围。
     * 此信息将由pinctrl子系统用于配置相应的GPIO引脚。
     */
    struct list_head pin_ranges;        // 描述GPIO控制器引脚范围的链表
#endif
};

该结构体是用来描述GPIO设备的数据结构,关于该结构体的参数介绍如下所示:

(1)int id:整型字段,表示GPIO设备的ID。每个GPIO设备可以有一个唯一的ID。

(2)struct device *dev:指向 struct device 的指针,表示与GPIO设备相关联的设备结构体。

(3)struct cdev chrdev: 字符设备结构体,用于实现GPIO设备的字符设备接口。

(4)struct device *mockdev: 指向 struct device 的指针,用于表示GPIO设备的模拟设备结构体。

(5)struct module *owner: 指向拥有该GPIO设备的内核模块的指针。

(6)struct gpio_chip *chip: 指向 struct gpio_chip 的指针,表示与GPIO设备关联的GPIO芯片(GPIO控制器)结构体。

(7)struct gpio_desc *descs: 指向 struct gpio_desc 数组的指针,表示与GPIO设备关联的GPIO描述符。每个GPIO描述符用于描述GPIO的属性和状态。

(8)int base: 表示GPIO编号的起始值。

(9)u16 ngpio: 16位无符号整型字段,表示GPIO的数量。

(10)const char *label: 指向字符串的指针,表示GPIO设备的标签或名称。

(11)void *data: 指向与GPIO设备相关的数据的指针,用于存储和访问与GPIO设备相关的自定义数据。

(12)struct list_head list: 将GPIO设备结构体连接到链表中的字段,用于管理多个GPIO设备的列表。

(13)struct list_head pin_ranges (仅在启用CONFIG_PINCTRL 选项时存在): 用于描述GPIO控制器引脚范围的链表。如果配置了GPIO控制器的引脚范围,该链表将包含描述每个范围的元素。

在上面一系列的参数中,要重点关注的是struct gpio_chip *chip这一结构体,表示与GPIO设备关联的GPIO芯片(GPIO控制器)结构体,该结构体定义在内核源码目录下的“include/linux/gpio/driver.h”文件中,具体内容如下所示

struct gpio_chip {
    const char *label;                              // GPIO芯片标签
    struct gpio_device gpiodev;                      // GPIO设备
    struct device *parent;                           // 父设备指针
    struct module *owner;                            // 拥有者模块指针
    int (*request)(struct gpio_chip *chip, unsigned offset);// 请求GPIO
    void (*free)(struct gpio_chip *chip, unsigned offset);  // 释放GPIO
    int (*get_direction)(struct gpio_chip *chip, unsigned offset); // 获取GPIO方向
    int (*direction_input)(struct gpio_chip *chip, unsigned offset); // 设置GPIO为输入
    int (*direction_output)(struct gpio_chip *chip, unsigned offset, int value); // 设置GPIO为输出
    int (*get)(struct gpio_chip chip, unsigned offset);   // 获取GPIO值
    int (*get_multiple)(struct gpio_chip chip, unsigned long *mask, unsigned long *bits); // 获取多个GPIO的值
    void (*set)(struct gpio_chip chip, unsigned offset, int value);    // 设置GPIO值
    void (*set_multiple)(struct gpio_chip chip, unsigned long mask, unsigned long *bits); // 设置多个GPIO的值
    int (*set_config)(struct gpio_chip *chip, unsigned offset, unsigned long config); // 设置GPIO配置
    int (*to_irq)(struct gpio_chip chip, unsigned offset);    // 将GPIO转换为中断
    void (*dbg_show)(struct seq_file *s, struct gpio_chip chip);  // 在调试信息中显示GPIO
    int base;                                     // GPIO编号的基准值
    u16 ngpio;                                    // GPIO的数量
    const char *const *names;                     // GPIO的名称数组
..........
};

struct gpio_chip *chip这一结构体用于描述 GPIO 芯片的属性和操作函数,可以通过函数指针调用相应的函数来请求、释放、设置、获取 GPIO 的状态和数值等操作,从而实现对GPIO的控制和管理,需要注意的是这个结构体中的一系列函数都不需要我们来填充,这些工作都是由芯片原厂工程师来完成的,我们只需要学会新gpio子系统相应API函数的使用即可。

在接下来的章节中将对常用的新gpio子系统API函数进行讲解。

  • 16
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值