Altera_Forum
Honored Contributor
15 years agoInterrupt priority IIR
Hi all,
I'm using the NIOSII with an Internal Interrupt Controller (IIR) and 8 IRQ's triggered by PIO edges. I assigned a number to each one of the IRQs which represents it's priority where a lower number means a higher priority (hope I'm right so far). Now here comes the problem. I found the following section in the NIOS II Software Developers Handbook under nested hardware interrupts: "By default, the HAL diables interrupt when it dispatches an ISR. This means that only one ISR can be executed at any time, and ISRs are executed on a first-come first-served basis. [...] However, first-come first-served execution means that the HALhardware interrupt priorities only have an effect if two IRQs are active at the same time. A low-priority interrupt occuring before a higher-priority interrupt can prevent the higher-priority interrupt ISR from executing." -> I don't want that. I want my ISRs to be pre-empted by higher-priority interrupts and return to the lower-priority interrupts after the higher-priority interrupt has been dispatched. So I thought I better use nested interrupts, right? Now I found two ways to enable nested interrupts: 1. The one in the NIOS II Software Developer's handbook tells me to use two functions: alt_irq_interruptible() and alt_irq_non_interruptible() to "bracket code in a processor-intensive ISR. 2. In the NIOS II Processor Reference Handbook it tells to enable nested interrupts by setting the status.PIE Register to 1 near the beginnung of an ISR. How? By calling alt_irq_enable_all()? If yes, which argument should I apply? Now my question is which "method" to use and more important HOW to use. Any help is highly appriciated. Heres my code for initializing an IRQ + it's ISR:void init_checkout_sd()
{
/* Recast the edge_capture pointer to match the alt_irq_register() function
* prototype. */
void* edge_capture_ptr = (void*) &checkout_edge_capture;
/* Enable first four interrupts. */
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(SD_CHECKOUT_IRQ_BASE, 0xf); // 1
/* Reset the edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(SD_CHECKOUT_IRQ_BASE, 0);
/* Register the interrupt handler. */
alt_irq_register(SD_CHECKOUT_IRQ_IRQ, edge_capture_ptr, checkout_SD_ISR);
} static void checkout_SD_ISR(void* context, uint32 id)
{
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(SD_CHECKOUT_IRQ_BASE, 0);
/* Cast context to edge_capture's type. It is important that this be
* declared volatile to avoid unwanted compiler optimization.*/
volatile int* edge_capture_ptr = (volatile int*) context;
/* Store the value in the Button's edge capture register in *context. */
*edge_capture_ptr = IORD_ALTERA_AVALON_PIO_EDGE_CAP(SD_CHECKOUT_IRQ_BASE);
//do something here...
/* Reset the Button's edge capture register. */
IOWR_ALTERA_AVALON_PIO_EDGE_CAP(SD_CHECKOUT_IRQ_BASE, 0);
/* reset interrupt capability for the Button PIO. */
IOWR_ALTERA_AVALON_PIO_IRQ_MASK(SD_CHECKOUT_IRQ_BASE, 0xf);
/* Read the PIO to delay ISR exit. This is done to prevent a
spurious interrupt in systems with high processor -> pio
latency and fast interrupts. */
IORD_ALTERA_AVALON_PIO_EDGE_CAP(SD_CHECKOUT_IRQ_BASE);
} Thanks!