Interrupts nesting

29 Jan 2011

To make a short story shorter : I have a program running an USB interrupt and a timer0 interrupt(200kHz frequency). The timer0 is suppose to have a high priority and should interrupt the USB routine. But with USB traffic ongoing I'm loosing about 25% of my timer irqs (they do not interrupt the USB irq). If I move the USB on the main loop instead of the IRQ I get all the timer interrupts. So is there any trick here? Does somehow the compiler make interrupt not nestable (disable irq on entry or something like that)? Thanks everyone.

31 Jan 2011

Just a shot in the dark, but are either of the interrupts just triggering the movement of data from USB? DMA might be a good solution if this is the case. The data movement interrupt that is issued could be serviced by the DMA instead of the CPU, leaving the CPU the task of processing whatever buffer the DMA leaves behind. The CPU should be used to do processing, not swapping memory around.

31 Jan 2011

Hi Mihai,

This sounds like expected behaviour if the interrupts have the same priority. Assuming that is the case, whilst the mbed library currently just leaves the priorities alone (i.e. they all are the same level, so they don't pre-empt each other), you can still set them using the CMSIS functions. Here is an example:

Import program

00001 // Example running the mbed Tickers at a lower priority
00002 
00003 #include "mbed.h"
00004 
00005 volatile int counter = 0;
00006 void timing_critical() {
00007     counter++;
00008 }
00009 
00010 void long_event() {
00011     wait_ms(50);
00012 }
00013 
00014 PwmOut out(p25);
00015 InterruptIn in(p26);
00016 Ticker tick;
00017 
00018 int main() {
00019     out.period_ms(10);
00020     out.pulsewidth_ms(5);
00021     in.rise(&timing_critical);
00022 
00023     printf("1) InterruptIn only...\n");    
00024     for(int i=0; i<5; i++) {
00025         counter = 0;
00026         wait(1);
00027         printf("counts/sec = %d\n", counter);
00028     }
00029 
00030     tick.attach(&long_event, 0.1);    
00031     
00032     printf("2) InterruptIn plus long running occasional ticker event...\n");    
00033     for(int i=0; i<5; i++) {
00034         counter = 0;
00035         wait(1);
00036         printf("count/sec = %d\n", counter);
00037     }
00038     
00039     printf("3) InterruptIn plus long running occasional ticker event at lower priority...\n");    
00040     NVIC_SetPriority(TIMER3_IRQn, 255); // set mbed tickers to lower priority than other things
00041     for(int i=0; i<5; i++) {
00042         counter = 0;
00043         wait(1);
00044         printf("counter = %d\n", counter);
00045     }
00046 }

Hope that helps.

Simon

31 Jan 2011

Indeed DMA is a solution, meanwhile I've moved the USB to the main loop and that's it. Simon, the thing is that USB has a lower priority (0x1f if I haven't mess up something when writing the registers - NVIC->IP[6] = (0x1f << 3)) and still the timer routine doesn't seem to interrupt it. So as long as timer has higher priority it should interrupt the USB but this doesn't seem to happen.

21 Jan 2019

Simon Ford, What do I do if there is an error in "TIMER3_IRQn"?

24 Jan 2019

Daniel,

TIMER3_IRQn is the interrupt used for the timers on the LPC1768 running Mbed 2, which is what everyone was using 8 years ago when this thread was written.

You need to use the correct interrupt name for the hardware timer used on your platform.