OpenHarmony-4.GPIO驱动

  • GPIO

1.功能简介

  GPIO(General-purpose input/output)即通用型输入输出。GPIO又俗称为I/O口,I指的是输入(in),O指的是输出(out)。可以通过软件来控制其输入和输出,即I/O控制。通常,GPIO控制器通过分组的方式管理所有GPIO管脚,每组GPIO有一个或多个寄存器与之关联,通过读写寄存器完成对GPIO管脚的操作。

  • GPIO输入

    输入是检测各个引脚上的电平状态,高电平或者低电平状态。常见的输入模式有:模拟输入、浮空输入、上拉输入、下拉输入。

  • GPIO输出

    输出是当需要控制引脚电平的高低时需要用到输出功能。常见的输出模式有:开漏输出、推挽输出、复用开漏输出、复用推挽输出。

  GPIO接口定义了操作GPIO管脚的标准方法集合,包括:

  • 设置、获取管脚方向:方向可以是输入或者输出(暂不支持高阻态)。

  • 读、写管脚电平值:电平值可以是低电平或高电平。

  • 设置、取消管脚中断服务函数:设置一个管脚的中断响应函数,以及中断触发方式。取消一个管脚的中断服务函数。

  • 使能、禁止管脚中断:禁止或使能管脚中断。

1.1.运作机制

  在HDF框架中,同类型设备对象较多时(可能同时存在十几个同类型配置器),若采用独立服务模式,则需要配置更多的设备节点,且相关服务会占据更多的内存资源。相反,采用统一服务模式可以使用一个设备服务作为管理器,统一处理所有同类型对象的外部访问(这会在配置文件中有所体现),实现便捷管理和节约资源的目的。GPIO模块接口适配模式采用统一服务模式:
在这里插入图片描述
  在统一模式下,所有的控制器都被核心层统一管理,并由核心层统一发布一个服务供接口层,因此这种模式下驱动无需再为每个控制器发布服务。

  GPIO模块各分层作用:

  • 接口层提供操作GPIO管脚的标准方法。

  • 核心层主要提供GPIO管脚资源匹配,GPIO管脚控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互,供芯片厂家快速接入HDF框架。

  • 适配层主要是将钩子函数的功能实例化,实现具体的功能。

1.2.接口层

  GPIO模块提供的主要接口:

  • drivers/hdf_core/framework/include/platform/gpio_if.h

在这里插入图片描述

  以gpio_stm32f4xx为例:

GpioRead-> GpioCntlrRead-> cntlr->ops->read 调用哪里?-> LL_GPIO_ReadInputPin

  GpioRead代码分析:

drivers_hdf_core/framework/support/platform/src/gpio/gpio_if.c
int32_t GpioRead(uint16_t gpio, uint16_t *val)
{int32_t ret;struct GpioCntlr *cntlr = GpioCntlrGetByGpio(gpio);ret = GpioCntlrRead(cntlr, GpioCntlrGetLocal(cntlr, gpio), val);GpioCntlrPut(cntlr);return ret;
}drivers_hdf_core/framework/support/platform/src/gpio/gpio_core.c:
int32_t GpioCntlrRead(struct GpioCntlr *cntlr, uint16_t local, uint16_t *val)
{...return cntlr->ops->read(cntlr, local, val);  //调用注册的gpio_stm32f4xx控制器ops接口对应的read函数,即g_GpioCntlrMethod->GpioDevRead
}

  gpio_stm32f4xx驱动:

  • drivers_hdf_core/adapter/platform/gpio/gpio_stm32f4xx.c
struct HdfDriverEntry g_GpioDriverEntry = {.moduleVersion = 1,.moduleName = "ST_GPIO_MODULE_HDF",.Init = GpioDriverInit,.Release = GpioDriverRelease,
};
HDF_INIT(g_GpioDriverEntry);static int32_t GpioDriverInit(struct HdfDeviceObject *device)
{int32_t ret;struct GpioCntlr *gpioCntlr = NULL;ret = PlatformDeviceBind(&g_stmGpioCntlr.device, device);gpioCntlr = GpioCntlrFromHdfDev(device);ret = AttachGpioDevice(gpioCntlr, device); /* GpioCntlr add GpioDevice to priv */gpioCntlr->ops = &g_GpioCntlrMethod;  //注册的ops接口ret = GpioCntlrAdd(gpioCntlr);return HDF_SUCCESS;
}/* GpioMethod definitions */
struct GpioMethod g_GpioCntlrMethod = {.request = NULL,.release = NULL,.write = GpioDevWrite,.read = GpioDevRead,.setDir = GpioDevSetDir,.getDir = GpioDevGetDir,.toIrq = NULL,.setIrq = GpioDevSetIrq,.unsetIrq = GpioDevUnSetIrq,.enableIrq = GpioDevEnableIrq,.disableIrq = GpioDevDisableIrq,
};static int32_t GpioDevRead(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t *val)
{(void)cntlr;uint16_t realPin = g_gpioPinsMap[gpio].realPin;uint32_t pinReg = g_stmRealPinMaps[realPin];uint16_t value = 0;GPIO_TypeDef* gpiox = g_gpioxMaps[g_gpioPinsMap[gpio].group];value = LL_GPIO_ReadInputPin(gpiox, pinReg);  //调用ll库对应的函数接口*val = value;return HDF_SUCCESS;
}

1.3.核心层

  • drivers_hdf_core/adapter/platform/gpio/gpio_stm32f4xx.c

  gpio_stm32f4xx驱动初始化:

struct HdfDriverEntry g_GpioDriverEntry = {.moduleVersion = 1,.moduleName = "ST_GPIO_MODULE_HDF",.Init = GpioDriverInit,.Release = GpioDriverRelease,
};
HDF_INIT(g_GpioDriverEntry);static struct GpioCntlr g_stmGpioCntlr;
static int32_t GpioDriverInit(struct HdfDeviceObject *device)
{int32_t ret;struct GpioCntlr *gpioCntlr = NULL;ret = PlatformDeviceBind(&g_stmGpioCntlr.device, device);gpioCntlr = GpioCntlrFromHdfDev(device);ret = AttachGpioDevice(gpioCntlr, device); /* GpioCntlr add GpioDevice to priv */gpioCntlr->ops = &g_GpioCntlrMethod; /* register callback */ret = GpioCntlrAdd(gpioCntlr);return HDF_SUCCESS;
}

  GpioDriverInit 函数主要工作:

  • 绑定GpioCntlr和HdfDeviceObject;
  • 调用GpioCntlrAdd将gpioCntlr 注册到PlatformManager进行管理。
    GpioCntlrAdd -> PlatformDeviceAdd->PlatformManagerAddDevice

1.4.开发步骤

  GPIO标准API通过GPIO管脚号来操作指定管脚,使用GPIO的一般流程如图所示。

图 2 GPIO使用流程图
1.3.1.确定GPIO管脚号

  两种方式获取管脚号:

  • 根据SOC芯片规则进行计算、通过管脚别名获取
    不同SOC芯片由于其GPIO控制器型号、参数、以及控制器驱动的不同,GPIO管脚号的换算方式不一样。
  • 通过管脚别名获取
    调用接口GpioGetByName进行获取,入参是该管脚的别名,接口返回值是管脚的全局ID。

1.3.2.设置GPIO管脚中断

  为一个GPIO管脚设置中断响应程序,使用如下函数:

int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg);

  以hdf_key 驱动为例:

SetupKeyIrq->GpioSetIrq
drivers_hdf_core/framework/model/input/driver/hdf_key.c:
static int32_t KeyInit(KeyDriver *keyDrv)
{int32_t ret = SetupKeyIrq(keyDrv);CHECK_RETURN_VALUE(ret);return HDF_SUCCESS;
}static int32_t SetupKeyIrq(KeyDriver *keyDrv)
{uint16_t intGpioNum = keyDrv->keyCfg->gpioNum;uint16_t irqFlag = keyDrv->keyCfg->irqFlag;int32_t ret = GpioSetDir(intGpioNum, GPIO_DIR_IN);ret = GpioSetIrq(intGpioNum, irqFlag | GPIO_IRQ_USING_THREAD, KeyIrqHandle, keyDrv);ret = GpioEnableIrq(intGpioNum);return HDF_SUCCESS;
}

GpioSetIrq 函数调用:

GpioSetIrq -> GpioCntlrSetIrq-> GpioIrqRecordCreate-> cntlr->ops->setIrq-> GpioDevSetIrq  //gpio_stm32f4xx.c

代码实现:

drivers_hdf_core/framework/support/platform/src/gpio/gpio_if.c
int32_t GpioSetIrq(uint16_t gpio, uint16_t mode, GpioIrqFunc func, void *arg)
{int32_t ret;struct GpioCntlr *cntlr = GpioCntlrGetByGpio(gpio);ret = GpioCntlrSetIrq(cntlr, GpioCntlrGetLocal(cntlr, gpio), mode, func, arg);GpioCntlrPut(cntlr);return ret;
}int32_t GpioCntlrSetIrq(struct GpioCntlr *cntlr, uint16_t local, uint16_t mode, GpioIrqFunc func, void *arg)
{int32_t ret;struct GpioInfo *ginfo = NULL;struct GpioIrqRecord *irqRecord = NULL;ginfo = &cntlr->ginfos[local];ret = GpioIrqRecordCreate(ginfo, mode, func, arg, &irqRecord);ret = GpioCntlrSetIrqInner(ginfo, irqRecord);return ret;
}static int32_t GpioCntlrSetIrqInner(struct GpioInfo *ginfo, struct GpioIrqRecord *irqRecord)
{int32_t ret;uint16_t local = GpioInfoToLocal(ginfo);struct GpioCntlr *cntlr = ginfo->cntlr;...ginfo->irqRecord = irqRecord;ret = cntlr->ops->setIrq(cntlr, local, irqRecord->mode);return ret;
}drivers_hdf_core/adapter/platform/gpio/gpio_stm32f4xx.c
struct GpioMethod g_GpioCntlrMethod = {....setIrq = GpioDevSetIrq,...
};static int32_t GpioDevSetIrq(struct GpioCntlr *cntlr, uint16_t gpio, uint16_t mode)
{(void)cntlr;uint16_t realPin = g_gpioPinsMap[gpio].realPin;uint32_t pinReg = g_stmRealPinMaps[realPin];if (mode == OSAL_IRQF_TRIGGER_RISING) {g_gpioExitCfg[gpio].trigger = LL_EXTI_TRIGGER_RISING;} else if (mode == OSAL_IRQF_TRIGGER_FALLING) {g_gpioExitCfg[gpio].trigger = LL_EXTI_TRIGGER_FALLING;} else {HDF_LOGE("%s %d, error mode:%d", __func__, __LINE__, mode);return HDF_ERR_NOT_SUPPORT;}return HDF_SUCCESS;
}

refer to

  • git clone https://gitee.com/openharmony/drivers_hdf_core.git
  • http://docs.openharmony.cn/pages/v4.1/zh-cn/device-dev/driver/driver-platform-gpio-des.md/

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/484099.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

文本生成类(机器翻译)系统评估

在机器翻译任务中常用评价指标:BLEU、ROGUE、METEOR、PPL。 这些指标的缺点:只能反应模型输出是否类似于测试文本。 BLUE(Bilingual Evaluation Understudy):是用于评估模型生成的句子(candidate)和实际句子(referen…

UG NX二次开发(Python)-UIStyler-选取点

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 1、前言2、设计一个UI界面3、创建长方体的代码4、需要引入的库5、测试验证1、前言 采用Python语言进行UG NX二次开发的资料比较少,我本来不是很认可采用Python进行二次开发的,但是近期有读者咨询…

鸿蒙 Next 可兼容运行 Android App,还支持出海 GMS?

最近 「出境易」和 「卓易通」 应该算是鸿蒙和 Android 开发圈“突如其来”的热门话题,而 「出境易」可能更高频一些,主要也是 Next 5.0 被大家发现刚上架了一个名为「出境易」的应用,通过这个 App 用户可以直接运行不兼容 Next 的 Android A…

请求响应:常见参数接收及封装(数组集合参数及日期参数)

数组参数 在前端页面的表单中,存在复选框元素,当提交表单到后端的时候,会将复选框中的全部内容提交到后端进行处理,由于复选框中往往存在很多数据,并且同复选框中数据名称相同,这样的请求参数叫做数组参数…

ASP.NET Core SignalR 入门

一、简介 📢 SignalR的主要功能是提供服务器和客户端之间的实时通信。当连接的客户端变得可用时,服务器可以立即向其推送内容,而不是等待客户端发起请求。这种功能特别适合需要实时更新数据的应用场景,如聊天应用、实时数据分析、…

介绍一下希尔排序法(c基础)

hi , I am 36 适合对象c语言初学者 希尔排序(Shell Sort)是一种改进的插入排序算法,它通过将原始数据分成多个子序列来改善插入排序在处理大规模无序数组时性能较差的情况。 基本原理 希尔排序的基本思想是先将整个待排序的记录序列分割成为…

Python知识分享第十九天-网络编程

网络编程 概述用来实现 网络互联 不同计算机上运行的程序间可以进行数据交互也叫Socket编程 套接字编程 三要素IP地址概述设备在网络中的唯一标识分类IPV4城域网13广域网22局域网31IPV6八字节 十六进制相关dos命令查看ipwindows: ipconfigmac和linux: ifconfig测试网络ping 域…

opencv-android编译遇到的相关问题处理

1、opencv-android sdk下载 下载地址:https://opencv.org/releases/ 下载安卓SDK即可 2、解压下载好的SDK 3、导入opencv的SDK到安卓项目中 导入步骤在/OpenCV-android-sdk/sdk/build.gradle文件的注释中写的非常详细,大家可安装官方给出的步骤导入。…

【CC2530开发基础篇】光敏和热敏传感器

一、前言 1.1 开发背景 本实验通过CC2530单片机接入光敏传感器和热敏传感器,进行数据采集与检测,并将检测结果通过串口终端输出。光敏传感器和热敏传感器是常见的环境感知设备,分别用于测量光强和温度。在实际应用中,这些传感器…

基于 LLamafactory 的异步API高效调用实现与速度对比

文章目录 背景摘要简介代码实现运行结果速度对比异步调用速度同步调用速度 背景 原先经常调用各家的闭源大模型的API,如果使用同步的方式调用,速度会很慢。为了加快 API 的调用速度,决定使用异步调用 API 的方式。 摘要 通过异步方式调用大…

贪心算法实例-问题分析(C++)

贪心算法实例-问题分析 饼干分配问题 有一群孩子和一堆饼干,每个小孩都有一个饥饿度,每个饼干都有一个能量值,当饼干的能量值大于等于小孩的饥饿度时,小孩可以吃饱,求解最多有多少个孩子可以吃饱?(注:每个小孩只能吃…

基于ZYNQ-7000系列的FPGA学习笔记7——按键控制蜂鸣器(模块化编写)

基于ZYNQ-7000系列的FPGA学习笔记7——按键控制蜂鸣器(模块化编写) 1. 实验要求2. 功能分析3. 模块设计4. 波形图4.1 按键消抖模块4.2 按键控制蜂鸣器模块 5.代码编写5.1 rtl代码5.2 测试代码 6. 代码仿真7. 添加约束文件并分析综合 在上期的内容中&…

linux环境GitLab服务部署安装及使用

一、GitLab介绍 GitLab是利用Ruby onRails一个开源的版本管理系统,实现一个自托管的Git项目仓库,可通过Web界面进行访问公开的或者私人项目。 二、GitLab安装 1、先安装相关依赖 yum -y install policycoreutils openssh-server openssh-clients postf…

视频码率到底是什么?详细说明

视频码率(Video Bitrate)是指在单位时间内(通常是每秒)传输或处理的视频数据量,用比特(bit)表示。它通常用来衡量视频文件的压缩程度和质量,码率越高,视频质量越好&#…

企业多套系统如何一步步实现对接完成闭环?

前言 很多企业用着用着突然发现企业内部有很多的系统,有ERP、CRM、MES、PLM各个系统还比较独立上线时间不一致,主数据包袱很重。这期就讲讲面对情况如何实施对接的案例。 客户背景 公司专注于健康科技领域,致力于打造国际化的专业健康管理…

MySQL大小写敏感、MySQL设置字段大小写敏感

文章目录 一、MySQL大小写敏感规则二、设置数据库及表名大小写敏感 2.1、查询库名及表名是否大小写敏感2.2、修改库名及表名大小写敏感 三、MySQL列名大小写不敏感四、lower_case_table_name与校对规则 4.1、验证校对规则影响大小写敏感4.1、验证校对规则影响排序 五、设置字段…

【HarmonyOS开发】超详细的ArkTS入门

安装DevEco Studio和新建项目就不多说了,可以移步官网 就可以把他们拆成这几个部分了,如果看不懂可以暂时忽略下面冒号后面的内容 装饰器:用于装饰类、结构、方法以及变量,并赋予其特殊的含义。如上述示例中Entry、Component和St…

如何在本地环境中模拟使用https

1.生成私钥文件,其中out输出路径可以自定义 openssl genrsa -out D:\localhost.key 2048 2 生成证书签名请求(CSR),根据第一步正确指定私钥路径,和签名请求 openssl req -new -key D:\localhost.key -out D:\localhos…

认识自定义协议

经过前面的介绍,我们知道TCP/IP协议有一组五层模型,从上往下为应用层、传输层、网络层、数据链路层和物理层,且在网络中传输的数据都必须经过这几层模型的封装和分用,作为程序员,我们最经常打交道的就是应用层。程序员…

在Node.js局域网调试https的Vue项目

需求: 最近在测试在网页端(HTML5)调用移动设备的定位等权限功能,发现某些功能是必须保证域名在https下的否则会出现不正常现象。 解决: 1.在线生成和证书 访问:CSR文件生成工具-中国数字证书CHINASSL …