Nios® V/II Embedded Design Suite (EDS)
Support for Embedded Development Tools, Processors (SoCs and Nios® V/II processor), Embedded Development Suites (EDSs), Boot and Configuration, Operating Systems, C and C++

Interrupt priority IIR

Altera_Forum
Honored Contributor II
4,613 Views

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!
0 Kudos
17 Replies
Altera_Forum
Honored Contributor II
1,453 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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!
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

 

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

 

static 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); } If you call alt_irq_interruptible(id) with the IRQ-id of the ISR then only higher priority IRQs are able to interrupt. 

 

Greets
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

thank you very much! I'll try this and let you know. :)

0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

Hi again! 

 

Ok I tried to implement the alt_irq_interruptible() and alt_irq_non_interruptible() functions but I get an undefined reference error: 

 

undefined reference to `alt_irq_interruptible' undefined reference to `alt_irq_non_interruptible'  

 

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!
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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.
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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!
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

 

--- 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
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

Hi, 

 

take a look at this application note. Maybe it might help you. 

http://www.altera.com/literature/an/an595.pdf
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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 !!!!!!!!!!
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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

0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

Or is something else causing a stack or heap overflow?

0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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 ?
0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

Waiting for reply..................

0 Kudos
Altera_Forum
Honored Contributor II
1,453 Views

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.
0 Kudos
Reply