Forum Discussion
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!17 Replies
- Altera_Forum
Honored Contributor
Hi,
--- Quote Start --- 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. --- Quote End --- I would use that in order to make your ISR interruptible. --- Quote Start --- 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? --- Quote End --- I think, this is done by alt_irq_interruptible(). Regards - Altera_Forum
Honored Contributor
hey pillemann!
thanks for the fast response. As far as i know alt_irq_interruptible() needs to be called together with alt_irq_non_interruptible() to bracket the code right? Are there any parameters that needs to be applied? Short example will do. Greetings! - Altera_Forum
Honored Contributor
--- Quote Start --- As far as i know alt_irq_interruptible() needs to be called together with alt_irq_non_interruptible() to bracket the code right? --- Quote End --- Exactly! Maybe something like that
If you call alt_irq_interruptible(id) with the IRQ-id of the ISR then only higher priority IRQs are able to interrupt. Greetsstatic void ISR_TIMER(void* context, int id) { int tempcontext; // optional: Do something which is not interruptible tempcontext= alt_irq_interruptible(id); // Do something which is interruptible alt_irq_non_interruptible(tempcontext); } - Altera_Forum
Honored Contributor
thank you very much! I'll try this and let you know. :)
- Altera_Forum
Honored Contributor
Hi again!
Ok I tried to implement the alt_irq_interruptible() and alt_irq_non_interruptible() functions but I get an undefined reference error:
The <sys/alt_irq.h> headerfile is included. Is there any other headerfile required? I also checked the "HAL API reference" (can be found here: http://www.altera.com/literature/hb/nios2/n2sw_nii52010.pdf) and noticed that both functions are not listed (any longer?). Maybe those are deprecated? What would be the alternative? Thanks in advance!undefined reference to `alt_irq_interruptible' undefined reference to `alt_irq_non_interruptible' - Altera_Forum
Honored Contributor
Hi,
I guess you are using NIOS IDE/EDS 9.1 or higher? My assumption is that you are using the ENHANCED Interrupt API which doesn't implement alt_irq_interruptible()/alt_irq_non_interruptible() anymore. The only way I know (means not that there is not an other way) how to use the both functions, is to manually change ALT_ENHANCED_INTERRUPT_API_PRESENT in system.h to ALT_LEGACY_INTERRUPT_API_PRESENT. Every time you regenerate your BSP or syslib you have to change it again! But that's just a workaround. I had the same problems and then included the VIC as EIC in my design. You can use the VIC with ENHANCED API. But much better, the VIC can handle the interruptible stuff without changing your code. That means your ISRs are interruptible without a call to alt_irq_interruptible(). Disadvantage: Until the momen, I don't know how set the option that an IRQ is not interruptible. - Altera_Forum
Honored Contributor
Hi pillemann!
Yep, you are completly right. I changed it to ALT_LEGACY_INTERRUPT_API_PRESENT and voilá it works. The errors are gone and I also noticed a warning which states "implicit declaration of alt_irq_register();" disappeared. This seems logical since it's also a legacy function. I also thought about using the VIC as an EIC but I 1st wanted to check this "version" of IRQ interuption. Maybe I'll also (have to) use the VIC later. My first ideas for your problem would be to set the non-interruptible IRQ to highest priority or to disable all other IRQ's while inside the ISR. But I guess you already thought about this :P - Altera_Forum
Honored Contributor
Hi!
--- Quote Start --- My first ideas for your problem would be to set the non-interruptible IRQ to highest priority or to disable all other IRQ's while inside the ISR. But I guess you already thought about this :P --- Quote End --- Well, Yes and No;-) If you have more than one IRQ which should not be interrupted, the highest priority thing does not work acceptably. But disabling all might me a solution .... Though I could imagine that the IRQ can be interrupted just the moment you are executing the disabling-all stuff. But at the moment I am lucky. I do not need it yet:-) Thanks for your suggestion! - Altera_Forum
Honored Contributor
--- Quote Start --- Hi, I guess you are using NIOS IDE/EDS 9.1 or higher? My assumption is that you are using the ENHANCED Interrupt API which doesn't implement alt_irq_interruptible()/alt_irq_non_interruptible() anymore. The only way I know (means not that there is not an other way) how to use the both functions, is to manually change ALT_ENHANCED_INTERRUPT_API_PRESENT in system.h to ALT_LEGACY_INTERRUPT_API_PRESENT. Every time you regenerate your BSP or syslib you have to change it again! But that's just a workaround. I had the same problems and then included the VIC as EIC in my design. You can use the VIC with ENHANCED API. But much better, the VIC can handle the interruptible stuff without changing your code. That means your ISRs are interruptible without a call to alt_irq_interruptible(). Disadvantage: Until the momen, I don't know how set the option that an IRQ is not interruptible. --- Quote End --- Well there should be a disvantage in using the LEGACY api.. How can i use the enhanced API? i dont find documentations of a simple "Hello world button" using IRQ - Altera_Forum
Honored Contributor
Hi,
take a look at this application note. Maybe it might help you. http://www.altera.com/literature/an/an595.pdf