为了方便对GPIO驱动进行测试,特意开发了通用GPIO测试工具,该工具同时也可用于GPIO硬件测试和GPIO应用开发参考。
in/out/irq
分别代表输入模式,输出模式和中断模式。如果是输出模式还可以后跟一个数字参数,指定输出是高电平(非0)或低电平(0)。如果是中断模式,后跟一个参数来指定触发类型,high(高电平触发)/low(低电平触发)/rise(上升沿触发)/fall(下降沿触发)/edge(双边沿触发)
。/*********************************************************************************************************
**
** 中国软件开源组织
**
** 嵌入式实时操作系统
**
** SylixOS(TM) LW : long wing
**
** Copyright All Rights Reserved
**
**--------------文件信息--------------------------------------------------------------------------------
**
** 文 件 名: gpioAccessCmd.c
**
** 创 建 人: Hou.JinYu (侯进宇)
**
** 文件创建日期: 2019 年 10 月 17 日
**
** 描 述: 通用 GPIO 测试工具
*********************************************************************************************************/
#include
#include
#include
#include
#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
*********************************************************************************************************/