在驱动层使用GPIO

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/ScilogyHunter/article/details/100164562

使用情景

GPIO 除了在应用层中使用外,其实更多的是在其他复杂驱动中调用。比如SD卡驱动中要使用一个GPIO来监测卡的插入与拔出,网卡驱动中需要使用一个GPIO来控制phy芯片硬复位,某些情况需要用GPIO来模拟I2C总线等等。驱动中使用GPIO时,为了提高效率并不是调用GPIO设备文件,而是使用SylixOS提供的GPIO调用接口。

GPIO API

/*********************************************************************************************************
  GPIO API (以下 API 仅供驱动程序内部使用, 应用程序不可使用)
*********************************************************************************************************/
LW_API VOID             API_GpioInit(VOID);
LW_API INT              API_GpioChipAdd(PLW_GPIO_CHIP pgchip);
LW_API INT              API_GpioChipDelete(PLW_GPIO_CHIP pgchip);
LW_API PLW_GPIO_CHIP    API_GpioChipFind(PVOID pvData, BOOL (*pfuncMatch)(PLW_GPIO_CHIP pgchip, PVOID  pvData));                                
LW_API INT              API_GpioIsValid(UINT uiGpio);
LW_API INT              API_GpioHasDrv(UINT uiGpio);
LW_API INT              API_GpioRequest(UINT uiGpio, CPCHAR pcLabel);
LW_API INT              API_GpioRequestOne(UINT uiGpio, ULONG ulFlags, CPCHAR pcLabel);
LW_API VOID             API_GpioFree(UINT uiGpio);
LW_API INT              API_GpioRequestArray(PLW_GPIO pgArray, size_t stNum);
LW_API VOID             API_GpioFreeArray(PLW_GPIO pgArray, size_t stNum);
LW_API INT              API_GpioGetFlags(UINT uiGpio, ULONG *pulFlags);
LW_API VOID             API_GpioOpenDrain(UINT uiGpio, BOOL bOpenDrain);
LW_API VOID             API_GpioOpenSource(UINT uiGpio, BOOL bOpenSource);
LW_API INT              API_GpioSetDebounce(UINT uiGpio, UINT uiDebounce);
LW_API INT              API_GpioSetPull(UINT uiGpio, UINT uiType);
LW_API INT              API_GpioDirectionInput(UINT uiGpio);
LW_API INT              API_GpioDirectionOutput(UINT uiGpio, INT iValue);
LW_API INT              API_GpioGetValue(UINT uiGpio);
LW_API VOID             API_GpioSetValue(UINT uiGpio, INT iValue);
LW_API ULONG            API_GpioGetIrq(UINT uiGpio, BOOL bIsLevel, UINT uiType);
LW_API ULONG            API_GpioSetupIrq(UINT uiGpio, BOOL bIsLevel, UINT uiType);
LW_API VOID             API_GpioClearIrq(UINT uiGpio);
LW_API irqreturn_t      API_GpioSvrIrq(UINT uiGpio);

同时系统还对这些API函数进行了宏定义

#define gpioInit                API_GpioInit
#define gpioChipAdd             API_GpioChipAdd
#define gpioChipDelete          API_GpioChipDelete
#define gpioChipFind            API_GpioChipFind
#define gpioIsValid             API_GpioIsValid
#define gpioHasDrv              API_GpioHasDrv
#define gpioRequest             API_GpioRequest
#define gpioRequestOne          API_GpioRequestOne
#define gpioFree                API_GpioFree
#define gpioRequestArray        API_GpioRequestArray
#define gpioFreeArray           API_GpioFreeArray
#define gpioGetFlags            API_GpioGetFlags
#define gpioOpenDrain           API_GpioOpenDrain
#define gpioOpenSource          API_GpioOpenSource
#define gpioSetDebounce         API_GpioSetDebounce
#define gpioSetPull             API_GpioSetPull
#define gpioDirectionInput      API_GpioDirectionInput
#define gpioDirectionOutput     API_GpioDirectionOutput
#define gpioGetValue            API_GpioGetValue
#define gpioSetValue            API_GpioSetValue
#define gpioGetIrq              API_GpioGetIrq
#define gpioSetupIrq            API_GpioSetupIrq
#define gpioClearIrq            API_GpioClearIrq
#define gpioSvrIrq              API_GpioSvrIrq

常用接口

一般使用GPIO也就是读取一下输入电平或控制输出电平,不需要太复杂的操作,只需要调用下面4个函数即可。

/*********************************************************************************************************
** 函数名称: API_GpioRequestOne
** 功能描述: 请求使用一个 GPIO
** 输 入  : uiGpio        请求 GPIO 号
**           ulFlags       需要设置的属性
**           pcLabel       标签
** 输 出  : ERROR_NONE or PX_ERROR
*********************************************************************************************************/
LW_API INT  API_GpioRequestOne(UINT uiGpio, ULONG ulFlags, CPCHAR pcLabel);
/*********************************************************************************************************
** 函数名称: API_GpioGetValue
** 功能描述: 获取指定 GPIO 的值
** 输 入  : uiGpio        GPIO 号
** 输 出  : GPIO 当前电平状态 1: 高电平 0: 低电平
** 注  意  : 此函数不做任何参数有效性判断, 所以用户必须保证 uiGpio 已经请求成功, 方向与其他参数设置正确.
*********************************************************************************************************/
LW_API INT  API_GpioGetValue(UINT uiGpio);
/*********************************************************************************************************
** 函数名称: API_GpioSetValue
** 功能描述: 设置指定 GPIO 的值
** 输 入  : uiGpio        GPIO 号
**           iValue        1: 高电平 0: 低电平
** 输 出  : NONE
** 注  意  : 此函数不做任何参数有效性判断, 所以用户必须保证 uiGpio 已经请求成功, 方向与其他参数设置正确.
*********************************************************************************************************/
LW_API VOID  API_GpioSetValue(UINT uiGpio, INT iValue);
/*********************************************************************************************************
** 函数名称: API_GpioFree
** 功能描述: 释放使用一个 GPIO
** 输 入  : uiGpio        GPIO 号
** 输 出  : NONE
*********************************************************************************************************/
LW_API VOID   API_GpioFree(UINT uiGpio);

这些 API 都是内核态下接口,仅能在驱动程序内部使用, 用户态下应用程序中不可使用。使用前需要包含 “SylixOS.h” 头文件。
首先调用 API_GpioRequestOne 函数,打开并按照 ulFlags 参数初始化GPIO。只有打开GPIO后才能调用其他接口函数。后面就可以根据GPIO是输入还是输出模式去分别调用 API_GpioGetValueAPI_GpioSetValue 函数进行操作了。如果该GPIO不再使用,需要调用 API_GpioFree 函数进行释放。
ulFlags 参数与 gpiofd 函数的 flags 参数相似,用于配置GPIO相关的一些属性。具体有如下选项:

#define LW_GPIOF_DIR_OUT                (0 << 0)
#define LW_GPIOF_DIR_IN                 (1 << 0)
#define LW_GPIOF_INIT_LOW               (0 << 1)
#define LW_GPIOF_INIT_HIGH              (1 << 1)
#define LW_GPIOF_IN                     (LW_GPIOF_DIR_IN)
#define LW_GPIOF_OUT_INIT_LOW           (LW_GPIOF_DIR_OUT | LW_GPIOF_INIT_LOW)
#define LW_GPIOF_OUT_INIT_HIGH          (LW_GPIOF_DIR_OUT | LW_GPIOF_INIT_HIGH)
#define LW_GPIOF_OPEN_DRAIN             (1 << 2)
#define LW_GPIOF_OPEN_SOURCE            (1 << 3)

演示例程

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: gpioDrvExample1.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                   */
/*********************************************************************************************************
** 函数名称: gpioDrvExample1
** 功能描述: gpio 轮询读取例程
** 输    入: NONE
** 输    出: ERROR_CODE
*********************************************************************************************************/
INT  gpioDrvExample1 (VOID)
{
    UINT8  ucValue;

    printf("Gpio poll example. Waiting press the key SW8.\n");

    API_GpioRequestOne(KEY08, LW_GPIOF_IN, "KEY08");
    API_GpioRequestOne(LED02, LW_GPIOF_OUT_INIT_LOW, "LED02");

    while (1) {
        ucValue = API_GpioGetValue(KEY08);                              /*  读取当前按键值              */
        printf("The key value = %d\n", ucValue);
        API_GpioSetValue(LED02, ucValue);                               /*  设置LED引脚输出             */
        sleep(1);
    }

    API_GpioFree(KEY08);
    API_GpioFree(LED02);

    return  (ERROR_NONE);
}
/*********************************************************************************************************
  END
*********************************************************************************************************/

实现效果和 《在应用层使用GPIO》中的 gpioExample1 例程的一样。

猜你喜欢

转载自blog.csdn.net/ScilogyHunter/article/details/100164562