Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
15 years ago

Interrupt 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!

17 Replies