GPIO Drv API
GPIO 除了在应用层中使用外,其实更多的是在其他复杂驱动中调用。比如SD卡驱动中要使用一个GPIO来监测卡的插入与拔出,网卡驱动中需要使用一个GPIO来控制phy芯片硬复位,某些情况需要用GPIO来模拟I2C总线等等。驱动中使用GPIO时,为了提高效率并不是调用GPIO设备文件,而是使用SylixOS提供的GPIO调用接口。
/*********************************************************************************************************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);
GPIO Drv API的实现基于GPIO控制器对象,实现相对简单,主要包括数据有效性检查,数据管理,防止重如保护,参数类型转换,调用GPIO控制器对象中的相应回调函数等。SylixOS通过一个双向链表来管理GPIO控制器对象,通过一个结构体数组来管理所有GPIO。
数据定义及宏定义
#define __SYLIXOS_KERNEL
#include "../SylixOS/kernel/include/k_kernel.h"
#include "../SylixOS/system/include/s_system.h"
/*********************************************************************************************************裁剪宏 *********************************************************************************************************/
#if LW_CFG_GPIO_EN > 0
/*********************************************************************************************************内部变量 *********************************************************************************************************/
static LW_LIST_LINE_HEADER _G_plineGpioChips; /* 驱动程序链表 */
static LW_GPIO_DESC _G_gdesc[LW_CFG_MAX_GPIOS]; /* 每个管脚描述符 */
static LW_SPINLOCK_DEFINE (_G_slGpio);
/*********************************************************************************************************内部操作宏 *********************************************************************************************************/
#define GPIO_LOCK(pintreg) LW_SPIN_LOCK_QUICK(&_G_slGpio, (pintreg))
#define GPIO_UNLOCK(intreg) LW_SPIN_UNLOCK_QUICK(&_G_slGpio, (intreg))#define GPIO_CHIP_HWGPIO(pgdesc) ((pgdesc) - &(pgdesc)->GD_pgcChip->GC_gdDesc[0])
#define GPIO_TO_DESC(gpio) (&_G_gdesc[(gpio)])
#define DESC_TO_GPIO(pgdesc) ((pgdesc)->GD_pgcChip->GC_uiBase + GPIO_CHIP_HWGPIO(pgdesc))#define GPIO_IS_VALID(gpio) ((gpio) < LW_CFG_MAX_GPIOS)
支持函数实现
/********************************************************************************************************* ** 函数名称: __gpioGetDirection ** 功能描述: 获得指定 GPIO 方向 ** 输 入 : pgdesc GPIO 管脚描述符 ** 输 出 : 0: 输入 1: 输出 *********************************************************************************************************/
static INT __gpioGetDirection (PLW_GPIO_DESC pgdesc)
{
INT iError;PLW_GPIO_CHIP pgchip = pgdesc->GD_pgcChip;if (!pgchip->GC_pfuncGetDirection) {
return (PX_ERROR);}iError = pgchip->GC_pfuncGetDirection(pgchip, GPIO_CHIP_HWGPIO(pgdesc));if (iError > 0) {
pgdesc->GD_ulFlags |= LW_GPIODF_IS_OUT;return (1);} else if (iError == 0) {
pgdesc->GD_ulFlags &= ~LW_GPIODF_IS_OUT;return (0);} else {
return (PX_ERROR);}
}
/********************************************************************************************************* ** 函数名称: __gpioGetDesc ** 功能描述: 通过 GPIO 号获得指定 GPIO 描述符 ** 输 入 : uiGpio GPIO 号 ** bRequested 是否检查请求 ** 输 出 : GPIO 管脚描述符 *********************************************************************************************************/
static PLW_GPIO_DESC __gpioGetDesc (UINT uiGpio, BOOL bRequested)
{
PLW_GPIO_DESC pgdesc;if (!GPIO_IS_VALID(uiGpio)) {
return (LW_NULL);}pgdesc = GPIO_TO_DESC(uiGpio);if (bRequested && !(pgdesc->GD_ulFlags & LW_GPIODF_REQUESTED)) {
return (LW_NULL);}return (pgdesc);
}
/********************************************************************************************************* ** 函数名称: __gpioSetValueOpenDrain ** 功能描述: 设置一个 OPEN DRAIN 属性的 GPIO ** 输 入 : pgdesc GPIO 管脚描述符 ** iValue 设置的值 ** 输 出 : NONE *********************************************************************************************************/
static VOID __gpioSetValueOpenDrain (PLW_GPIO_DESC pgdesc, INT iValue)
{
INT iError;PLW_GPIO_CHIP pgchip = pgdesc->GD_pgcChip;if (iValue) {
iError = pgchip->GC_pfuncDirectionInput(pgchip, GPIO_CHIP_HWGPIO(pgdesc));if (iError == ERROR_NONE) {
pgdesc->GD_ulFlags &= ~LW_GPIODF_IS_OUT;}} else {
iError = pgchip->GC_pfuncDirectionOutput(pgchip, GPIO_CHIP_HWGPIO(pgdesc), 0);if (iError == ERROR_NONE) {
pgdesc->GD_ulFlags |= LW_GPIODF_IS_OUT;}}
}
/********************************************************************************************************* ** 函数名称: __gpioSetValueOpenSource ** 功能描述: 设置一个 OPEN SOURCE 属性的 GPIO ** 输 入 : pgdesc GPIO 管脚描述符 ** iValue 设置的值 ** 输 出 : NONE *********************************************************************************************************/
static VOID __gpioSetValueOpenSource (PLW_GPIO_DESC pgdesc, INT iValue)
{
INT iError;PLW_GPIO_CHIP pgchip = pgdesc->GD_pgcChip;if (iValue) {
iError = pgchip->GC_pfuncDirectionOutput(pgchip, GPIO_CHIP_HWGPIO(pgdesc), 1);if (iError == ERROR_NONE) {
pgdesc->GD_ulFlags |= LW_GPIODF_IS_OUT;}} else {
iError = pgchip->GC_pfuncDirectionInput(pgchip, GPIO_CHIP_HWGPIO(pgdesc));if (iError == ERROR_NONE) {
pgdesc->GD_ulFlags &= ~LW_GPIODF_IS_OUT;}}
}
GPIO 控制器对象操作接口
/********************************************************************************************************* ** 函数名称: _GpioInit ** 功能描述: 初始化 GPIO 库 ** 输 入 : NONE ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioInit (VOID)
{
LW_SPIN_INIT(&_G_slGpio);
}
/********************************************************************************************************* ** 函数名称: API_GpioChipAdd ** 功能描述: 加入一个 GPIO 芯片驱动 ** 输 入 : pgchip GPIO 驱动 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioChipAdd (PLW_GPIO_CHIP pgchip)
{
INTREG iregInterLevel;UINT i;PLW_LIST_LINE plineTemp;PLW_LIST_LINE plinePrev;PLW_GPIO_CHIP pgchipTemp;if (!pgchip) {
_ErrorHandle(EINVAL);return (PX_ERROR);}if (pgchip->GC_ulVerMagic != LW_GPIO_VER_MAGIC) {
/* 驱动不匹配 */_DebugHandle(__ERRORMESSAGE_LEVEL, "GPIO driver version not matching to current system.\r\n");_ErrorHandle(EFTYPE);return (PX_ERROR);}if ((!GPIO_IS_VALID(pgchip->GC_uiBase)) || (!GPIO_IS_VALID(pgchip->GC_uiBase + pgchip->GC_uiNGpios - 1))) {
_ErrorHandle(EINVAL);return (PX_ERROR);}GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */for (plineTemp = _G_plineGpioChips;plineTemp != LW_NULL;plineTemp = _list_line_get_next(plineTemp)) {
pgchipTemp = _LIST_ENTRY(plineTemp, LW_GPIO_CHIP, GC_lineManage);if (pgchipTemp->GC_uiBase >= (pgchip->GC_uiBase + pgchip->GC_uiNGpios)) {
break;}}if (plineTemp) {
plinePrev = _list_line_get_prev(plineTemp);if (plinePrev) {
pgchipTemp = _LIST_ENTRY(plinePrev, LW_GPIO_CHIP, GC_lineManage);if ((pgchipTemp->GC_uiBase + pgchipTemp->GC_uiNGpios) > pgchip->GC_uiBase) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */_DebugHandle(__ERRORMESSAGE_LEVEL, "GPIO integer space overlap, cannot add chip.\r\n");_ErrorHandle(EBUSY);return (PX_ERROR);}}_List_Line_Add_Left(&pgchip->GC_lineManage, plineTemp);} else if (_G_plineGpioChips) {
/* 新加入点 base 最大 */_List_Line_Add_Right(&pgchip->GC_lineManage, &pgchipTemp->GC_lineManage);} else {
_List_Line_Add_Ahead(&pgchip->GC_lineManage, &_G_plineGpioChips);}pgchip->GC_gdDesc = &_G_gdesc[pgchip->GC_uiBase];for (i = 0; i < pgchip->GC_uiNGpios; i++) {
PLW_GPIO_DESC pgdesc = &pgchip->GC_gdDesc[i];pgdesc->GD_pgcChip = pgchip;if (pgchip->GC_pfuncDirectionInput == LW_NULL) {
/* 没有输入功能 */pgdesc->GD_ulFlags = LW_GPIODF_IS_OUT;} else {
pgdesc->GD_ulFlags = 0ul; /* 默认为输入态(芯片都这样设计)*/}}GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */return (ERROR_NONE);
}
/********************************************************************************************************* ** 函数名称: API_GpioChipDelete ** 功能描述: 删除一个 GPIO 芯片驱动 ** 输 入 : pgchip GPIO 驱动 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioChipDelete (PLW_GPIO_CHIP pgchip)
{
INTREG iregInterLevel;UINT i;if (!pgchip) {
_ErrorHandle(EINVAL);return (PX_ERROR);}GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */for (i = 0; i < pgchip->GC_uiNGpios; i++) {
if (pgchip->GC_gdDesc[i].GD_ulFlags & LW_GPIODF_REQUESTED) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */_ErrorHandle(EBUSY);return (PX_ERROR);}}for (i = 0; i < pgchip->GC_uiNGpios; i++) {
pgchip->GC_gdDesc[i].GD_pgcChip = LW_NULL;}_List_Line_Del(&pgchip->GC_lineManage, &_G_plineGpioChips);GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */return (ERROR_NONE);
}
/********************************************************************************************************* ** 函数名称: API_GpioChipFind ** 功能描述: 查询一个 GPIO 芯片驱动 ** 输 入 : pvData 匹配函数参数 ** pfuncMatch 查询匹配函数 (此函数返回 LW_TRUE 表示找到) ** 输 出 : 查询到的驱动结构 *********************************************************************************************************/
LW_API
PLW_GPIO_CHIP API_GpioChipFind (PVOID pvData, BOOL (*pfuncMatch)(PLW_GPIO_CHIP pgchip, PVOID pvData))
{
INTREG iregInterLevel;PLW_GPIO_CHIP pgchip;PLW_LIST_LINE plineTemp;if (!pfuncMatch) {
_ErrorHandle(EINVAL);return (LW_NULL);}GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */for (plineTemp = _G_plineGpioChips;plineTemp != LW_NULL;plineTemp = _list_line_get_next(plineTemp)) {
pgchip = _LIST_ENTRY(plineTemp, LW_GPIO_CHIP, GC_lineManage);if (pfuncMatch(pgchip, pvData)) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */return (pgchip);}}GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */return (LW_NULL);
}
常用GPIO操作接口
/********************************************************************************************************* ** 函数名称: API_GpioRequest ** 功能描述: 请求使用一个 GPIO ** 输 入 : uiGpio 请求 GPIO 号 ** pcLabel 标签 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioRequest (UINT uiGpio, CPCHAR pcLabel)
{
INTREG iregInterLevel;INT iError;PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;if (!GPIO_IS_VALID(uiGpio)) {
_ErrorHandle(EINVAL);return (PX_ERROR);}pgdesc = GPIO_TO_DESC(uiGpio);GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */pgchip = pgdesc->GD_pgcChip;if (!pgchip) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */_ErrorHandle(EINVAL);return (PX_ERROR);}if (pgdesc->GD_ulFlags & LW_GPIODF_REQUESTED) {
/* 已经在使用中 */GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */_ErrorHandle(EBUSY);return (PX_ERROR);}pgdesc->GD_ulFlags |= LW_GPIODF_REQUESTED;pgdesc->GD_pcLabel = pcLabel ? pcLabel : "?";if (pgchip->GC_pfuncRequest) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */iError = pgchip->GC_pfuncRequest(pgchip, GPIO_CHIP_HWGPIO(pgdesc));GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */if (iError < ERROR_NONE) {
pgdesc->GD_ulFlags &= ~LW_GPIODF_REQUESTED;pgdesc->GD_pcLabel = LW_NULL;GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */return (iError);}}if (pgchip->GC_pfuncGetDirection) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */__gpioGetDirection(pgdesc);} else {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */}return (ERROR_NONE);
}
/********************************************************************************************************* ** 函数名称: API_GpioRequestOne ** 功能描述: 请求使用一个 GPIO ** 输 入 : uiGpio 请求 GPIO 号 ** ulFlags 需要设置的属性 ** pcLabel 标签 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioRequestOne (UINT uiGpio, ULONG ulFlags, CPCHAR pcLabel)
{
INT iError;PLW_GPIO_DESC pgdesc;iError = API_GpioRequest(uiGpio, pcLabel);if (iError < ERROR_NONE) {
return (iError);}pgdesc = GPIO_TO_DESC(uiGpio);if (ulFlags & LW_GPIOF_OPEN_DRAIN) {
pgdesc->GD_ulFlags |= LW_GPIODF_OPEN_DRAIN;}if (ulFlags & LW_GPIOF_OPEN_SOURCE) {
pgdesc->GD_ulFlags |= LW_GPIODF_OPEN_SOURCE;}if (ulFlags & LW_GPIOF_DIR_IN) {
iError = API_GpioDirectionInput(uiGpio);} else {
iError = API_GpioDirectionOutput(uiGpio, (ulFlags & LW_GPIOF_INIT_HIGH) ? 1 : 0);}if (iError < ERROR_NONE) {
API_GpioFree(uiGpio);return (iError);}return (ERROR_NONE);
}
/********************************************************************************************************* ** 函数名称: API_GpioFree ** 功能描述: 释放使用一个 GPIO ** 输 入 : uiGpio GPIO 号 ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioFree (UINT uiGpio)
{
INTREG iregInterLevel;PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
return;}GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */pgchip = pgdesc->GD_pgcChip;if (pgchip && (pgdesc->GD_ulFlags & LW_GPIODF_REQUESTED)) {
if (pgchip->GC_pfuncFree) {
GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */pgchip->GC_pfuncFree(pgchip, GPIO_CHIP_HWGPIO(pgdesc));GPIO_LOCK(&iregInterLevel); /* 锁定 GPIO */}pgdesc->GD_ulFlags &= ~(LW_GPIODF_REQUESTED | LW_GPIODF_TRIGGER_MASK);pgdesc->GD_pcLabel = LW_NULL;}GPIO_UNLOCK(iregInterLevel); /* 解锁 GPIO */
}/********************************************************************************************************* ** 函数名称: API_GpioDirectionInput ** 功能描述: 设置指定 GPIO 为输入模式 ** 输 入 : uiGpio GPIO 号 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioDirectionInput (UINT uiGpio)
{
INT iError;PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (PX_ERROR);}pgchip = pgdesc->GD_pgcChip;if (!pgchip || !pgchip->GC_pfuncGet || !pgchip->GC_pfuncDirectionInput) {
_ErrorHandle(ENOTSUP);return (PX_ERROR);}iError = pgchip->GC_pfuncDirectionInput(pgchip, GPIO_CHIP_HWGPIO(pgdesc));if (iError == ERROR_NONE) {
pgdesc->GD_ulFlags &= ~LW_GPIODF_IS_OUT;}return (iError);
}
/********************************************************************************************************* ** 函数名称: API_GpioDirectionOutput ** 功能描述: 设置指定 GPIO 为输出模式 ** 输 入 : uiGpio GPIO 号 ** iValue 1: 高电平 0: 低电平 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioDirectionOutput (UINT uiGpio, INT iValue)
{
INT iError;PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (PX_ERROR);}pgchip = pgdesc->GD_pgcChip;if (!pgchip || !pgchip->GC_pfuncSet || !pgchip->GC_pfuncDirectionOutput) {
_ErrorHandle(ENOTSUP);return (PX_ERROR);}iError = pgchip->GC_pfuncDirectionOutput(pgchip, GPIO_CHIP_HWGPIO(pgdesc), iValue);if (iError == ERROR_NONE) {
pgdesc->GD_ulFlags |= LW_GPIODF_IS_OUT;}return (iError);
}
/********************************************************************************************************* ** 函数名称: API_GpioGetValue ** 功能描述: 获取指定 GPIO 的值 ** 输 入 : uiGpio GPIO 号 ** 输 出 : GPIO 当前电平状态 1: 高电平 0: 低电平 *********************************************************************************************************/
LW_API
INT API_GpioGetValue (UINT uiGpio)
{
PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = GPIO_TO_DESC(uiGpio); /* 不做任何检查, 加快速度 */pgchip = pgdesc->GD_pgcChip;return (pgchip->GC_pfuncGet(pgchip, GPIO_CHIP_HWGPIO(pgdesc)));
}
/********************************************************************************************************* ** 函数名称: API_GpioSetValue ** 功能描述: 设置指定 GPIO 的值 ** 输 入 : uiGpio GPIO 号 ** iValue 1: 高电平 0: 低电平 ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioSetValue (UINT uiGpio, INT iValue)
{
PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = GPIO_TO_DESC(uiGpio); /* 不做任何检查, 加快速度 */pgchip = pgdesc->GD_pgcChip;if (pgdesc->GD_ulFlags & LW_GPIODF_OPEN_DRAIN) {
__gpioSetValueOpenDrain(pgdesc, iValue);} else if (pgdesc->GD_ulFlags & LW_GPIODF_OPEN_SOURCE) {
__gpioSetValueOpenSource(pgdesc, iValue);} else {
pgchip->GC_pfuncSet(pgchip, GPIO_CHIP_HWGPIO(pgdesc), iValue);}
}
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)
{
PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (LW_VECTOR_INVALID);}pgchip = pgdesc->GD_pgcChip;if (pgchip->GC_pfuncGetIrq) {
return (pgchip->GC_pfuncGetIrq(pgchip, GPIO_CHIP_HWGPIO(pgdesc), bIsLevel, uiType));} else {
_ErrorHandle(ENXIO);return (LW_VECTOR_INVALID);}
}
/********************************************************************************************************* ** 函数名称: 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)
{
ULONG ulVector;PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (LW_VECTOR_INVALID);}pgchip = pgdesc->GD_pgcChip;if (pgchip->GC_pfuncSetupIrq) {
ulVector = pgchip->GC_pfuncSetupIrq(pgchip, GPIO_CHIP_HWGPIO(pgdesc), bIsLevel, uiType);if (ulVector != LW_VECTOR_INVALID) {
/* 外部中断设置成功 */if (bIsLevel) {
pgdesc->GD_ulFlags |= LW_GPIODF_TRIG_LEVEL;}if (uiType == 0) {
pgdesc->GD_ulFlags |= LW_GPIODF_TRIG_FALL;} else if (uiType == 1) {
pgdesc->GD_ulFlags |= LW_GPIODF_TRIG_RISE;} else if (uiType == 2) {
pgdesc->GD_ulFlags |= (LW_GPIODF_TRIG_FALL | LW_GPIODF_TRIG_RISE);}}return (ulVector);} else {
_ErrorHandle(ENXIO);return (LW_VECTOR_INVALID);}
}
/********************************************************************************************************* ** 函数名称: API_GpioClearIrq ** 功能描述: GPIO 为外部中断输入模式时, 在中断上下文中清除中断请求操作 ** 输 入 : uiGpio GPIO 号 ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioClearIrq (UINT uiGpio)
{
PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = GPIO_TO_DESC(uiGpio); /* 不做任何检查, 加快速度 */pgchip = pgdesc->GD_pgcChip;if (pgchip->GC_pfuncClearIrq) {
pgchip->GC_pfuncClearIrq(pgchip, GPIO_CHIP_HWGPIO(pgdesc));}
}
/********************************************************************************************************* ** 函数名称: API_GpioSvrIrq ** 功能描述: GPIO 为外部中断输入模式时, 判断当前是否为指定的 GPIO 中断 ** 输 入 : uiGpio GPIO 号 ** 输 出 : LW_IRQ_HANDLED 表示当前中断是指定 GPIO 产生的中断 ** LW_IRQ_NONE 表示当前中断不是指定 GPIO 产生的中断 *********************************************************************************************************/
LW_API
irqreturn_t API_GpioSvrIrq (UINT uiGpio)
{
irqreturn_t irqret = LW_IRQ_NONE;PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = GPIO_TO_DESC(uiGpio); /* 不做任何检查, 加快速度 */pgchip = pgdesc->GD_pgcChip;if (pgchip->GC_pfuncSvrIrq) {
irqret = pgchip->GC_pfuncSvrIrq(pgchip, GPIO_CHIP_HWGPIO(pgdesc));}return (irqret);
}
不常用GPIO操作接口实现
/********************************************************************************************************* ** 函数名称: API_GpioIsValid ** 功能描述: GPIO 号是否有效 ** 输 入 : uiGpio GPIO 号 ** 输 出 : 1: 有效 0:无效 *********************************************************************************************************/
LW_API
INT API_GpioIsValid (UINT uiGpio)
{
return (GPIO_IS_VALID(uiGpio));
}
/********************************************************************************************************* ** 函数名称: API_GpioHasDrv ** 功能描述: GPIO 是否有对应的驱动程序 ** 输 入 : uiGpio GPIO 号 ** 输 出 : 1: 有 0:无 *********************************************************************************************************/
LW_API
INT API_GpioHasDrv (UINT uiGpio)
{
PLW_GPIO_DESC pgdesc;pgdesc = GPIO_TO_DESC(uiGpio);return (pgdesc->GD_pgcChip ? 1 : 0);
}
/********************************************************************************************************* ** 函数名称: API_GpioRequestArray ** 功能描述: 请求使用一组 GPIO ** 输 入 : pgArray GPIO 数组 ** stNum 数组元素个数 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioRequestArray (PLW_GPIO pgArray, size_t stNum)
{
INT i;INT iError;if (!pgArray || !stNum) {
_ErrorHandle(EINVAL);return (PX_ERROR);}for (i = 0; i < stNum; i++, pgArray++) {
iError = API_GpioRequestOne(pgArray->G_ulGpio, pgArray->G_ulFlags, pgArray->G_pcLabel);if (iError < ERROR_NONE) {
goto __error_handle;}}return (ERROR_NONE);__error_handle:while (i) {
pgArray--;i--;API_GpioFree(pgArray->G_ulGpio);}return (iError);
}
/********************************************************************************************************* ** 函数名称: API_GpioFreeArray ** 功能描述: 释放一组 GPIO ** 输 入 : pgArray GPIO 数组 ** stNum 数组元素个数 ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioFreeArray (PLW_GPIO pgArray, size_t stNum)
{
if (!pgArray) {
return;}while (stNum) {
API_GpioFree(pgArray->G_ulGpio);pgArray++;stNum--;}
}
/********************************************************************************************************* ** 函数名称: API_GpioGetFlags ** 功能描述: 获取一个 GPIO flags ** 输 入 : uiGpio 请求 GPIO 号 ** pulFlags 获取的 flags ** 输 出 : NONE *********************************************************************************************************/
LW_API
INT API_GpioGetFlags (UINT uiGpio, ULONG *pulFlags)
{
PLW_GPIO_DESC pgdesc;if (!pulFlags) {
_ErrorHandle(EINVAL);return (PX_ERROR);}pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (PX_ERROR);}*pulFlags = pgdesc->GD_ulFlags;return (ERROR_NONE);
}
/********************************************************************************************************* ** 函数名称: API_GpioOpenDrain ** 功能描述: 设置一个 GPIO OPEN DRAIN 参数 ** 输 入 : uiGpio 请求 GPIO 号 ** bOpenDrain 参数 ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioOpenDrain (UINT uiGpio, BOOL bOpenDrain)
{
PLW_GPIO_DESC pgdesc;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
return;}if (bOpenDrain) {
pgdesc->GD_ulFlags |= LW_GPIODF_OPEN_DRAIN;} else {
pgdesc->GD_ulFlags &= ~LW_GPIODF_OPEN_DRAIN;}
}
/********************************************************************************************************* ** 函数名称: API_GpioOpenSource ** 功能描述: 设置一个 GPIO OPEN SOURCE 参数 ** 输 入 : uiGpio 请求 GPIO 号 ** bOpenSource 参数 ** 输 出 : NONE *********************************************************************************************************/
LW_API
VOID API_GpioOpenSource (UINT uiGpio, BOOL bOpenSource)
{
PLW_GPIO_DESC pgdesc;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
return;}if (bOpenSource) {
pgdesc->GD_ulFlags |= LW_GPIODF_OPEN_SOURCE;} else {
pgdesc->GD_ulFlags &= ~LW_GPIODF_OPEN_SOURCE;}
}
/********************************************************************************************************* ** 函数名称: API_GpioSetDebounce ** 功能描述: 设置指定 GPIO 去抖动时间参数 ** 输 入 : uiGpio GPIO 号 ** uiDebounce 去抖动时间参数 ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioSetDebounce (UINT uiGpio, UINT uiDebounce)
{
PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (PX_ERROR);}pgchip = pgdesc->GD_pgcChip;if (!pgchip || !pgchip->GC_pfuncSetDebounce) {
_ErrorHandle(ENOTSUP);return (PX_ERROR);}return (pgchip->GC_pfuncSetDebounce(pgchip, GPIO_CHIP_HWGPIO(pgdesc), uiDebounce));
}
/********************************************************************************************************* ** 函数名称: API_GpioSetPull ** 功能描述: 设置指定 GPIO 上下拉参数 ** 输 入 : uiGpio GPIO 号 ** uiType 上下拉参数 0: 开路 1: 上拉 pull up 2: 下拉 pull down ** 输 出 : ERROR_NONE or PX_ERROR *********************************************************************************************************/
LW_API
INT API_GpioSetPull (UINT uiGpio, UINT uiType)
{
PLW_GPIO_DESC pgdesc;PLW_GPIO_CHIP pgchip;pgdesc = __gpioGetDesc(uiGpio, LW_TRUE);if (!pgdesc) {
_ErrorHandle(EINVAL);return (PX_ERROR);}pgchip = pgdesc->GD_pgcChip;if (!pgchip || !pgchip->GC_pfuncSetPull) {
_ErrorHandle(ENOTSUP);return (PX_ERROR);}return (pgchip->GC_pfuncSetPull(pgchip, GPIO_CHIP_HWGPIO(pgdesc), uiType));
}