📄 xsgpio.c
字号:
else if (initialLevel & ~1u)
{
badParamNum = 3;
}
if (badParamNum)
{
status = ERR_T_ILLPARAM;
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_SET_DIR, status, badParamNum, 0, 0)
}
else // Now move on to checking the current state, to see
// if it's OK to perform the requested operation.
{
// Must be for GPIO mode (ERR_T_WRONG_STATE)
// with no interrupt currently registered if new
// direction is output. (ERR_T_REG_HANDLER)
currPinCfgP = XsGpioCurrentUsageTable + pinID;
if (XS_GPIO_UNAVAILABLE == currPinCfgP->fnCategory)
{
status = ERR_T_NOT_AVAIL;
}
else if (XS_GPIO_ALT_FUNC_GPIO != currPinCfgP->fnCategory)
{
status = ERR_T_WRONG_STATE;
}
else if (currPinCfgP->registeredHandlerFnP
&& (XS_GPIO_DIR_OUT == direction))
{
status = ERR_T_REG_HANDLER;
}
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_SET_DIR, status, 0, 0, 0)
}
else // Safe to do the job.
{
currPinCfgP->initialLevel = initialLevel;
currPinCfgP->direction = direction;
// Order of operations is important in HW access.
// level, then direction
// Set up addressing for register operations
XsGpioRegsCalcLocIndices ( pinID, ®Index, &bitOffset );
// For output lines only, set the level.
if (XS_GPIO_DIR_OUT == currPinCfgP->direction)
{
// Output level registers are write-only, don't read-"OR"-write
if (XS_GPIO_PIN_LEVEL_1 == currPinCfgP->initialLevel)
{
XsGpioRegsP->GPSRs[regIndex] =
XS_GPIO_PIN_LEVEL_MSK << bitOffset;
}
else // must be XS_GPIO_PIN_LEVEL_0
{
XsGpioRegsP->GPCRs[regIndex] =
XS_GPIO_PIN_LEVEL_MSK << bitOffset;
}
} // End of set level for output direction
// Set the new direction.
tempGPDR = XsGpioRegsP->GPDRs[regIndex]
& ~(XS_GPIO_PIN_LEVEL_MSK << bitOffset);
XsGpioRegsP->GPDRs[regIndex] = tempGPDR
| (direction << bitOffset);
} // else - Safe to do the job
} // else - passed parameter checks
// Lubbock_WriteHexLeds(status);
// DM_WaitMs(1000);
return(status);
} // End of XsGpioSetDirection ()
/*
*******************************************************************************
*
* FUNCTION: XsGpioRegisterHandler
*
* DESCRIPTION: Register an interrupt handling subroutine to be called
* when a specified edge transition occurs on the target GPIO
* input pin level. Also register a pointer that will be
* passed to that handler.
*
* INPUT PARAMETERS:
* XsGpioIdT pinID - GPIO pin to register handler for
* XsGpioIntTriggerEdgeT triggerType- Pin state change to trigger int:
* Rising edge, falling edge, both.
* XsGpioHandlerFnPT handlerFnP - Handler to be called for pinID int.
* void * paramP - Pointer to be passed to reg. handler
*
* RETURNS:
* Success: 0 (ERR_NONE)
* Failure: ERR_T_ILLPARAM - out of range parameter; details in err log
* ERR_T_WRONG_STATE - pin not configured as GPIO
* ERR_T_REG_HANDLER - pin already has a registered handler
*
* GLOBAL EFFECTS:
* - Required for XsGpioEnablePinInt().
* - Records last detected failure condition
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:
*
* Notes:
* - This is the only way to specify the type of edge trigger for an interrupt
* - Does not enable the interrupt: use XsGpioEnablePinInt() afterwards.
*
* PROTOTYPE: UINT32 XsGpioRegisterHandler (XsGpioIdT,
* XsGpioIntTriggerEdgeT,
* XsGpioHandlerFnPT,
* void *)
*
*******************************************************************************
*/
UINT32 XsGpioRegisterHandler ( XsGpioIdT pinID,
XsGpioIntTriggerEdgeT triggerType,
XsGpioHandlerFnPT handlerFnP,
void *paramP)
{
UINT32 status = 0; // Assume success
INT badParamNum = 0; // Which param had error. Assume no errors.
XsGpioUsageEntryT *currPinCfgP;
status = XsGpioRangeCheckPinId (pinID);
if (status)
{
badParamNum = 1;
}
else
{ // Pin ID safe, check other conditions
currPinCfgP = XsGpioCurrentUsageTable + pinID;
if ( (XS_GPIO_ALT_FUNC_GPIO != currPinCfgP->fnCategory)
|| (XS_GPIO_DIR_IN != currPinCfgP->direction))
{
status = ERR_T_WRONG_STATE;
}
if (currPinCfgP->registeredHandlerFnP)
{
status = ERR_T_REG_HANDLER;
}
if ((UINT) triggerType > (UINT) XS_GPIO_INT_BOTH_EDGES)
{
status = ERR_T_ILLPARAM;
badParamNum = 2;
}
} // else: pin ID passed range check.
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_REG_HANDLER, status, badParamNum, 0, 0)
}
else // No problems, register the handler.
{
currPinCfgP->registeredHandlerFnP = handlerFnP;
currPinCfgP->triggerCondition = triggerType;
currPinCfgP->registeredParamP = paramP;
}
return(status);
} // End XsGpioRegisterHandler ()
/*
*******************************************************************************
*
* FUNCTION: XsGpioUnRegisterHandler
*
* DESCRIPTION: Disable any interrupt on the target pin and unregister any
* registered handler on that pin. Clears any existing edge
* type specification to XS_GPIO_INT_NONE. The only error is
* out-of-range pin ID; this function no-ops quietly.
*
* INPUT PARAMETERS: XsGpioIdT pinID - GPIO pin to unregister handler for
*
* RETURNS: Success: 0 (ERR_NONE)
* Failure: ERR_T_ILLPARAM - out of range parameter
*
* GLOBAL EFFECTS: None
*
* ASSUMPTIONS: None
*
* CALLS:
*
* CALLED BY: ]
*
* PROTOTYPE: UINT32 XsGpioUnRegisterHandler (XsGpioIdT;
*
*******************************************************************************
*/
UINT32 XsGpioUnRegisterHandler (XsGpioIdT pinID)
{
UINT32 status = 0 ; // Assume success
XsGpioUsageEntryT *currPinCfgP;
status = XsGpioDisablePinInt (pinID); // Also checks pinID and all states.
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_UNR_HANDLER, status, 0, 0, 0)
}
else // All clear and interrupt disabled for pin. Unregister.
{
currPinCfgP = XsGpioCurrentUsageTable + pinID;
currPinCfgP->registeredHandlerFnP = NULL;
currPinCfgP->triggerCondition = XS_GPIO_INT_NONE;
currPinCfgP->registeredParamP = NULL;
}
return(status);
} // End XsGpioUnRegisterHandler ()
/*
*******************************************************************************
*
* FUNCTION: XsGpioEnablePinInt
*
* DESCRIPTION: Activate the existing specified edge type for triggering an
* interrupt on the target pin. An interrupt handling
* subroutine must already be registered. Performed under
* interrupt protection.
*
* INPUT PARAMETERS: XsGpioIdT pinID - GPIO pin to activate interrupt for
*
* RETURNS:
* Success: 0 (ERR_NONE)
* Failure: ERR_T_ILLPARAM - out of range parameter
* ERR_T_NO_HANDLER - pin lacks a registered handler
*
* GLOBAL EFFECTS: None
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsGpioEnablePinInt (XsGpioIdT);
*
*******************************************************************************
*/
UINT32 XsGpioEnablePinInt (XsGpioIdT pinID)
{
UINT32 status = 0 ; // Assume success
UINT32 previousIntState;
UINT32 tempGRER;
UINT32 tempGFER;
INT regIndex; // For GPIO register addressing.
INT bitOffset; // For GPIO register addressing.
XsGpioUsageEntryT *currPinCfgP;
status = XsGpioRangeCheckPinId (pinID);
if (!status)
{
currPinCfgP = XsGpioCurrentUsageTable + pinID;
if (!currPinCfgP->registeredHandlerFnP)
{
status = ERR_T_NO_HANDLER;
}
} // Finished if !status: all error states checked.
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_EN_PIN_INT, status, 0, 0, 0)
}
else
{
// Set up addressing for register operations
XsGpioRegsCalcLocIndices ( pinID, ®Index, &bitOffset );
// Set the desired values in the appropriate edge detect register(s),
// clearing out the current setting for the target pin;
// then the clear current edge detect status for a fresh start.
// Perform the register accesses under interrupt protection
// to prevent spurious interrupts.
previousIntState = IRQ_DisableInterrupts(CPSR_I_Bit|CPSR_F_Bit);
tempGRER = XsGpioRegsP->GRERs[regIndex];
tempGFER = XsGpioRegsP->GFERs[regIndex];
tempGRER &= ~(XS_GPIO_INT_EDGE_MSK << bitOffset);
tempGFER &= ~(XS_GPIO_INT_EDGE_MSK << bitOffset);
switch (currPinCfgP->triggerCondition)
{
case XS_GPIO_INT_RISING_EDGE:
tempGRER |= (XS_GPIO_INT_EDGE_MSK << bitOffset);
break;
case XS_GPIO_INT_FALLING_EDGE:
tempGFER |= (XS_GPIO_INT_EDGE_MSK << bitOffset);
break;
case XS_GPIO_INT_BOTH_EDGES:
tempGRER |= (XS_GPIO_INT_EDGE_MSK << bitOffset);
tempGFER |= (XS_GPIO_INT_EDGE_MSK << bitOffset);
break;
} // switch triggerCondition)
// Set the new trigger conditions
XsGpioRegsP->GRERs[regIndex] = tempGRER;
XsGpioRegsP->GFERs[regIndex] = tempGFER;
// Clear outstanding calls on this pin
XsGpioRegsP->GEDRs[regIndex] |= (XS_GPIO_INT_EDGE_MSK << bitOffset);
// Now record it.
currPinCfgP->interruptEnabled = TRUE;
IRQ_EnableInterrupts (previousIntState);
} // else (status): No problems, activate the settings.
return(status);
} // End XsGpioEnablePinInt ()
/*
*******************************************************************************
*
* FUNCTION: XsGpioDisablePinInt
*
* DESCRIPTION: Deactivate any existing edge type for triggering an
* interrupt on the target pin. Clears any outstanding
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -