/****************************************************************************** * * Copyright (C) 2002 - 2014 Xilinx, Inc. All rights reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * Use of the Software is limited solely to applications: * (a) running on a Xilinx device, or * (b) that interact with a Xilinx device through a bus or interconnect. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * XILINX CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. * * Except as contained in this notice, the name of the Xilinx shall not be used * in advertising or otherwise to promote the sale, use or other dealings in * this Software without prior written authorization from Xilinx. * ******************************************************************************/ /*****************************************************************************/ /** * * @file xintc.c * * Contains required functions for the XIntc driver for the Xilinx Interrupt * Controller. See xintc.h for a detailed description of the driver. * *
* MODIFICATION HISTORY:
*
* Ver   Who  Date     Changes
* ----- ---- -------- --------------------------------------------------------
* 1.00a ecm  08/16/01 First release
* 1.00b jhl  02/21/02 Repartitioned the driver for smaller files
* 1.00b jhl  04/24/02 Made LookupConfig global and compressed ack before table
*                     in the configuration into a bit mask
* 1.00c rpm  10/17/03 New release. Support the static vector table created
*                     in the xintc_g.c configuration table.
* 1.00c rpm  04/23/04 Removed check in XIntc_Connect for a previously connected
*                     handler. Always overwrite the vector table handler with
*                     the handler provided as an argument.
* 1.10c mta  03/21/07 Updated to new coding style
* 1.11a sv   11/21/07 Updated driver to support access through a DCR bridge
* 2.00a ktn  10/20/09 Updated to use HAL Processor APIs.
* 2.04a bss  01/13/12 Added XIntc_ConnectFastHandler API for Fast Interrupt
*		      and XIntc_SetNormalIntrMode for setting to normal
*		      interrupt mode.
* 2.05a bss  08/16/12 Updated to support relocatable vectors in Microblaze,
*		      updated XIntc_SetNormalIntrMode to use IntVectorAddr
*		      which is the interrupt vector address
* 2.06a bss  01/28/13 To support Cascade mode:
*		      Modified XIntc_Initialize,XIntc_Start,XIntc_Connect
*		      XIntc_Disconnect,XIntc_Enable,XIntc_Disable,
*		      XIntc_Acknowledge,XIntc_ConnectFastHandler and
*		      XIntc_SetNormalIntrMode APIs.
*		      Added XIntc_InitializeSlaves API.
* 3.0   bss  01/28/13 Modified to initialize IVAR register with
*		      XPAR_MICROBLAZE_BASE_VECTORS + 0x10 to fix
*		      CR#765931
*
* 
* ******************************************************************************/ /***************************** Include Files *********************************/ #include "xil_types.h" #include "xil_assert.h" #include "xintc.h" #include "xintc_l.h" #include "xintc_i.h" /************************** Constant Definitions *****************************/ /**************************** Type Definitions *******************************/ /***************** Macros (Inline Functions) Definitions *********************/ /************************** Variable Definitions *****************************/ /* * Array of masks associated with the bit position, improves performance * in the ISR and acknowledge functions, this table is shared between all * instances of the driver. XIN_CONTROLLER_MAX_INTRS is the maximum number of * sources of Interrupt controller */ u32 XIntc_BitPosMask[XIN_CONTROLLER_MAX_INTRS]; /************************** Function Prototypes ******************************/ static void StubHandler(void *CallBackRef); static void XIntc_InitializeSlaves(XIntc * InstancePtr); /*****************************************************************************/ /** * * Initialize a specific interrupt controller instance/driver. The * initialization entails: * * - Initialize fields of the XIntc structure * - Initial vector table with stub function calls * - All interrupt sources are disabled * - Interrupt output is disabled * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param DeviceId is the unique id of the device controlled by this XIntc * instance. Passing in a device id associates the generic XIntc * instance to a specific device, as chosen by the caller or * application developer. * * @return * - XST_SUCCESS if initialization was successful * - XST_DEVICE_IS_STARTED if the device has already been started * - XST_DEVICE_NOT_FOUND if device configuration information was * not found for a device with the supplied device ID. * * @note In Cascade mode this function calls XIntc_InitializeSlaves to * initialiaze Slave Interrupt controllers. * ******************************************************************************/ int XIntc_Initialize(XIntc * InstancePtr, u16 DeviceId) { u8 Id; XIntc_Config *CfgPtr; u32 NextBitMask = 1; Xil_AssertNonvoid(InstancePtr != NULL); /* * If the device is started, disallow the initialize and return a status * indicating it is started. This allows the user to stop the device * and reinitialize, but prevents a user from inadvertently initializing */ if (InstancePtr->IsStarted == XIL_COMPONENT_IS_STARTED) { return XST_DEVICE_IS_STARTED; } /* * Lookup the device configuration in the CROM table. Use this * configuration info down below when initializing this component. */ CfgPtr = XIntc_LookupConfig(DeviceId); if (CfgPtr == NULL) { return XST_DEVICE_NOT_FOUND; } /* * Set some default values */ InstancePtr->IsReady = 0; InstancePtr->IsStarted = 0; /* not started */ InstancePtr->CfgPtr = CfgPtr; InstancePtr->CfgPtr->Options = XIN_SVC_SGL_ISR_OPTION; InstancePtr->CfgPtr->IntcType = CfgPtr->IntcType; /* * Save the base address pointer such that the registers of the * interrupt can be accessed */ #if (XPAR_XINTC_USE_DCR_BRIDGE != 0) InstancePtr->BaseAddress = ((CfgPtr->BaseAddress >> 2)) & 0xFFF; #else InstancePtr->BaseAddress = CfgPtr->BaseAddress; #endif /* * Initialize all the data needed to perform interrupt processing for * each interrupt ID up to the maximum used */ for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { /* * Initalize the handler to point to a stub to handle an * interrupt which has not been connected to a handler. Only * initialize it if the handler is 0 or XNullHandler, which * means it was not initialized statically by the tools/user. * Set the callback reference to this instance so that * unhandled interrupts can be tracked. */ if ((InstancePtr->CfgPtr->HandlerTable[Id].Handler == 0) || (InstancePtr->CfgPtr->HandlerTable[Id].Handler == XNullHandler)) { InstancePtr->CfgPtr->HandlerTable[Id].Handler = StubHandler; } InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; /* * Initialize the bit position mask table such that bit * positions are lookups only for each interrupt id, with 0 * being a special case * (XIntc_BitPosMask[] = { 1, 2, 4, 8, ... }) */ XIntc_BitPosMask[Id] = NextBitMask; NextBitMask *= 2; } /* * Disable IRQ output signal * Disable all interrupt sources * Acknowledge all sources */ XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, 0); XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF); /* * If the fast Interrupt mode is enabled then set all the * interrupts as normal mode. */ if(InstancePtr->CfgPtr->FastIntr == TRUE) { XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, 0); #ifdef XPAR_MICROBLAZE_BASE_VECTORS for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + 0x10); } #else for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), 0x10); } #endif } /* Initialize slaves in Cascade mode*/ if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { XIntc_InitializeSlaves(InstancePtr); } /* * Indicate the instance is now ready to use, successfully initialized */ InstancePtr->IsReady = XIL_COMPONENT_IS_READY; return XST_SUCCESS; } /*****************************************************************************/ /** * * Starts the interrupt controller by enabling the output from the controller * to the processor. Interrupts may be generated by the interrupt controller * after this function is called. * * It is necessary for the caller to connect the interrupt handler of this * component to the proper interrupt source. This function also starts Slave * controllers in Cascade mode. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Mode determines if software is allowed to simulate interrupts or * real interrupts are allowed to occur. Note that these modes are * mutually exclusive. The interrupt controller hardware resets in * a mode that allows software to simulate interrupts until this * mode is exited. It cannot be reentered once it has been exited. * * One of the following values should be used for the mode. * - XIN_SIMULATION_MODE enables simulation of interrupts only * - XIN_REAL_MODE enables hardware interrupts only * * @return * - XST_SUCCESS if the device was started successfully * - XST_FAILURE if simulation mode was specified and it could not * be set because real mode has already been entered. * * @note Must be called after XIntc initialization is completed. * ******************************************************************************/ int XIntc_Start(XIntc * InstancePtr, u8 Mode) { u32 MasterEnable = XIN_INT_MASTER_ENABLE_MASK; XIntc_Config *CfgPtr; int Index; /* * Assert the arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid((Mode == XIN_SIMULATION_MODE) || (Mode == XIN_REAL_MODE)) Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Check for simulation mode */ if (Mode == XIN_SIMULATION_MODE) { if (MasterEnable & XIN_INT_HARDWARE_ENABLE_MASK) { return XST_FAILURE; } } else { MasterEnable |= XIN_INT_HARDWARE_ENABLE_MASK; } /* * Indicate the instance is ready to be used and is started before we * enable the device. */ InstancePtr->IsStarted = XIL_COMPONENT_IS_STARTED; /* Start the Slaves for Cascade Mode */ if (InstancePtr->CfgPtr->IntcType != XIN_INTC_NOCASCADE) { for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) { CfgPtr = XIntc_LookupConfig(Index); XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, MasterEnable); } } /* Start the master */ XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, MasterEnable); return XST_SUCCESS; } /*****************************************************************************/ /** * * Stops the interrupt controller by disabling the output from the controller * so that no interrupts will be caused by the interrupt controller. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * * @return None. * * @note None. * ******************************************************************************/ void XIntc_Stop(XIntc * InstancePtr) { /* * Assert the arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Stop all interrupts from occurring thru the interrupt controller by * disabling all interrupts in the MER register */ XIntc_Out32(InstancePtr->BaseAddress + XIN_MER_OFFSET, 0); InstancePtr->IsStarted = 0; } /*****************************************************************************/ /** * * Makes the connection between the Id of the interrupt source and the * associated handler that is to run when the interrupt is recognized. The * argument provided in this call as the Callbackref is used as the argument * for the handler when it is called. In Cascade mode, connects handler to * Slave controller handler table depending on the interrupt Id. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being * the highest priority interrupt. * @param Handler to the handler for that interrupt. * @param CallBackRef is the callback reference, usually the instance * pointer of the connecting driver. * * @return * * - XST_SUCCESS if the handler was connected correctly. * * @note * * WARNING: The handler provided as an argument will overwrite any handler * that was previously connected. * ****************************************************************************/ int XIntc_Connect(XIntc * InstancePtr, u8 Id, XInterruptHandler Handler, void *CallBackRef) { XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertNonvoid(Handler != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* Connect Handlers for Slave controllers in Cascade Mode */ if (Id > 31) { CfgPtr = XIntc_LookupConfig(Id/32); CfgPtr->HandlerTable[Id%32].Handler = Handler; CfgPtr->HandlerTable[Id%32].CallBackRef = CallBackRef; } /* Connect Handlers for Master/primary controller */ else { /* * The Id is used as an index into the table to select the * proper handler */ InstancePtr->CfgPtr->HandlerTable[Id].Handler = Handler; InstancePtr->CfgPtr->HandlerTable[Id].CallBackRef = CallBackRef; } return XST_SUCCESS; } /*****************************************************************************/ /** * * Updates the interrupt table with the Null Handler and NULL arguments at the * location pointed at by the Id. This effectively disconnects that interrupt * source from any handler. The interrupt is disabled also. In Cascade mode, * disconnects handler from Slave controller handler table depending on the * interrupt Id. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being * the highest priority interrupt. * * @return None. * * @note None. * ****************************************************************************/ void XIntc_Disconnect(XIntc * InstancePtr, u8 Id) { u32 CurrentIER; u32 Mask; XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); /* * Disable the interrupt such that it won't occur while disconnecting * the handler, only disable the specified interrupt id without * modifying the other interrupt ids */ /* Disconnect Handlers for Slave controllers in Cascade Mode */ if (Id > 31) { CfgPtr = XIntc_LookupConfig(Id/32); CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[(Id%32)]; XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, (CurrentIER & ~Mask)); /* * Disconnect the handler and connect a stub, the callback * reference must be set to this instance to allow unhandled * interrupts to be tracked */ CfgPtr->HandlerTable[Id%32].Handler = StubHandler; CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr; } /* Disconnect Handlers for Master/primary controller */ else { CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[Id]; XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, (CurrentIER & ~Mask)); InstancePtr->CfgPtr->HandlerTable[Id%32].Handler = StubHandler; InstancePtr->CfgPtr->HandlerTable[Id%32].CallBackRef = InstancePtr; } } /*****************************************************************************/ /** * * Enables the interrupt source provided as the argument Id. Any pending * interrupt condition for the specified Id will occur after this function is * called. In Cascade mode, enables corresponding interrupt of Slave controllers * depending on the Id. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being * the highest priority interrupt. * * @return None. * * @note None. * ****************************************************************************/ void XIntc_Enable(XIntc * InstancePtr, u8 Id) { u32 CurrentIER; u32 Mask; XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); if (Id > 31) { /* Enable user required Id in Slave controller */ CfgPtr = XIntc_LookupConfig(Id/32); CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[(Id%32)]; XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, (CurrentIER | Mask)); } else { /* * The Id is used to create the appropriate mask for the * desired bit position. */ Mask = XIntc_BitPosMask[Id]; /* * Enable the selected interrupt source by reading the * interrupt enable register and then modifying only the * specified interrupt id enable */ CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, (CurrentIER | Mask)); } } /*****************************************************************************/ /** * * Disables the interrupt source provided as the argument Id such that the * interrupt controller will not cause interrupts for the specified Id. The * interrupt controller will continue to hold an interrupt condition for the * Id, but will not cause an interrupt.In Cascade mode, disables corresponding * interrupt of Slave controllers depending on the Id. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the * highest priority interrupt. * * @return None. * * @note None. * ****************************************************************************/ void XIntc_Disable(XIntc * InstancePtr, u8 Id) { u32 CurrentIER; u32 Mask; XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); if (Id > 31) { /* Enable user required Id in Slave controller */ CfgPtr = XIntc_LookupConfig(Id/32); CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[(Id%32)]; XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, (CurrentIER & ~Mask)); } else { /* * The Id is used to create the appropriate mask for the * desired bit position. Id currently limited to 0 - 31 */ Mask = XIntc_BitPosMask[Id]; /* * Disable the selected interrupt source by reading the * interrupt enable register and then modifying only the * specified interrupt id */ CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); XIntc_Out32(InstancePtr->BaseAddress + XIN_IER_OFFSET, (CurrentIER & ~Mask)); } } /*****************************************************************************/ /** * * Acknowledges the interrupt source provided as the argument Id. When the * interrupt is acknowledged, it causes the interrupt controller to clear its * interrupt condition.In Cascade mode, acknowledges corresponding interrupt * source of Slave controllers depending on the Id. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being * the highest priority interrupt. * * @return None. * * @note None. * ****************************************************************************/ void XIntc_Acknowledge(XIntc * InstancePtr, u8 Id) { u32 Mask; XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); if (Id > 31) { /* Enable user required Id in Slave controller */ CfgPtr = XIntc_LookupConfig(Id/32); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[(Id%32)]; XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, Mask); } else { /* * The Id is used to create the appropriate mask for the * desired bit position. */ Mask = XIntc_BitPosMask[Id]; /* * Acknowledge the selected interrupt source, no read of the * acknowledge register is necessary since only the bits set * in the mask will be affected by the write */ XIntc_Out32(InstancePtr->BaseAddress + XIN_IAR_OFFSET, Mask); } } /*****************************************************************************/ /** * * A stub for the asynchronous callback. The stub is here in case the upper * layers forget to set the handler. * * @param CallBackRef is a pointer to the upper layer callback reference * * @return None. * * @note None. * ******************************************************************************/ static void StubHandler(void *CallBackRef) { /* * Verify that the inputs are valid */ Xil_AssertVoid(CallBackRef != NULL); /* * Indicate another unhandled interrupt for stats */ ((XIntc *) CallBackRef)->UnhandledInterrupts++; } /*****************************************************************************/ /** * * Looks up the device configuration based on the unique device ID. A table * contains the configuration info for each device in the system. * * @param DeviceId is the unique identifier for a device. * * @return A pointer to the XIntc configuration structure for the specified * device, or NULL if the device was not found. * * @note None. * ******************************************************************************/ XIntc_Config *XIntc_LookupConfig(u16 DeviceId) { XIntc_Config *CfgPtr = NULL; int Index; for (Index = 0; Index < XPAR_XINTC_NUM_INSTANCES; Index++) { if (XIntc_ConfigTable[Index].DeviceId == DeviceId) { CfgPtr = &XIntc_ConfigTable[Index]; break; } } return CfgPtr; } /*****************************************************************************/ /** * * Makes the connection between the Id of the interrupt source and the * associated handler that is to run when the interrupt is recognized.In Cascade * mode, connects handler to corresponding Slave controller IVAR register * depending on the Id and sets all interrupt sources of the Slave controller as * fast interrupts. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being * the highest priority interrupt. * @param Handler to the handler for that interrupt. * * @return * - XST_SUCCESS * * @note * Slave controllers in Cascade Mode should have all as Fast * interrupts or Normal interrupts, mixed interrupts are not * supported * * WARNING: The handler provided as an argument will overwrite any handler * that was previously connected. * ****************************************************************************/ int XIntc_ConnectFastHandler(XIntc *InstancePtr, u8 Id, XFastInterruptHandler Handler) { u32 Imr; u32 CurrentIER; u32 Mask; XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertNonvoid(InstancePtr != NULL); Xil_AssertNonvoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertNonvoid(Handler != NULL); Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertNonvoid(InstancePtr->CfgPtr->FastIntr == TRUE); if (Id > 31) { /* Enable user required Id in Slave controller */ CfgPtr = XIntc_LookupConfig(Id/32); if (CfgPtr->FastIntr != TRUE) { /*Fast interrupts of slave controller are not enabled*/ return XST_FAILURE; } /* Get the Enabled Interrupts */ CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[(Id%32)]; /* Disable the Interrupt if it was enabled before calling * this function */ if (CurrentIER & Mask) { XIntc_Disable(InstancePtr, Id); } XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + ((Id%32) * 4), (u32) Handler); /* Slave controllers in Cascade Mode should have all as Fast * interrupts or Normal interrupts, mixed interrupts are not * supported */ XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0xFFFFFFFF); /* Enable the Interrupt if it was enabled before calling this * function */ if (CurrentIER & Mask) { XIntc_Enable(InstancePtr, Id); } } else { /* Get the Enabled Interrupts */ CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[Id]; /* Disable the Interrupt if it was enabled before calling * this function */ if (CurrentIER & Mask) { XIntc_Disable(InstancePtr, Id); } XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), (u32) Handler); Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, Imr | Mask); /* Enable the Interrupt if it was enabled before * calling this function */ if (CurrentIER & Mask) { XIntc_Enable(InstancePtr, Id); } } return XST_SUCCESS; } /*****************************************************************************/ /** * * Sets the normal interrupt mode for the specified interrupt in the Interrupt * Mode Register. In Cascade mode disconnects handler from corresponding Slave * controller IVAR register depending on the Id and sets all interrupt sources * of the Slave controller as normal interrupts. * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * @param Id contains the ID of the interrupt source and should be in the * range of 0 to XPAR_INTC_MAX_NUM_INTR_INPUTS - 1 with 0 being the * highest priority interrupt. * * @return None. * * @note * Slave controllers in Cascade Mode should have all as Fast * interrupts or Normal interrupts, mixed interrupts are not * supported * ****************************************************************************/ void XIntc_SetNormalIntrMode(XIntc *InstancePtr, u8 Id) { u32 Imr; u32 CurrentIER; u32 Mask; XIntc_Config *CfgPtr; /* * Assert the arguments */ Xil_AssertVoid(InstancePtr != NULL); Xil_AssertVoid(Id < XPAR_INTC_MAX_NUM_INTR_INPUTS); Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY); Xil_AssertVoid(InstancePtr->CfgPtr->FastIntr == TRUE); if (Id > 31) { /* Enable user required Id in Slave controller */ CfgPtr = XIntc_LookupConfig(Id/32); /* Get the Enabled Interrupts */ CurrentIER = XIntc_In32(CfgPtr->BaseAddress + XIN_IER_OFFSET); /* Convert from integer id to bit mask */ Mask = XIntc_BitPosMask[(Id%32)]; /* Disable the Interrupt if it was enabled before calling * this function */ if (CurrentIER & Mask) { XIntc_Disable(InstancePtr, Id); } /* Slave controllers in Cascade Mode should have all as Fast * interrupts or Normal interrupts, mixed interrupts are not * supported */ XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0x0); #ifdef XPAR_MICROBLAZE_BASE_VECTORS for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + 0x10); } #else for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), 0x10); } #endif /* Enable the Interrupt if it was enabled before calling this * function */ if (CurrentIER & Mask) { XIntc_Enable(InstancePtr, Id); } } else { /* Get the Enabled Interrupts */ CurrentIER = XIntc_In32(InstancePtr->BaseAddress + XIN_IER_OFFSET); Mask = XIntc_BitPosMask[Id];/* Convert from integer id to bit mask */ /* Disable the Interrupt if it was enabled before * calling this function */ if (CurrentIER & Mask) { XIntc_Disable(InstancePtr, Id); } /* * Disable the selected interrupt as Fast Interrupt by reading the * interrupt mode register and then modifying only the * specified interrupt id */ Imr = XIntc_In32(InstancePtr->BaseAddress + XIN_IMR_OFFSET); XIntc_Out32(InstancePtr->BaseAddress + XIN_IMR_OFFSET, Imr & ~Mask); #ifdef XPAR_MICROBLAZE_BASE_VECTORS for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + 0x10); } #else for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(InstancePtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), 0x10); } #endif /* Enable the Interrupt if it was enabled before * calling this function */ if (CurrentIER & Mask) { XIntc_Enable(InstancePtr, Id); } } } /*****************************************************************************/ /** * * Initializes Slave controllers in Cascade mode. The initialization entails: * - Initial vector table with stub function calls * - All interrupt sources are disabled for last controller. * - All interrupt sources are disabled except sources to 31 pin of * primary and secondary controllers * - Interrupt outputs are disabled * * @param InstancePtr is a pointer to the XIntc instance to be worked on. * * @return None * * @note None. * ******************************************************************************/ static void XIntc_InitializeSlaves(XIntc * InstancePtr) { int Index; u32 Mask; XIntc_Config *CfgPtr; int Id; Mask = XIntc_BitPosMask[31]; /* Convert from integer id to bit mask */ /* Enable interrupt id with 31 for Master * interrupt controller */ XIntc_Out32(InstancePtr->CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask); for (Index = 1; Index <= XPAR_XINTC_NUM_INSTANCES - 1; Index++) { CfgPtr = XIntc_LookupConfig(Index); XIntc_Out32(CfgPtr->BaseAddress + XIN_IAR_OFFSET, 0xFFFFFFFF); if (CfgPtr->IntcType != XIN_INTC_LAST) { /* Enable interrupt ids with 31 for secondary * interrupt controllers */ XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, Mask); } else { XIntc_Out32(CfgPtr->BaseAddress + XIN_IER_OFFSET, 0x0); } /* Disable Interrupt output */ XIntc_Out32(CfgPtr->BaseAddress + XIN_MER_OFFSET, 0); /* Set all interrupts as normal mode if Fast Interrupts * are enabled */ if(CfgPtr->FastIntr == TRUE) { XIntc_Out32(CfgPtr->BaseAddress + XIN_IMR_OFFSET, 0); #ifdef XPAR_MICROBLAZE_BASE_VECTORS for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), XPAR_MICROBLAZE_BASE_VECTORS + 0x10); } #else for (Id = 0; Id < 32 ; Id++) { XIntc_Out32(CfgPtr->BaseAddress + XIN_IVAR_OFFSET + (Id * 4), 0x10); } #endif } /* * Initialize all the data needed to perform interrupt * processing for each interrupt ID up to the maximum used */ for (Id = 0; Id < CfgPtr->NumberofIntrs; Id++) { /* * Initalize the handler to point to a stub to handle an * interrupt which has not been connected to a handler. * Only initialize it if the handler is 0 or * XNullHandler, which means it was not initialized * statically by the tools/user.Set the callback * reference to this instance so that unhandled * interrupts can be tracked. */ if ((CfgPtr->HandlerTable[Id].Handler == 0) || (CfgPtr->HandlerTable[Id].Handler == XNullHandler)) { CfgPtr->HandlerTable[Id].Handler = StubHandler; } CfgPtr->HandlerTable[Id].CallBackRef = InstancePtr; } } }