📄 xsgpio.c
字号:
* interrupt for pin. No-ops unless pin mode is GPIO
* and direction is input. Leaves the record of desired
* trigger type for subsequent use of XsGpioEnablePinInt().
*
* INPUT PARAMETERS: XsGpioIdT pinID - GPIO pin to deactivate interrupt for
*
* RETURNS: Success: 0 (ERR_NONE)
* Failure: ERR_T_ILLPARAM - out of range parameter
*
* GLOBAL EFFECTS: None
*
* ASSUMPTIONS:
*
* CALLS:
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsGpioDisablePinInt (XsGpioIdT);
*
*******************************************************************************
*/
UINT32 XsGpioDisablePinInt (XsGpioIdT pinID)
// Does not change the edge type that triggers the interrupt
// Only error is for bad pinID. If not GPIO input,
// quietly does nothing.
{
UINT32 status = ERR_NONE; // Assume success
UINT32 previousIntState;
INT regIndex; // For GPIO register addressing.
INT bitOffset; // For GPIO register addressing.
XsGpioUsageEntryT *currPinCfgP;
status = XsGpioRangeCheckPinId (pinID);
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_DI_PIN_INT, status, 0, 0, 0)
}
else
{
currPinCfgP = XsGpioCurrentUsageTable + pinID;
if ( (XS_GPIO_ALT_FUNC_GPIO == currPinCfgP->fnCategory)
&& (XS_GPIO_DIR_IN == currPinCfgP->direction ))
{
// Set up addressing for register operations
XsGpioRegsCalcLocIndices ( pinID, ®Index, &bitOffset );
// Perform the register accesses under interrupt protection
previousIntState = IRQ_DisableInterrupts(CPSR_I_Bit|CPSR_F_Bit);
// Clear out the current setting for the target pin in both
// edge detect selection registers.
// Then the clear current edge detect status because we
// don't want an interrupt on this pin now.
XsGpioRegsP->GRERs[regIndex]
&= ~(XS_GPIO_INT_EDGE_MSK << bitOffset);
XsGpioRegsP->GFERs[regIndex]
&= ~(XS_GPIO_INT_EDGE_MSK << bitOffset);
// Clear outstanding calls on this pin
XsGpioRegsP->GEDRs[regIndex]
|= (XS_GPIO_INT_EDGE_MSK << bitOffset);
// Now record it.
currPinCfgP->interruptEnabled = FALSE;
IRQ_EnableInterrupts (previousIntState);
} // GPIO function and input direction: perform the operation
} // Finished else (status): parameter range checked
return(status);
} // End XsGpioDisablePinInt ()
/*
*******************************************************************************
XsGpioSetSimulatedLevelInt
*******************************************************************************
*/
void XsGpioSetSimulatedLevelInt (XsGpioIdT pinID, BOOL simulatedLevelInt)
// Don't use bad params, but don't report param errors. Other calls to the
// driver in this vicinity will catch them.
{
UINT32 status;
status = XsGpioRangeCheckPinId (pinID);
if (!status)
{
XsGpioCurrentUsageTable[pinID].simulatedLevelInt = simulatedLevelInt;
}
} // XsGpioSetSimulatedLevelInt ()
/*
*******************************************************************************
Non-standard, test-oriented API of main processor on-board
GPIO driver. Lower level access provided.
*******************************************************************************
*/
//=============================== LATER ================================
UINT32 XsGpioSetAlternateFunction ( XsGpioIdT pinID,
XsGpioAltFuncCodeT alternateFunction)
// (This is a register-oriented primitive and does not trigger
// a general initialization of all pins needed to support
// the alternate function selected for this pin)
// It may be necessary to set the direction and the level (for outputs)
// If an interrupt handler is registered, the new function must be GPIO.
{
UINT32 status;
INT regIndex; // For GPIO register addressing.
INT bitOffset; // For GPIO register addressing.
UINT32 tempGAFR;
INT previousIntState;
XsGpioUsageEntryT *currPinCfgP;
status = XsGpioRangeCheckPinId (pinID);
if (!status)
{
currPinCfgP = &XsGpioCurrentUsageTable[pinID];
if (XS_GPIO_UNAVAILABLE == currPinCfgP->fnCategory)
{
status = ERR_T_NOT_AVAIL;
}
else
{ // Non-reserved pin. Continue checking
// Absence of change is OK; otherwise,
// Start function must be GPIO
if ( ( alternateFunction != currPinCfgP->fnCategory)
&&( XS_GPIO_ALT_FUNC_GPIO != currPinCfgP->fnCategory)
&& (XS_GPIO_ALT_FUNC_GPIO != alternateFunction))
{
status = ERR_T_WRONG_STATE;
}
}
}
if (!status)
{
// No SW problems, do the job
// Set up addressing for GAFR access (alternate function regs)
XsGpioRegsCalcLocIndicesGafr ( pinID, ®Index, &bitOffset );
previousIntState = IRQ_DisableInterrupts(CPSR_I_Bit|CPSR_F_Bit);
// Get current alternate function register setting, clearing
// out the target pin's control bits.
tempGAFR = XsGpioRegsP->GAFRs[regIndex]
& ~(XS_GPIO_GAFR_PIN_MSK << bitOffset);
// Set target bits, leave others untouched.
tempGAFR |= alternateFunction << bitOffset;
XsGpioRegsP->GAFRs[regIndex] = tempGAFR; // Write to HW
// Record the change
currPinCfgP->fnCategory = alternateFunction;
IRQ_EnableInterrupts (previousIntState);
} // if (!status) No SW problems, do the job
return(status);
} // XsGpioSetAlternateFunction ()
//=============================== ================================
UINT32 XsGpioGetLevel (XsGpioIdT pinID, XsGpioPinLevelT *level)
{
UINT32 status;
INT regIndex; // For GPIO register addressing.
INT bitOffset; // For GPIO register addressing.
UINT32 tempGPLR;
status = XsGpioRangeCheckPinId (pinID);
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_GET_LEVEL, status, pinID, 0, 0)
}
else
{
XsGpioRegsCalcLocIndices ( pinID, ®Index, &bitOffset );
// Get current value of pin set
tempGPLR = XsGpioRegsP->GPLRs[regIndex];
// Isolate target pin level and normalize to LSB
*level = (tempGPLR >> bitOffset) & 1;
}
return(status);
} // XsGpioGetLevel ()
//=============================== ================================
UINT32 XsGpioSetLevel (XsGpioIdT pinID, XsGpioPinLevelT level)
// For general purpose use, performed with interrupt protection.
{
UINT32 status;
INT regIndex; // For GPIO register addressing.
INT bitOffset; // For GPIO register addressing.
PVUINT32 targetRegP;
INT previousIntState;
status = XsGpioRangeCheckPinId (pinID);
if (!status)
{
if (XS_GPIO_UNAVAILABLE ==
XsGpioCurrentUsageTable[pinID].fnCategory)
{
status = ERR_T_NOT_AVAIL;
}
}
if (!status)
{
// No SW problems, do the job
XsGpioRegsCalcLocIndices ( pinID, ®Index, &bitOffset );
if (level)
{ // For sets, use the GPIO Pin Output Set Register
targetRegP = &XsGpioRegsP->GPSRs[regIndex];
}
else
{ // For clears, use the GPIO Pin Output Clear Register
targetRegP = &XsGpioRegsP->GPCRs[regIndex];
}
// Hardware access and record-keeping done under interrupt protection
previousIntState = IRQ_DisableInterrupts (CPSR_I_Bit|CPSR_F_Bit);
*targetRegP = 1u << bitOffset; // Just write a "1" to target bit
IRQ_EnableInterrupts (previousIntState); // Restore state
} // if (!status) No SW problems, do the job
else
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_SET_LEVEL, status, pinID, 0, 0)
}
return(status);
} // XsGpioSetLevel
//=============================== ================================
UINT32 XsGpioSetLevelIsr (XsGpioIdT pinID, XsGpioPinLevelT level)
// For speed, assumes interrupt protection. Intended for use in ISRs.
{
UINT32 status;
INT regIndex; // For GPIO register addressing.
INT bitOffset; // For GPIO register addressing.
status = XsGpioRangeCheckPinId (pinID);
if (status)
{
LOGERROR (XsGpioContext.loggedError, ERR_L_XSGPIO,
ERR_S_XSGPIO_SET_LEVEL, status, pinID, 0, 0)
}
else
{
XsGpioRegsCalcLocIndices ( pinID, ®Index, &bitOffset );
if (level)
{ // Write a "1" to target bit in GPIO Pin Output Set Register
XsGpioRegsP->GPSRs[regIndex] = 1u << bitOffset;
}
else
{ // Write a "1" to target bit in GPIO Pin Output Clear Register
XsGpioRegsP->GPCRs[regIndex] = 1u << bitOffset;
}
}
return(status);
} // XsGpioSetLevelIsr ()
// Set the pins needed by the STUART or ICP to that alternate function. These functions are expected
// to be used to toggle them betweeen STUART and ICP, and it is assumed that they will never be used
// for GPIO in the systems where this function is used. Also, the only two pins affected in this
// are Rx and Tx data, so initial levels are not important. The ICP and STUART devices should both
// be disabled (clocks off) when either of these calls are made.
// Note that the alternate function selector values are reversed for ICP and STUART between the
// Rx and Tx capabilities.
void XsGpioSetIcp (void)
{
// First move target pins to GPIO function, then to target functions
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_RX, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_TX, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetDirection (XS_GPIO_ID_ICPSTUART_RX, XS_GPIO_DIR_IN, XS_GPIO_PIN_LEVEL_0);
(void) XsGpioSetDirection (XS_GPIO_ID_ICPSTUART_TX, XS_GPIO_DIR_OUT, XS_GPIO_PIN_LEVEL_1);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_RX, XS_GPIO_ALT_FUNC_1);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_TX, XS_GPIO_ALT_FUNC_2);
}
void XsGpioSetStuart (void)
{
// First move target pins to GPIO function, then to target functions
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_RX, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_TX, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetDirection (XS_GPIO_ID_ICPSTUART_RX, XS_GPIO_DIR_IN, XS_GPIO_PIN_LEVEL_0);
(void) XsGpioSetDirection (XS_GPIO_ID_ICPSTUART_TX, XS_GPIO_DIR_OUT, XS_GPIO_PIN_LEVEL_1);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_RX, XS_GPIO_ALT_FUNC_2);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_ICPSTUART_TX, XS_GPIO_ALT_FUNC_1);
}
void XsGpioSetSspExtClock (UINT device)
{
switch (device & 0x03)
{
case SSP1:
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_SSP1_EXTCLK, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetDirection (XS_GPIO_ID_SSP1_EXTCLK, XS_GPIO_DIR_IN, XS_GPIO_PIN_LEVEL_0);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_SSP1_EXTCLK, XS_GPIO_ALT_FUNC_1);
break;
case SSP2:
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_SSP2_EXTCLK, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetDirection (XS_GPIO_ID_SSP2_EXTCLK, XS_GPIO_DIR_IN, XS_GPIO_PIN_LEVEL_0);
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_SSP2_EXTCLK, XS_GPIO_ALT_FUNC_1);
break;
case SSP3:
break;
}
}
void XsGpioClearSspExtClock (UINT device)
{
switch (device & 0x03)
{
case SSP1:
(void) XsGpioSetAlternateFunction ( XS_GPIO_ID_SSP1_EXTCLK, XS_GPIO_ALT_FUNC_GPIO);
(void) XsGpioSetDirection (XS_GPIO_ID_SSP1_EXTCLK, XS_GPIO_DIR_IN, XS_GPIO_PIN_LEVEL_X);
break;
case SSP2:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -