通用GPIO测试工具

为了方便对GPIO驱动进行测试,特意开发了通用GPIO测试工具,该工具同时也可用于GPIO硬件测试和GPIO应用开发参考。

简要说明

  • 命令行解析基于cmdParse模块,这个模块的功能和用法会单独说明。
  • 命令每次只针对一个GPIO进行操作。
  • -id 选项指定了GPIO序号,选项参数可以是一个无符号整数,也可以是“gpio_port_pin”格式字符串(和SylixOS中GPIO序号宏定义中的格式类似,只不过那里是宏定义常数,这里是小写字符串)。
  • -oper 选项指定了操作类型(operation type),可以是in/out/irq分别代表输入模式,输出模式和中断模式。如果是输出模式还可以后跟一个数字参数,指定输出是高电平(非0)或低电平(0)。如果是中断模式,后跟一个参数来指定触发类型,high(高电平触发)/low(低电平触发)/rise(上升沿触发)/fall(下降沿触发)/edge(双边沿触发)
  • -i选项指定动作时间间隔,单位是毫秒,默认是1000毫秒;-n选项指定动作重复次数,默认是一次。
  • 对于输出模式如果执行次数不止一次,则每次输出时电平会翻转一次,便于让LED闪烁或输出某个频率的方波。在这里插入图片描述在这里插入图片描述
  • -info选项用于显示命令内部参数信息。
    在这里插入图片描述
  • -d [on/off] 选项用于控制是否打印运行信息。对于较高频率的动作执行时一般要关闭调试信息。
  • -h 选项输出帮助信息,主要是一些命令实例。
    在这里插入图片描述
  • help选项是个通用选项,会输出相应命令的选项列表。
  • 在这里插入图片描述

程序源码

/*********************************************************************************************************
**
**                                    中国软件开源组织
**
**                                   嵌入式实时操作系统
**
**                                SylixOS(TM)  LW : long wing
**
**                               Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文   件   名: gpioAccessCmd.c
**
** 创   建   人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2019 年 10 月 17 日
**
** 描        述: 通用 GPIO 测试工具
*********************************************************************************************************/
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>

#include "pthread.h"
#include "sys/gpiofd.h"
#include "cmdParse/cmdParse.h"
/*********************************************************************************************************
  操作模式
*********************************************************************************************************/
#define OPE_CLOSE               (0)                                     /*  关闭模式                    */
#define OPE_INPUT               (1)                                     /*  输入模式                    */
#define OPE_OUTPUT              (2)                                     /*  输出模式                    */
#define OPE_IRQ                 (3)                                     /*  中断模式                    */
/*********************************************************************************************************
  设备配置参数结构
*********************************************************************************************************/
typedef struct {
    uint32_t                    uiEffective;                            /*  0无效,1有效                */
    uint32_t                    uiDisplayState;                         /*  过程显示,0不显示 1显示     */
    uint32_t                    uiInterval;                             /*  运行间隔,单位毫秒          */
    uint32_t                    uiOperateNum;                           /*  计划运行次数                */
    uint32_t                    uiOperateCount;                         /*  设计运行次数                */

    uint32_t                    uiGpioId;                               /*  gpio id                     */
    uint32_t                    uiOperate;                              /*  操作类型                    */
    uint32_t                    uiValue;                                /*  操作数值                    */
    uint32_t                    uiFlags;                                /*  gpio_flags                  */

    int32_t                     iFd;                                    /*  设备文件标识符              */
    pthread_t                   tid;                                    /*  运行线程ID                  */

} DEV_ARG_ST;
/*********************************************************************************************************
** 名称: help
** 输入: cmd        命令参数
**       opti       选项索引号
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 帮助信息,列出参数列表信息
*********************************************************************************************************/
static  int  getHelp (command_st  *cmd, int opti)
{
    printf("Usage:  \n"
       "gpio  [options] [parameter]...\n"
       "gpio -id gpio_0_10 -opr in\n"
       "gpio -id gpio_0_10 -opr out 0/1\n"
       "gpio -id gpio_0_10 -opr irq high/low/rise/fall/edge\n"
       "gpio -help\n");

    return  (NONE);
}
/*********************************************************************************************************
** 名称: getInfo
** 输入: cmd        命令参数
**       opti       参数索引
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 获取 info 选项
*********************************************************************************************************/
static int  getInfo (command_st  *cmd, int opti)
{
    DEV_ARG_ST  *pArg;

    pArg = cmd->priv;
    printf("uiEffective    = %d\n",         pArg->uiEffective   );
    printf("uiDisplayState = %d\n",         pArg->uiDisplayState);
    printf("uiInterval     = %d\n",         pArg->uiInterval    );
    printf("uiOperateNum   = %d\n",         pArg->uiOperateNum  );
    printf("uiOperateCount = %d\n",         pArg->uiOperateCount);
    printf("uiGpioId       = %d\n",         pArg->uiGpioId      );
    printf("uiOperate      = %d\n",         pArg->uiOperate     );
    printf("uiValue        = %d\n",         pArg->uiValue       );
    printf("uiFlags        = %08x\n",       pArg->uiFlags       );
    printf("iFd            = %d\n",         pArg->iFd           );
    printf("tid            = %08x\n", (UINT)pArg->tid           );

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 名称: getId
** 输入: cmd        命令参数
**       opti       参数索引
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 获取 Id 选项
*********************************************************************************************************/
static int  getId (command_st  *cmd, int opti)
{
    option_st   *opt;
    DEV_ARG_ST  *pArg;

    pArg = cmd->priv;
    opt  = &cmd->optv[opti];

    if (opt->argc) {
        int  port;
        int  pin;

        if (2 == sscanf(cmd->argv[opt->index + 1], "gpio_%d_%d", &port, &pin)) {
            pArg->uiGpioId = port * 32 + pin;
        } else {
            pArg->uiGpioId = strtoul(cmd->argv[opt->index + 1], NULL, 0);
        }
    } else {
        printf("error!miss gpio id. -id xxx or -id gpio_x_y\n");
        return  (ERROR);
    }

    return  (NONE);
}
/*********************************************************************************************************
** 名称: getIn
** 输入: cmd        命令参数
**       opti       参数索引
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 获取 In 选项
*********************************************************************************************************/
static int  getOperate (command_st  *cmd, int opti)
{
    DEV_ARG_ST  *pArg;
    option_st   *opt;
    char        *type;
    char        *str;

    pArg = cmd->priv;
    opt  = &cmd->optv[opti];

    if (opt->argc > 0) {
        type = cmd->argv[opt->index + 1];
        if (strcasecmp(type, "in") == 0) {
            pArg->uiOperate = OPE_INPUT;
            pArg->uiFlags   = GPIO_FLAG_IN;
            pArg->uiValue   = 0;

        } else if (strcasecmp(type, "out") == 0) {
            pArg->uiOperate = OPE_OUTPUT;
            pArg->uiFlags   = GPIO_FLAG_OUT_INIT_LOW;
            pArg->uiValue   = 0;
            if (opt->argc > 1) {
                str = cmd->argv[opt->index + 2];
                if (strcasecmp(str, "0") == 0) {
                    pArg->uiFlags = GPIO_FLAG_OUT_INIT_LOW;
                    pArg->uiValue = 0;
                } else {
                    pArg->uiFlags = GPIO_FLAG_OUT_INIT_HIGH;
                    pArg->uiValue = 1;
                }
            }

        } else if (strcasecmp(type, "irq") == 0) {
            pArg->uiOperate = OPE_IRQ;
            pArg->uiFlags   = GPIO_FLAG_TRIG_FALL;
            pArg->uiValue   = 0;
            if (opt->argc > 1) {
                str = cmd->argv[opt->index + 2];
                if (strcasecmp(str, "high") == 0) {
                    pArg->uiFlags = GPIO_FLAG_TRIG_LEVEL | GPIO_FLAG_TRIG_RISE;
                } else if (strcasecmp(str, "low") == 0) {
                    pArg->uiFlags = GPIO_FLAG_TRIG_LEVEL | GPIO_FLAG_TRIG_FALL;
                } else if (strcasecmp(str, "rise") == 0) {
                    pArg->uiFlags = GPIO_FLAG_TRIG_RISE;
                } else if (strcasecmp(str, "fall") == 0) {
                    pArg->uiFlags = GPIO_FLAG_TRIG_FALL;
                } else if (strcasecmp(str, "edge") == 0) {
                    pArg->uiFlags = GPIO_FLAG_TRIG_FALL | GPIO_FLAG_TRIG_RISE;
                }
            }
        }
    }

    return  (NONE);
}
/*********************************************************************************************************
** 名称: devPthread
** 输入: pvArg       线程参数
** 输出: 错误码,NONE成功,ERROR错误
** 说明: 设备运行线程
*********************************************************************************************************/
static  void   *devPthread (void * pvArg)
{
    int          iFd;
    int          iError;
    uint8_t      value;
    DEV_ARG_ST  *pArg = (DEV_ARG_ST  *)pvArg;

    iFd = gpiofd(pArg->uiGpioId, O_RDWR, pArg->uiFlags);
    if (iFd < 0) {
        printf("open gpio_%d_%d failed!\n", pArg->uiGpioId / 32, pArg->uiGpioId % 32);
        return  (NULL);
    }

    pArg->iFd = iFd;
    pArg->uiOperateCount = 0;

    if (pArg->uiOperate == OPE_INPUT) {
        while(1) {
            iError = gpiofd_read(iFd, &value);
            if (iError < 0) {
                printf("gpio %d read error!\n", pArg->uiGpioId);
                break;
            }
            pArg->uiValue = value;
            if (pArg->uiDisplayState) {
                printf("gpio %d input %d\n", pArg->uiGpioId, pArg->uiValue);
            }

            pArg->uiOperateCount++;
            if (pArg->uiOperateCount >= pArg->uiOperateNum) {
                break;
            }

            usleep(pArg->uiInterval * 1000);
        }

    } else if (pArg->uiOperate == OPE_OUTPUT) {
        while(1) {
            value = pArg->uiValue;
            iError = gpiofd_write(iFd, value & 0x01);
            if (iError < 0) {
                printf("gpio %d write error!\n", pArg->uiGpioId);
                break;
            }
            if (pArg->uiDisplayState) {
                printf("gpio %d output %d\n", pArg->uiGpioId, pArg->uiValue);
            }
            usleep(pArg->uiInterval * 1000);

            pArg->uiOperateCount++;
            if (pArg->uiOperateCount >= pArg->uiOperateNum) {
                break;
            }

            pArg->uiValue = !pArg->uiValue;
        }

    } else if (pArg->uiOperate == OPE_IRQ) {
        fd_set           fdset;

        FD_ZERO(&fdset);
        while(1) {
            FD_SET(iFd, &fdset);

            iError = select(iFd + 1, &fdset, NULL, NULL, NULL);
            if (iError < 0) {
                printf("gpio %d select error! errno = %d\n", pArg->uiGpioId, iError);
                break;
            }
            if (pArg->uiDisplayState) {
                printf("gpio %d irq response. count = %u\n", pArg->uiGpioId, pArg->uiOperateCount);
            }
            pArg->uiOperateCount++;
            if (pArg->uiOperateCount >= pArg->uiOperateNum) {
                break;
            }
            usleep(pArg->uiInterval * 1000);
        }
    }

    close(pArg->iFd);
    pArg->iFd = -1;

    return  (NULL);
}
/*********************************************************************************************************
** 名称: gpioTool
** 输入: argc       参数个数
**       argv       参数列表
** 输出: 错误码,NONE成功,ERROR错误
** 说明: gpio 测试工具函数
*********************************************************************************************************/
static int gpioTool (int argc, char *argv[])
{
    DEV_ARG_ST  devArg = {
        .uiEffective    = 0,
        .uiDisplayState = 1,
        .uiInterval     = 1000,
        .uiOperateNum   = 1,
        .uiOperateCount = 0,
        .uiGpioId       = 0,
        .uiOperate      = 0,
        .uiValue        = 0,
        .uiFlags        = 0,
        .iFd            = -1,
        .tid            = 0,
    };
    option_st  optv[] = {
        {ATT_FUNC,        getHelp,                  "h",    "help info"},
        {ATT_FUNC,        getId,                    "id",   "gpio id, 32/gpio_1_0"},
        {ATT_FUNC,        getOperate,               "oper", "gpio operate type,in/out/irq"},
        {ATT_FUNC,        getInfo,                  "info", "print Info"},
        {ATT_TYPE_BOOL,   &devArg.uiDisplayState,   "d",    "display, on/off"},
        {ATT_TYPE_U32,    &devArg.uiOperateNum,     "n",    "set operate number"},
        {ATT_TYPE_U32,    &devArg.uiInterval,       "i",    "set Interval, ms"},

    };
    command_st      cmd;
    pthread_attr_t  attr;
    int             err;

    cmd.argc = argc;
    cmd.argv = argv;
    cmd.optc = GET_OPTC(optv);
    cmd.optv = optv;
    cmd.priv = &devArg;
    err = cmdParse(&cmd);

    if (err != NONE) {
        return  (err);
    }

    pthread_attr_init(&attr);
    pthread_attr_setname(&attr, "t_gpioTest");
    pthread_create(&devArg.tid, &attr, devPthread, (void *)&devArg);

    return  (ERROR_NONE);
}
/*********************************************************************************************************
** 函数名称: main
** 功能描述: 程序入口
** 输    入: argc   参数个数
**           argv   参数列表
** 输    出: ERROR_CODE
*********************************************************************************************************/
int main (int argc, char **argv)
{
    gpioTool(argc, argv);

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

发布了39 篇原创文章 · 获赞 6 · 访问量 5066

猜你喜欢

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