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

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    If you check "Enable preemption into a new register set", this has the effect of NOT disabling interrupts while an ISR is executing. We had to do this because e.g. the SGDMA receive ISR runs "forever" and we were missing higher priority interrupts that occurred during the SGDMA RX ISR.

    Of course you have to ensure you don't reenable the interrupt too soon so the same interrupt won't nest on itself.

    Bill
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    Hi everyone,

    I have added my own customized component "Dual FIFO" in SOPC builder.

    I have kept its priority 0 to ensure it has top priority.

    I have programmed in such a way that every 2 milli-sec an interrupt will come to NIOS II.

    In my NIOS II application program, I registered the interrupt and written ISR.

    Everytime an interrupt comes, ISR gets executed.

    BUTTTT after some time ISR doen't get executed or I can say my system doesn't respond.

    I experimented and calculated that ISR runs for fix number of times 14563 and stops after this.

    What might be the reason ?

    Please reply...

    URGENT !!!!!!!!!!
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    What do you mean with your system does not respond? Does the NIOS crash or does your "DUAL FIFO" not generate an IRQ anymore?

  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    I was using TCP send() inside the ISR.

    Now I removed send() from the ISR and placed it one task.

    It's working now continuously.

    What if I want to use send inside ISR?

    What care should be taken ?
  • Altera_Forum's avatar
    Altera_Forum
    Icon for Honored Contributor rankHonored Contributor

    In order to call a function from within an ISR the subsystem containing the function has to carefully protect all of it data areas (and thus a lot of its code paths) from the effects of being re-entered from an ISR.

    This typically means disabling interrupts for large tracts of code - which will adversely affect interrupt latency.

    Provided your ISR can't interrupt any of the ethernet ISRs, you might manage by disabling your (or all) interrupts across ALL socket functions in all threads - and include any system task used for network processing.

    Much better is to put the data into a locally defined private circular buffer and get a task to do the actual send.

    In general the only functions you can call from an interrupt are those explicitly marked as being callable from an interrupt (or that clearly have to be callable from an interrupt). These will all be very low-level functions.