Use the GPIO interrupt function in the driver layer

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.
This link: https://blog.csdn.net/ScilogyHunter/article/details/100191820

Usage scenarios

Previous spoke in how to use the GPIO driver layer API function for simple GPIO input and output functions, this article about how to use the GPIO interrupt function in the driver layer. Some complex drive system is to be achieved by means of notification interrupt their GPIO interrupt function. FXOS8700CQ triaxial magnetometer unit circuit chip shown in the following figure, in addition to the way using the I2C interface communicates with the CPU, there INT1, INT2 two interrupt pin for transmitting an interrupt signal to the CPU, telling the CPU that detects the active state no change. The two interrupt pin is connected to the two GPIO, GPIO to be set as the falling edge trigger mode.
Here Insert Picture Description

Interface Description

/*********************************************************************************************************
** 函数名称: 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);

The sample program

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                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
*********************************************************************************************************/

Description:

  • Use the GPIO interrupt function, to its first initialized to the input mode, remember not set to output mode.
  • Not all will have a GPIO interrupt mode, so getting GPIO interrupt number to check its validity.
  • Need to use interrupt control API initialization and interrupt register interrupt callback function.
  • Interrupt the callback function to check the validity of the interrupt and clear interrupt flag to prevent re-triggering interrupts.
  • And achieve the effect of " used in the application layer GPIO as" the gpioExample2 routine.

Guess you like

Origin blog.csdn.net/ScilogyHunter/article/details/100191820