上一篇讲了在驱动层如何使用GPIO的API函数进行简单的GPIO输入和输出功能,这一篇讲如何在驱动层使用GPIO的中断功能。有些复杂驱动是要借助GPIO的中断功能来实现自身对系统的中断通知的。如下图所示的 FXOS8700CQ 三轴磁力计芯片的单元电路中,除了要使用一路I2C接口与CPU通信外,还有 INT1,INT2两个中断脚用于向CPU发送中断信号,主动告知CPU检测到状态有变化。这两个中断引脚就是连接到两个GPIO的,GPIO要设置为下降沿触发模式。
/*********************************************************************************************************
** 函数名称: API_GpioGetIrq
** 功能描述: 根据指定 GPIO 号返回对应的 IRQ 号
** 输 入 : uiGpio GPIO 号
** bIsLevel 是否为电平触发
** uiType 如果为电平触发, 1 表示高电平触发, 0 表示低电平触发
** 如果为边沿触发, 1 表示上升沿触发, 0 表示下降沿触发, 2 表示双边沿触发
** 输 出 : IRQ 号, 错误返回 LW_VECTOR_INVALID
*********************************************************************************************************/
LW_API ULONG API_GpioGetIrq(UINT uiGpio, BOOL bIsLevel, UINT uiType);
/*********************************************************************************************************
** 函数名称: API_GpioSetupIrq
** 功能描述: 根据指定 GPIO 号设置相应的外部中断, 并返回对应的 IRQ 号
** 输 入 : uiGpio GPIO 号
** bIsLevel 是否为电平触发
** uiType 如果为电平触发, 1 表示高电平触发, 0 表示低电平触发
** 如果为边沿触发, 1 表示上升沿触发, 0 表示下降沿触发, 2 表示双边沿触发
** 输 出 : IRQ 号, 错误返回 LW_VECTOR_INVALID
*********************************************************************************************************/
LW_API ULONG API_GpioSetupIrq(UINT uiGpio, BOOL bIsLevel, UINT uiType);
/*********************************************************************************************************
** 函数名称: API_GpioClearIrq
** 功能描述: GPIO 为外部中断输入模式时, 在中断上下文中清除中断请求操作
** 输 入 : uiGpio GPIO 号
** 输 出 : NONE
*********************************************************************************************************/
LW_API VOID API_GpioClearIrq(UINT uiGpio);
/*********************************************************************************************************
** 函数名称: API_GpioSvrIrq
** 功能描述: GPIO 为外部中断输入模式时, 判断当前是否为指定的 GPIO 中断
** 输 入 : uiGpio GPIO 号
** 输 出 : LW_IRQ_HANDLED 表示当前中断是指定 GPIO 产生的中断
** LW_IRQ_NONE 表示当前中断不是指定 GPIO 产生的中断
*********************************************************************************************************/
LW_API irqreturn_t API_GpioSvrIrq(UINT uiGpio);
/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: gpioDrvExample.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"
/*********************************************************************************************************
引脚宏定义
********************************************************************************************************/
#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 uiGpioKey;
UINT uiGpioLed;
UINT uiIrqCount;
ULONG ulVector;
LW_OBJECT_HANDLE hSemBIrq; /* 信号量句柄 */
} GPIO_TEST;
/*********************************************************************************************************
** 函数名称: gpioDrvExample2Isr
** 功能描述: GPIO 中断服务函数
** 输 入: pvArg 输入参数
** ulVector 中断向量
** 输 出: 中断返回值
*********************************************************************************************************/
static irqreturn_t gpioDrvExample2Isr (PVOID pvArg, ULONG ulVector)
{
irqreturn_t irqret;
GPIO_TEST *pGpioTest;
pGpioTest = (GPIO_TEST *)pvArg;
irqret = API_GpioSvrIrq(pGpioTest->uiGpioKey); /* 判断是否为指定的 GPIO 中断 */
if (LW_IRQ_HANDLED == irqret) {
pGpioTest->uiIrqCount++;
API_GpioClearIrq(pGpioTest->uiGpioKey); /* 清除中断标志,防止重复触发 */
API_SemaphoreBPost(pGpioTest->hSemBIrq);
}
return (irqret);
}
/*********************************************************************************************************
** 函数名称: gpioDrvExample2
** 功能描述: gpio 中断例程
** 输 入: NONE
** 输 出: ERROR_CODE
*********************************************************************************************************/
INT gpioDrvExample2 (VOID)
{
GPIO_TEST gpioTest;
printf("Gpio interrupt example. Waiting press the key SW8.\n");
gpioTest.uiGpioKey = KEY08;
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.uiGpioKey, LW_GPIOF_IN, "KEY");
API_GpioRequestOne(gpioTest.uiGpioLed, LW_GPIOF_OUT_INIT_LOW, "LED");
API_GpioSetupIrq(gpioTest.uiGpioKey, 0, 0); /* 设置 KEY08 为下降沿触发 */
gpioTest.ulVector = API_GpioGetIrq(gpioTest.uiGpioKey, 0, 0); /* 获取中断号 */
API_InterVectorConnect(gpioTest.ulVector, /* 注册中断服务函数 */
(PINT_SVR_ROUTINE)gpioDrvExample2Isr,
&gpioTest,
"KEY_isr");
API_InterVectorEnable(gpioTest.ulVector); /* 使能中断 */
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_GpioFree(gpioTest.uiGpioKey);
API_GpioFree(gpioTest.uiGpioLed);
return (ERROR_NONE);
}
/*********************************************************************************************************
END
*********************************************************************************************************/
说明: