Disclaimer: This article is a blogger original article, follow the CC 4.0 BY-SA copyright agreement, reproduced, please attach the original source link and this statement.
Interface Description
To simplify the driver layer using the GPIO Interrupt complex function I encapsulates into two interfaces, API standards are similar to the interface provided by the system, using a direct request to the interrupt mode when the GPIO function GPIO interrupts, and then run out call the corresponding release function. These two functions encapsulate the GPIO interrupt processing interface, interrupt API function and the necessary processes and exception handling. As shown in the following:
/*********************************************************************************************************
GPIO_IRQ 对象结构体
*********************************************************************************************************/
typedef struct {
UINT uiGpio; /* GPIO 编号 */
ULONG ulFlags; /* GPIO 配置参数 */
VOID (*pFunc)(PVOID); /* 中断回调函数 */
PVOID pvArg; /* 回调函数参数 */
CPCHAR pcLabel; /* GPIO 标签名称 */
CPCHAR pcIrqName; /* GPIO 中断名称 */
ULONG ulVector; /* GPIO 中断号 */
} GPIO_IRQ;
/*********************************************************************************************************
** 函数名称: API_GpioIrqRequest
** 功能描述: 请求使用一个中断模式的 GPIO
** 输 入 : pGpioIrq 中断GPIO对象
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT API_GpioIrqRequest (GPIO_IRQ *pGpioIrq);
/*********************************************************************************************************
** 函数名称: API_GpioIrqFree
** 功能描述: 释放一个中断模式的 GPIO
** 输 入 : pGpioIrq 中断GPIO对象
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT API_GpioIrqFree (GPIO_IRQ *pGpioIrq);
Implementation code
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: gpioIrqLib.h
**
** 创 建 人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2017 年 12 月 13 日
**
** 描 述: GPIO 中断模式简化接口
*********************************************************************************************************/
#define __SYLIXOS_KERNEL
#include "SylixOS.h"
/*********************************************************************************************************
GPIO_IRQ 对象结构体
*********************************************************************************************************/
typedef struct {
UINT uiGpio; /* GPIO 编号 */
ULONG ulFlags; /* GPIO 配置参数 */
VOID (*pFunc)(PVOID); /* 中断回调函数 */
PVOID pvArg; /* 回调函数参数 */
CPCHAR pcLabel; /* GPIO 标签名称 */
CPCHAR pcIrqName; /* GPIO 中断名称 */
ULONG ulVector; /* GPIO 中断号 */
} GPIO_IRQ;
/*********************************************************************************************************
** 函数名称: __gpioIsr
** 功能描述: GPIO 中断服务函数
** 输 入: pvArg 输入参数
** ulVector 中断向量
** 输 出: 中断返回值
*********************************************************************************************************/
static irqreturn_t __gpioIsr (PVOID pvArg, ULONG ulVector)
{
irqreturn_t irqret;
GPIO_IRQ *pGpioIrq;
pGpioIrq = (GPIO_IRQ *)pvArg;
if (pGpioIrq == NULL) {
return (LW_IRQ_NONE);
}
irqret = API_GpioSvrIrq(pGpioIrq->uiGpio);
if (LW_IRQ_HANDLED == irqret) {
API_GpioClearIrq(pGpioIrq->uiGpio);
if (pGpioIrq->pFunc) {
pGpioIrq->pFunc(pGpioIrq->pvArg);
}
}
return (irqret);
}
/*********************************************************************************************************
** 函数名称: API_GpioIrqRequest
** 功能描述: 请求使用一个中断模式的 GPIO
** 输 入 : pGpioIrq 中断GPIO对象
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT API_GpioIrqRequest (GPIO_IRQ *pGpioIrq)
{
INT iRet;
if (pGpioIrq == NULL) {
return (PX_ERROR);
}
iRet = API_GpioRequestOne(pGpioIrq->uiGpio, LW_GPIOF_DIR_IN, pGpioIrq->pcLabel);
if (iRet != ERROR_NONE) {
return (PX_ERROR);
}
pGpioIrq->ulVector = API_GpioGetIrq(pGpioIrq->uiGpio, 0, 0);
if (pGpioIrq->ulVector < 0) {
return (PX_ERROR);
}
if (pGpioIrq->ulFlags & LW_GPIODF_TRIG_LEVEL) {
if (pGpioIrq->ulFlags & LW_GPIODF_TRIG_FALL) { /* 设置为低电平触发 */
iRet = API_GpioSetupIrq(pGpioIrq->uiGpio, 1, 0);
} else if (pGpioIrq->ulFlags & LW_GPIODF_TRIG_RISE) { /* 设置为高电平触发 */
iRet = API_GpioSetupIrq(pGpioIrq->uiGpio, 1, 1);
}
} else {
if ((pGpioIrq->ulFlags & LW_GPIODF_TRIG_FALL) &&
(pGpioIrq->ulFlags & LW_GPIODF_TRIG_RISE)) { /* 设置为双边沿触发 */
iRet = API_GpioSetupIrq(pGpioIrq->uiGpio, 0, 2);
} else if (pGpioIrq->ulFlags & LW_GPIODF_TRIG_FALL) { /* 设置为下降沿触发 */
iRet = API_GpioSetupIrq(pGpioIrq->uiGpio, 0, 0);
} else if (pGpioIrq->ulFlags & LW_GPIODF_TRIG_RISE) { /* 设置为上升沿触发 */
iRet = API_GpioSetupIrq(pGpioIrq->uiGpio, 0, 1);
}
}
if (iRet == LW_VECTOR_INVALID) {
return (PX_ERROR);
}
API_InterVectorConnect(pGpioIrq->ulVector, /* 注册中断服务函数 */
(PINT_SVR_ROUTINE)__gpioIsr,
pGpioIrq,
pGpioIrq->pcIrqName);
API_InterVectorEnable(pGpioIrq->ulVector);
return (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: API_GpioIrqFree
** 功能描述: 释放一个中断模式的 GPIO
** 输 入 : pGpioIrq 中断GPIO对象
** 输 出 : ERROR_CODE
*********************************************************************************************************/
static INT API_GpioIrqFree (GPIO_IRQ *pGpioIrq)
{
API_InterVectorDisable(pGpioIrq->ulVector);
API_InterVectorDisconnect(pGpioIrq->ulVector, /* 注册中断服务函数 */
(PINT_SVR_ROUTINE)__gpioIsr,
pGpioIrq);
API_GpioFree(pGpioIrq->uiGpio);
return (ERROR_NONE);
}
/*********************************************************************************************************
END
*********************************************************************************************************/
Routine use
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: gpioDrvExample3.c
**
** 创 建 人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2017 年 12 月 13 日
**
** 描 述: gpio 在驱动中的调用例程,针对NXP i.MX-RT1050 EVK开发版。
** 因为连接板载 LED01 的引脚同时也连接了 enet 的复位脚,硬件冲突故不能使用。
** LED02 只是一个空闲的gpio(为J22.7),需要用户连接LED或万用表来检测电平变化。
*********************************************************************************************************/
#define __SYLIXOS_KERNEL
#include "stdio.h"
#include "SylixOS.h"
#include "gpio/gpio.h"
#include "gpioIrqLib.h"
/*********************************************************************************************************
引脚宏定义
********************************************************************************************************/
#define KEY08 GPIO_E_00 /* GPIO5--00 */
#define LED01 GPIO_A_09 /* GPIO1--09 */
#define LED02 GPIO_A_18 /* GPIO1--18 */
/*********************************************************************************************************
GPIO_TEST 对象结构体
*********************************************************************************************************/
typedef struct {
UINT uiGpioLed; /* GPIO编号 */
UINT uiIrqCount; /* 中断计数值 */
LW_OBJECT_HANDLE hSemBIrq; /* 信号量句柄 */
} GPIO_TEST;
/*********************************************************************************************************
** 函数名称: gpioDrvExample3CallBack
** 功能描述: GPIO 中断回调函数
** 输 入: pvArg 输入参数
** 输 出: 无
*********************************************************************************************************/
static VOID gpioDrvExample3CallBack (PVOID pvArg)
{
GPIO_TEST *pGpioTest = (GPIO_TEST *)pvArg;
pGpioTest->uiIrqCount++;
API_SemaphoreBPost(pGpioTest->hSemBIrq);
}
/*********************************************************************************************************
** 函数名称: gpioDrvExample3
** 功能描述: gpio 中断例程
** 输 入: NONE
** 输 出: ERROR_CODE
*********************************************************************************************************/
INT gpioDrvExample3 (VOID)
{
INT iRet;
GPIO_TEST gpioTest;
GPIO_IRQ gpioIrq;
printf("Gpio interrupt example. Waiting press the key SW8.\n");
gpioIrq.uiGpio = KEY08;
gpioIrq.ulFlags = LW_GPIODF_TRIG_FALL;
gpioIrq.pFunc = gpioDrvExample3CallBack;
gpioIrq.pvArg = (PVOID)&gpioTest;
gpioIrq.pcLabel = "key";
gpioIrq.pcIrqName = "key_isr";
iRet = API_GpioIrqRequest(&gpioIrq);
if (iRet != ERROR_NONE) {
return (PX_ERROR);
}
gpioTest.uiGpioLed = LED02;
gpioTest.uiIrqCount = 0;
gpioTest.hSemBIrq = API_SemaphoreBCreate("gpioTest",
LW_FALSE,
LW_OPTION_OBJECT_LOCAL |
LW_OPTION_WAIT_PRIORITY,
LW_NULL);
API_GpioRequestOne(gpioTest.uiGpioLed, LW_GPIOF_OUT_INIT_LOW, "LED");
while (1) {
API_SemaphoreBPend(gpioTest.hSemBIrq, LW_OPTION_WAIT_INFINITE);
printf("The key effective, uiIrqCount = %d\n", gpioTest.uiIrqCount);
API_GpioSetValue(gpioTest.uiGpioLed, gpioTest.uiIrqCount & 0x01);
}
API_GpioIrqFree(&gpioIrq);
API_GpioFree(gpioTest.uiGpioLed);
return (ERROR_NONE);
}
/*********************************************************************************************************
END
*********************************************************************************************************/