功能简介
GPIO(General-purpose input/output)即通用型输入输出。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。
GPIO接口定义了操作GPIO管脚的标准方法集合,包括:
-
设置、获取管脚方向:方向可以是输入或者输出(暂不支持高阻态)。
-
读、写管脚电平值:电平值可以是低电平或高电平。
-
设置、取消管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式。取消一个管脚的中断服务函数。
-
使能、禁止管脚中断:禁止或使能管脚中断。
基本概念
GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。可以通过软件来控制其输入和输出,即I/O控制。
-
GPIO输入
输入是检测各个引脚上的电平状态,高电平或者低电平状态。常见的输入模式有:模拟输入、浮空输入、上拉输入、下拉输入。
-
GPIO输出
输出是当需要控制引脚电平的高低时需要用到输出功能。常见的输出模式有:开漏输出、推挽输出、复用开漏输出、复用推挽输出。
运作机制
在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。GPIO模块接口适配模式采用统一服务模式(如图1所示)。
在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。
GPIO模块各分层作用:
-
接口层提供操作GPIO管脚的标准方法。
-
核心层主要提供GPIO管脚资源匹配,GPIO管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互,供芯片厂家快速接入HDF框架。
-
适配层主要是将钩子函数的功能实例化,实现具体的功能。
图 1 GPIO统一服务模式结构图
使用指导
场景介绍
GPIO主要是对GPIO管脚资源进行管理。开发者可以使用提供的GPIO操作接口,实现对管脚控制的具体控制。
接口说明
GPIO模块提供的主要接口如表1所示。具体API详见//drivers/hdf_core/framework/include/platform/gpio_if.h。
表 1 GPIO驱动API接口功能介绍
接口名 | 描述 |
---|---|
GpioGetByName(const char *gpioName) | 获取GPIO管脚ID |
int32_t GpioRead(uint16_t gpio, uint16_t *val) | 读GPIO管脚电平值 |
int32_t GpioWrite(uint16_t gpio, uint16_t val) | 写GPIO管脚电平值 |
int32_t GpioGetDir(uint16_t gpio, uint16_t *dir) | 获取GPIO管脚方向 |
int32_t GpioSetDir(uint16_t gpio, uint16_t dir) | 设置GPIO管脚方向 |
int32_t GpioUnsetIrq(uint16_t gpio, void *arg) | 取消GPIO管脚对应的中断服务函数 |
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg) | 设置GPIO管脚对应的中断服务函数 |
int32_t GpioEnableIrq(uint16_t gpio) | 使能GPIO管脚中断 |
int32_t GpioDisableIrq(uint16_t gpio) | 禁止GPIO管脚中断 |
说明:
本文涉及GPIO的所有接口,支持内核态及用户态使用。
开发步骤
GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如图2所示。
图 2 GPIO使用流程图
确定GPIO管脚号
两种方式获取管脚号:根据SOC芯片规则进行计算、通过管脚别名获取
-
根据SOC芯片规则进行计算
不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。
-
Hi3516DV300
控制器管理12组GPIO管脚,每组8个。
GPIO号 = GPIO组索引 (0~11) * 每组GPIO管脚数(8) + 组内偏移
举例:GPIO10_3的GPIO号 = 10 * 8 + 3 = 83
-
Hi3518EV300
控制器管理10组GPIO管脚,每组10个。
GPIO号 = GPIO组索引 (0~9) * 每组GPIO管脚数(10) + 组内偏移
举例:GPIO7_3的GPIO管脚号 = 7 * 10 + 3
-