void vPortISRHandler( void *pvNullDoNotUse ) { uint32_t ulInterruptStatus, ulInterruptMask = 1UL; BaseType_t xInterruptNumber; XIntc_Config *pxInterruptController; XIntc_VectorTableEntry *pxTable; /* Just to remove compiler warning. */ ( void ) pvNullDoNotUse; /* Get the configuration by using the device ID - in this case it is assumed that only one interrupt controller is being used. */ pxInterruptController = &XIntc_ConfigTable[ XPAR_XPS_INTC_0_DEVICE_ID ]; /* Which interrupts are pending? */ ulInterruptStatus = XIntc_mGetIntrStatus( pxInterruptController->BaseAddress ); for( xInterruptNumber = 0; xInterruptNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; xInterruptNumber++ ) { if( ulInterruptStatus & 0x01UL ) { /* Clear the pending interrupt. */ XIntc_mAckIntr( pxInterruptController->BaseAddress, ulInterruptMask ); /* Call the registered handler. */ pxTable = &( pxInterruptController->HandlerTable[ xInterruptNumber ] ); pxTable->Handler( pxTable->CallBackRef ); } /* Check the next interrupt. */ ulInterruptMask <<= 0x01UL; ulInterruptStatus >>= 0x01UL; /* Have we serviced all interrupts? */ if( ulInterruptStatus == 0UL ) { break; } } }
/** * * This function is the primary interrupt handler for the driver. It must be * connected to the interrupt source such that is called when an interrupt of * the interrupt controller is active. It will resolve which interrupts are * active and enabled and call the appropriate interrupt handler. It uses * the AckBeforeService flag in the configuration data to determine when to * acknowledge the interrupt. Highest priority interrupts are serviced first. * This function assumes that an interrupt vector table has been previously * initialized.It does not verify that entries in the table are valid before * calling an interrupt handler. In Cascade mode this function calls * XIntc_CascadeHandler to handle interrupts of Master and Slave controllers. * This functions also handles interrupts nesting by saving and restoring link * register of Microblaze and Interrupt Level register of interrupt controller * properly. * @param DeviceId is the zero-based device ID defined in xparameters.h * of the interrupting interrupt controller. It is used as a direct * index into the configuration data, which contains the vector * table for the interrupt controller. Note that even though the * argument is a void pointer, the value is not a pointer but the * actual device ID. The void pointer type is necessary to meet * the XInterruptHandler typedef for interrupt handlers. * * @return None. * * @note For nested interrupts, this function saves microblaze r14 * register on entry and restores on exit. This is required since * compiler does not support nesting. This function enables * Microblaze interrupts after blocking further interrupts * from the current interrupt number and interrupts below current * interrupt proirity by writing to Interrupt Level Register of * INTC on entry. On exit, it disables microblaze interrupts and * restores ILR register default value(0xFFFFFFFF)back. It is * recommended to increase STACK_SIZE in linker script for nested * interrupts. * ******************************************************************************/ void XIntc_DeviceInterruptHandler(void *DeviceId) { u32 IntrStatus; u32 IntrMask = 1; int IntrNumber; XIntc_Config *CfgPtr; u32 Imr; /* Get the configuration data using the device ID */ CfgPtr = &XIntc_ConfigTable[(u32)DeviceId]; #if XPAR_INTC_0_INTC_TYPE != XIN_INTC_NOCASCADE if (CfgPtr->IntcType != XIN_INTC_NOCASCADE) { XIntc_CascadeHandler(DeviceId); } else #endif { /* This extra brace is required for compilation in Cascade Mode */ #if XPAR_XINTC_HAS_ILR == TRUE #ifdef __MICROBLAZE__ volatile u32 R14_register; /* Save r14 register */ R14_register = mfgpr(r14); #endif volatile u32 ILR_reg; /* Save ILR register */ ILR_reg = Xil_In32(CfgPtr->BaseAddress + XIN_ILR_OFFSET); #endif /* Get the interrupts that are waiting to be serviced */ IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); /* Mask the Fast Interrupts */ if (CfgPtr->FastIntr == TRUE) { Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); IntrStatus &= ~Imr; } /* Service each interrupt that is active and enabled by * checking each bit in the register from LSB to MSB which * corresponds to an interrupt input signal */ for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; IntrNumber++) { if (IntrStatus & 1) { XIntc_VectorTableEntry *TablePtr; #if XPAR_XINTC_HAS_ILR == TRUE /* Write to ILR the current interrupt * number */ Xil_Out32(CfgPtr->BaseAddress + XIN_ILR_OFFSET, IntrNumber); /* Read back ILR to ensure the value * has been updated and it is safe to * enable interrupts */ Xil_In32(CfgPtr->BaseAddress + XIN_ILR_OFFSET); /* Enable interrupts */ Xil_ExceptionEnable(); #endif /* If the interrupt has been setup to * acknowledge it before servicing the * interrupt, then ack it */ if (CfgPtr->AckBeforeService & IntrMask) { XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); } /* The interrupt is active and enabled, call * the interrupt handler that was setup with * the specified parameter */ TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); TablePtr->Handler(TablePtr->CallBackRef); /* If the interrupt has been setup to * acknowledge it after it has been serviced * then ack it */ if ((CfgPtr->AckBeforeService & IntrMask) == 0) { XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); } #if XPAR_XINTC_HAS_ILR == TRUE /* Disable interrupts */ Xil_ExceptionDisable(); /* Restore ILR */ Xil_Out32(CfgPtr->BaseAddress + XIN_ILR_OFFSET, ILR_reg); #endif /* * Read the ISR again to handle architectures * with posted write bus access issues. */ XIntc_GetIntrStatus(CfgPtr->BaseAddress); /* * If only the highest priority interrupt is to * be serviced, exit loop and return after * servicing * the interrupt */ if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { #if XPAR_XINTC_HAS_ILR == TRUE #ifdef __MICROBLAZE__ /* Restore r14 */ mtgpr(r14, R14_register); #endif #endif return; } } /* Move to the next interrupt to check */ IntrMask <<= 1; IntrStatus >>= 1; /* If there are no other bits set indicating that all * interrupts have been serviced, then exit the loop */ if (IntrStatus == 0) { break; } } #if XPAR_XINTC_HAS_ILR == TRUE #ifdef __MICROBLAZE__ /* Restore r14 */ mtgpr(r14, R14_register); #endif #endif } }
/** * * This function is called by primary interrupt handler for the driver to handle * all Controllers in Cascade mode.It will resolve which interrupts are active * and enabled and call the appropriate interrupt handler. It uses the * AckBeforeService flag in the configuration data to determine when to * acknowledge the interrupt. Highest priority interrupts are serviced first. * This function assumes that an interrupt vector table has been previously * initialized. It does not verify that entries in the table are valid before * calling an interrupt handler.This function calls itself recursively to handle * all interrupt controllers. * * @param DeviceId is the zero-based device ID defined in xparameters.h * of the interrupting interrupt controller. It is used as a direct * index into the configuration data, which contains the vector * table for the interrupt controller. * * @return None. * * @note * ******************************************************************************/ static void XIntc_CascadeHandler(void *DeviceId) { u32 IntrStatus; u32 IntrMask = 1; int IntrNumber; u32 Imr; XIntc_Config *CfgPtr; static int Id = 0; /* Get the configuration data using the device ID */ CfgPtr = &XIntc_ConfigTable[(u32)DeviceId]; /* Get the interrupts that are waiting to be serviced */ IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); /* Mask the Fast Interrupts */ if (CfgPtr->FastIntr == TRUE) { Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); IntrStatus &= ~Imr; } /* Service each interrupt that is active and enabled by * checking each bit in the register from LSB to MSB which * corresponds to an interrupt input signal */ for (IntrNumber = 0; IntrNumber < CfgPtr->NumberofIntrs; IntrNumber++) { if (IntrStatus & 1) { XIntc_VectorTableEntry *TablePtr; /* In Cascade mode call this function recursively * for interrupt id 31 and until interrupts of last * instance/controller are handled */ if ((IntrNumber == 31) && (CfgPtr->IntcType != XIN_INTC_LAST) && (CfgPtr->IntcType != XIN_INTC_NOCASCADE)) { XIntc_CascadeHandler((void *)++Id); Id--; } /* If the interrupt has been setup to * acknowledge it before servicing the * interrupt, then ack it */ if (CfgPtr->AckBeforeService & IntrMask) { XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); } /* Handler of 31 interrupt Id has to be called only * for Last controller in cascade Mode */ if (!((IntrNumber == 31) && (CfgPtr->IntcType != XIN_INTC_LAST) && (CfgPtr->IntcType != XIN_INTC_NOCASCADE))) { /* The interrupt is active and enabled, call * the interrupt handler that was setup with * the specified parameter */ TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); TablePtr->Handler(TablePtr->CallBackRef); } /* If the interrupt has been setup to acknowledge it * after it has been serviced then ack it */ if ((CfgPtr->AckBeforeService & IntrMask) == 0) { XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); } /* * Read the ISR again to handle architectures with * posted write bus access issues. */ XIntc_GetIntrStatus(CfgPtr->BaseAddress); /* * If only the highest priority interrupt is to be * serviced, exit loop and return after servicing * the interrupt */ if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { return; } } /* Move to the next interrupt to check */ IntrMask <<= 1; IntrStatus >>= 1; /* If there are no other bits set indicating that all interrupts * have been serviced, then exit the loop */ if (IntrStatus == 0) { break; } } }
/** * * This function is the primary interrupt handler for the driver. It must be * connected to the interrupt source such that is called when an interrupt of * the interrupt controller is active. It will resolve which interrupts are * active and enabled and call the appropriate interrupt handler. It uses * the AckBeforeService flag in the configuration data to determine when to * acknowledge the interrupt. Highest priority interrupts are serviced first. * The driver can be configured to service only the highest priority interrupt * or all pending interrupts using the {XIntc_SetOptions()} function or * the {XIntc_SetIntrSrvOption()} function. * * This function assumes that an interrupt vector table has been previously * initialized. It does not verify that entries in the table are valid before * calling an interrupt handler. * * @param DeviceId is the zero-based device ID defined in xparameters.h * of the interrupting interrupt controller. It is used as a direct * index into the configuration data, which contains the vector * table for the interrupt controller. Note that even though the * argument is a void pointer, the value is not a pointer but the * actual device ID. The void pointer type is necessary to meet * the XInterruptHandler typedef for interrupt handlers. * * @return None. * * @note * * The constant XPAR_INTC_MAX_NUM_INTR_INPUTS must be setup for this to compile. * Interrupt IDs range from 0 - 31 and correspond to the interrupt input signals * for the interrupt controller. XPAR_INTC_MAX_NUM_INTR_INPUTS specifies the * highest numbered interrupt input signal that is used. * ******************************************************************************/ void XIntc_DeviceInterruptHandler(void *DeviceId) { u32 IntrStatus; u32 IntrMask = 1; int IntrNumber; XIntc_Config *CfgPtr; u32 Imr; /* Get the configuration data using the device ID */ CfgPtr = &XIntc_ConfigTable[(u32) DeviceId]; /* Get the interrupts that are waiting to be serviced */ IntrStatus = XIntc_GetIntrStatus(CfgPtr->BaseAddress); /* Mask the Fast Interrupts */ if (CfgPtr->FastIntr == TRUE) { Imr = XIntc_In32(CfgPtr->BaseAddress + XIN_IMR_OFFSET); IntrStatus &= ~Imr; } /* Service each interrupt that is active and enabled by checking each * bit in the register from LSB to MSB which corresponds to an interrupt * intput signal */ for (IntrNumber = 0; IntrNumber < XPAR_INTC_MAX_NUM_INTR_INPUTS; IntrNumber++) { if (IntrStatus & 1) { XIntc_VectorTableEntry *TablePtr; /* If the interrupt has been setup to acknowledge it * before servicing the interrupt, then ack it */ if (CfgPtr->AckBeforeService & IntrMask) { XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); } /* The interrupt is active and enabled, call the * interrupt handler that was setup with the specified * parameter */ TablePtr = &(CfgPtr->HandlerTable[IntrNumber]); TablePtr->Handler(TablePtr->CallBackRef); /* If the interrupt has been setup to acknowledge it * after it has been serviced then ack it */ if ((CfgPtr->AckBeforeService & IntrMask) == 0) { XIntc_AckIntr(CfgPtr->BaseAddress, IntrMask); } /* * Read the ISR again to handle architectures with posted write * bus access issues. */ XIntc_GetIntrStatus(CfgPtr->BaseAddress); /* * If only the highest priority interrupt is to be * serviced, exit loop and return after servicing * the interrupt */ if (CfgPtr->Options == XIN_SVC_SGL_ISR_OPTION) { return; } } /* Move to the next interrupt to check */ IntrMask <<= 1; IntrStatus >>= 1; /* If there are no other bits set indicating that all interrupts * have been serviced, then exit the loop */ if (IntrStatus == 0) { break; } } }