📄 xsintctrl.c
字号:
} // End XsIcDisableIrqDeviceInt()
/*
*******************************************************************************
*******************************************************************************
Private functions
*******************************************************************************
*******************************************************************************
*/
/*
*******************************************************************************
*
* FUNCTION: XsIcInstallInterruptVectors
*
* DESCRIPTION: Installs DM's direct IRQ interrupt handler. There is no
* support for chaining the IRQ interrrupt.
*
* Note: The FIQ handler is not installed because the DM does
* not use the FIQ interrupt; however, the code to install it
* is present but commented out. The FIQ section also shows
* a method to "chain" a predecessor interrupt handler that
* is already installed in the target vector location.
*
* INPUT PARAMETERS: None
*
* RETURNS: Success: 0 (ERR_NONE)
* ERR_T_NO_HANDLER: No appropriate code already located
* at the IRQ vector address.
*
* GLOBAL EFFECTS: Logs detected errors.
*
* ASSUMPTIONS: DM only uses IRQ, but owns that.
* IRQ interrupts are disabled.
* (If the FIQ vector were being modified, FIQ interrupts
* would have to be disabled.)
* CALLS:
*
* CALLED BY: XsIcHWSetup ()
*
* PROTOTYPE: UINT32 XsIcInstallInterruptVectors (void)
*
*******************************************************************************
*/
static
UINT32 XsIcInstallInterruptVectors (void)
{
UINT32 status = ERR_NONE;
UINT32 physicalAddr;
UINT32 *vectorP;
UINT32 *vectorHandlerP;
UINT32 *vectorHandlerP2;
XsIntCtrlContext.loggedError = 0;
// Note: the following FIQ-related code segment is present only for example
// purposes. The FIQ is not used by the DM, but is rather treated as reserved
// for Angel* and other debug monitors; therefore this segment is commented
// out.
//
// /*
// ***************************************************************************
// First, install new FIQ vector
// For FIQ, this implementation only worries about chaining Angel and
// other predecessors that install the LDR PC, #x.
// **************************************************************************
// */
//
// /*
// Assuming the use of the LDR pc, #x instruction in the vector location
// (this is used by Angel and the DM), chain the reference to the existing
// handler and install the reference to the DM handler.
//
// The effect of this instruction, which uses the "Load and Store Word or
// Unsigned Byte - Immediate Offset" addressing mode, is as follows:
// - A code-area word-size data element is created by the assembler to
// hold the constant value "x." Call it "xWord."
// - The low-order 12 bits of the executable binary assembled from the
// instruction are an offset from the address of the Program Counter
// to the location of xWord (that is, a pointer to a pointer).
// Call it "xWordOffset".
// - The high-order 24 bits of the executable binary assembled from the
// instruction define the operation that is to be taken relative to
// location xWord. In this case, it is:
// Load the PC register with the 32 bits found at address (PC +
// xWordOffset).
//
// The chaining logic of the DM contains the instruction
// "LDR pc, XsIcFiqChain", which provides the address of the pointer used
// in the loading operation, but is otherwise the same as LDR pc, #x.
//
// So, the operations performed here will be:
// - Find the location of xWord.
// * Derive xWordOffset from the binary found at the target vector
// location. This is done by isolating the low order 8 bits.
// * Add 8 to xWordOffset. See the note "Use of R15" that appears
// in many addressing mode descriptions in the ARM* architecture
// specification.
// * Add the address of the target vector location to (xWordOffset+8)
// - Copy the address found in xWord into XsIcFiqChain
// - Insert the address of DM's FIQ handler into xWord.
// /*
//
// vectorP = (UINT32 *) FIQ_EXCEPTION;
//
// /* Verify that the vector location contains an instruction of the form
// LDR pc, #x (used by Angel) before proceeding.
// */
//
// if ((*vectorP & 0xfffff000) == 0xe59ff000) // Verify instruction at vector
// {
// // Add vector address to xWordOffset plus PC adjustment for addressing
// // to get the address containing the predecessor FIQ handler.
// vectorHandlerP = (UINT32 *) ((*vectorP & 0xfff) + (UINT32) vectorP + 8);
//
// // Record old handler address in chain pointer.
// *(UINT32 *) &XsIcFiqChain = *vectorHandlerP;
// // Install DM handler for direct execution on FIQ interrupt.
// *vectorHandlerP = (UINT32) XsIcFiqWrapper;
// /*
// Flush data cache for pointer location used by the LDR instructions
// Instruction cache will be flushed once, later in function.
// */
// XsInvalidateDCacheLine (vectorHandlerP);
// XsCpWait();
// }
// else
// {
// // Error handling not defined yet
// status = ERR_T_NO_HANDLER;
// LOGERROR (XsIntCtrlContext.loggedError, ERR_L_XSIC, ERR_S_XSIC_IIV_FIQ
// status, 0, 0, 0)
// return (status); // Don't normally do multiple returns.
// }
//
/*
***************************************************************************
Now, install the DM IRQ handler.
IRQ for the DM will not be linked to a predecessor. However, since we
already have the method and shall assume that there is already a LDR pc, #x
instruction at the vector location, we'll use a subset of the FIQ approach.
***************************************************************************
*/
vectorP = (UINT32 *) IRQ_EXCEPTION;
if ((*vectorP & 0xfffff000) == 0xe59ff000) // Verify instruction at vector
{
// Add vector address to xWordOffset plus PC adjustment for addressing
// to get the address of the function pointer for the handler.
vectorHandlerP = (UINT32 *) ((*vectorP & 0xfff) + (UINT32) vectorP + 8);
XsIntCtrlContext.oldVectorContent = *vectorP;
XsIntCtrlContext.oldVectorHandlerPointerAddress =
(VUINT32)vectorHandlerP;
XsIntCtrlContext.oldVectorHandlerPointer = *vectorHandlerP;
XsIntCtrlContext.desiredHandlerAddress = (UINT32) XsIcIrqWrapper;
// Install DM handler for direct execution on IRQ interrupt.
*vectorHandlerP = (UINT32) XsIcIrqWrapper;
XsIntCtrlContext.newVectorContent = (VUINT32) *vectorP;
XsIntCtrlContext.newVectorHandlerPointerAddress =
(VUINT32)vectorHandlerP;
XsIntCtrlContext.newVectorHandlerPointer = (VUINT32) *vectorHandlerP;
/*
Flush the Instruction cache to remove old vectors
Also flush data cache for pointer location used by the LDR instruction
*/
XsInvalidateICacheAndBTB ();
XsInvalidateDCacheLine ((UINT32) vectorHandlerP);
XsCpWait();
//@@@ Don't know why a write to uncached memory is needed. Probably need to
// improve the forcing procedure just above.
// And now write through a virtual address with uncached attribute
(void) VirtualToPhysical (vectorHandlerP, &physicalAddr);
(void) PhysicalToVirtual (physicalAddr, 0,
(PVOID*)&vectorHandlerP2);
*vectorHandlerP2 = (UINT32) XsIcIrqWrapper;
XsIntCtrlContext.oldVectorContent = 0xDeaddeadL;
XsIntCtrlContext.oldVectorHandlerPointerAddress =
(VUINT32)vectorHandlerP2;
XsIntCtrlContext.oldVectorHandlerPointer = *vectorHandlerP2;
XsInvalidateICacheAndBTB ();
XsInvalidateDCacheLine ((UINT32) vectorHandlerP2);
XsCpWait();
}
else
{
status = ERR_T_NO_HANDLER;
LOGERROR (XsIntCtrlContext.loggedError, ERR_L_XSIC, ERR_S_XSIC_IIV_IRQ,
status, 0, 0, 0)
}
return (XsIntCtrlContext.loggedError);
} // End xsIcInstallInterruptVectors()
/*
*******************************************************************************
*
* FUNCTION: XsIcEnableIrqDeviceInt
*
* DESCRIPTION: Enable IRQ interrupts for the specified first level
* interrupt signal. This takes effect only while IRQ
* interrupts are globally enabled in the CPSR.
*
* INPUT PARAMETERS: sourceID: Identifier of the first level source signal for
* which to enable IRQ interrupts.
*
* RETURNS: XSIC_ALL_HANDLED: All active and enabled IRQ signals had
* registered handlers
* XSIC_SOME_UNHANDLED (Theoretical only):
* There was at least one active IRQ signal that
* did not have a registered handler. If IRQ
* chaining were supported, this would be used as
* an indicator to XsIcIrqWrapper() that the
* predecessor ISR should be invoked.
*
* GLOBAL EFFECTS: Logs fact of unregistered handler for active signal.
* Also, in that case, goes into infinite loop sending an
* LED error code. That sort of bug shouldn't get past
* testing, and would prevent any non-interrupt code from
* executing.
*
* ASSUMPTIONS:
*
* CALLS: PlatformLedsDisplayInterrupt()
*
* CALLED BY: XsIcIrqWrapper()
*
* PROTOTYPE: UINT32 XsIcInterruptHandlerCIrq (void) ;
*
*******************************************************************************
*/
/*----------------------------------------------------------------------
* Local interrupt handler (first level sources only). Other devices may
* need to supply similar capabilities.
*/
UINT32 XsIcInterruptHandlerCIrq (void)
{
UINT32 irq_processed = XSIC_ALL_HANDLED; // Assume chaining not needed
// Get active, mask-enabled signals from IRQ level sources
UINT32 activeIrqInterruptSignals = XsIntCtrlRegsP->ICIP;
UINT32 i;
// Indicate entry into interrupt handling for system
// PlatformLedsDisplayInterrupt (1); // Need manifest constant and real function name here.
// Only check interrupt signals that are supported in Cotulla
for (i = XSIC_MIN_SGNL; i <= XSIC_MAX_SGNL; i++)
{
if (activeIrqInterruptSignals & (1 << i))
{
if (XsIcIrqHandlerTable[i])
XsIcIrqHandlerTable[i] (XsIcIrqHandlerParamTable[i]);
else
{
// There is an unhandled interrupt. Baaad.
// Handle error here via some notice and an
// LCD indication infinite loop.
LOGERROR (XsIntCtrlContext.loggedError, ERR_L_XSIC,
ERR_S_XSIC_IH_C_IRQ, ERR_T_NO_HANDLER, i, 0, 0)
// DM2: DM_ErrPrintf("Unhandled interrupt %d\n", i);
// DM2: DisableInterrupt(i);
// // If chaining were implemented and there was something to
// // chain to, we could pass this indicator back to the master
// // ISR and let the predecessor deal with it instead of
// // treating it as an error.
// irq_processed = XSIC_SOME_UNHANDLED;
// return irq_processed;
}
}
}
// Indicate exit from interrupt handling for system
// PlatformLedsDisplayInterrupt (0); // Need manifest constant and real function name here.
return irq_processed;
} // End xsIcInterruptHandlerCIrq()
/*
*******************************************************************************
*
* FUNCTION: XsIcRangeCheckSource
*
* DESCRIPTION: Range checks the value of its parameter.
*
* INPUT PARAMETERS: sourceID: Identifier of the first level source signal
* for checking.
*
* RETURNS: Success: 0 (ERR_NONE)
* ERR_T_ILLPARAM: sourceID out of range.
*
* GLOBAL EFFECTS: None
*
* ASSUMPTIONS: None
*
* CALLS: None
*
* CALLED BY:
*
* PROTOTYPE: UINT32 XsIcUnRegisterHandler (XsIcInterruptSignalsT sourceID);
*
*******************************************************************************
*/
static
UINT32 XsIcRangeCheckSource (XsIcInterruptSignalsT sourceID)
{
UINT32 status = ERR_NONE;
if ((sourceID < XSIC_MIN_SGNL)|| (sourceID > XSIC_MAX_SGNL))
{
status = ERR_T_ILLPARAM;
}
return(status);
}
//----------------- Debug ------------------
void XsIcDbgPrintCurrentState (void)
{
VUINT32 cpsrTmp;
UINT32 *vectorP;
UINT32 *vectorHandlerP;
if(DM_ControlWordsDebugPrintGetBit(DM_CW_XS_INT_CTRL))
{
vectorP = (UINT32 *) IRQ_EXCEPTION;
vectorHandlerP = (UINT32 *) ((*vectorP & 0xfff) + (UINT32) vectorP + 8);
cpsrTmp = XsIcGetCpsr();
DM_CwDbgPrintf (DM_CW_XS_INT_CTRL,
"Some current values of the Main Interrupt Controller\n");
DM_CwDbgPrintf (DM_CW_XS_INT_CTRL,
" Current Status Word: %X; I-mask: %X; F-mask: %X\n",
cpsrTmp, CPSR_I_Bit, CPSR_F_Bit);
DM_CwDbgPrintf (DM_CW_XS_INT_CTRL,
" IC registers: ICIP %X; ICMR %X; ICLR %X\n",
*((PVUINT*) 0x40D00000),
*((PVUINT*) 0x40D00004),
*((PVUINT*) 0x40D00008));
DM_CwDbgPrintf (DM_CW_XS_INT_CTRL,
" IC registers: ICFP %X; ICPR %X; ICCR %X\n",
*((PVUINT*) 0x40D0000C),
*((PVUINT*) 0x40D00010),
*((PVUINT*) 0x40D00014));
// DM_CwDbgPrintf(DM_CW_AC97_CODEC,
DM_CwDbgPrintf(DM_CW_XS_INT_CTRL,
" IRQ vector: Function Addr %08X installed at virtual addr %08X\n",
*vectorHandlerP,
vectorHandlerP);
}
} // XsIcDbgPrintCurrentState()
void XsIcDoVecs (void)
{
XsIcInstallInterruptVectors();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -