# Why aren't my interrupts nested in an ATSAM controller?

The interrupt controller of an ATSAMD21 (based on a Cortex-M0+) is called NVIC (Nested Vector Interrupt controller), so I was hoping it would be easy to nest interrupts.

The documentation doesn't mention how an interrupt can interrupt another interrupt. Actually, it doesn't say much about the interrupts, as they don't even have their registers listed, being only mentioned under the chapter "Processor and Architecture", unlike other peripherals which have their own chapters.

Searching the headers and the debugger I found the following registers used by the interrupt controller:

• enable register. Every one of 28 possible interrupts has a bit here.
• pending register. same as above
• priority register.

Setting an interrupt to be of higher priority than another one, still doesn't allow it to interrupt the lower priority one.

The application notes about interrupts don't mention any way of nesting interrupts, it is rather written that:

Inside an ISR, interrupts are disabled. Therefore don’t do anything that requires an interrupt to be serviced.

EDIT : Thanks to pointing me to the ARM documentation, where it is stated that higher priority interrupts always preempt lower priority interrupts. However, some experiments show that it either does not happen on my board, or it takes too long.

Experimental setup

The links to this question showed statements that interrupt nesting is not only possible, but actually the only option for Cortex-M0 processors. Still, my experiments show otherwise.

In a timer overflow interrupt, the first thing I do is to check the value of the timer, thereby getting the interrupt latency (+ the few clocks required to read the timer). I calculate the maximum of this latency over the period of at least one minute.

• If I only have this timer running, I have times below 1.5 µs

• If I start several SPI senders (SERCOM), all transmitting continuously (all they do in their transmit interrupt is to fetch the next byte), I measure 4.2 µs

• If I put a deliberate time wasting code (a few floating point operations) into two of the SERCOM transmit interrupts, I measure 140 µs!

• If I put the timer interrupt to priority 0 (the highest) and all SERCOMs to priority 3, I measure 70 µs! Half of the time that I measured when all the interrupts had the same priority. This also seems to show that the SERCOM interrupt was never interrupted by the timer interrupt.

• If I double the floating point operations in the SERCOM interrupts, the worst case latency in the timer interrupt is almost 140 µs, which would indicate that they are not interrupted.

• If I put an endless loop after the float operations, the time is still 140 µs, so the endless loop does get interrupted. (And it was not optimized away - if I set all interrupt priorities back to the same value, it gets stuck in the endless loop)

EDIT My mistake was that although I set the priorities to the SERCOM interrupts, I didn't set it to all of them. SERCOM interrupt priorities have to be set individually. Closing the question, as I think it deviated too much from its original concept to have this posted as an answer.

• electronics.stackexchange.com/questions/74162/… – DiBosco Aug 22 '17 at 9:52
• Another one that may be useful is this which has another link within it. stackoverflow.com/questions/45789624/… – DiBosco Aug 22 '17 at 9:57
• @DiBosco : I will then check my experimental setup again. I tested it with an oscilloscope, a fast interrupt which toggles a portpin, and a slow interrupt which deliberately wastes time with a float division. It was not interrupted. – vsz Aug 22 '17 at 10:01
• I think I'd be tempted to put an infinite loop in one ISR then have a higher priority interrupt fired off to prove a point. – DiBosco Aug 22 '17 at 11:37
• @DiBosco : interestingly, the infinite loop in a lower priority ISR does get interrupted. But then why does it not get interrupted when it's merely doing some calculations for 70 µs? It might seem that preempting an interrupt has such a huge overhead? Anyway, the premise of my question seems flawed, now. – vsz Aug 22 '17 at 11:56

That's because the NVIC is not part of Atmel but instead it's a part of IP supplied by ARM. Therefore you will find all documentation regarding this part on the ARM website for your specific core https://developer.arm.com/docs/dui0662/latest/4-cortex-m0-peripherals/42-nested-vectored-interrupt-controller

• I specified ATSAMD21, which uses the Cortex-M0+ (added the latter to the question). Its interrupt documentation can be found here: infocenter.arm.com/help/topic/com.arm.doc.dui0497a/… which states that interrupts of different priorities are always nested. However, my experiments seem to disagree with this statement. Maybe I missed something, or the ATSAMD21 doesn't implement all of the M0's features? – vsz Aug 22 '17 at 11:12

Setting an interrupt to be of higher priority than another one, still doesn't allow it to interrupt the lower priority one.

Carful: Cortex-M use 0 as the highest priority, and num-of-prorities-minus-1 as the lowest priority. By default all interrupts have priority 0, so unless you initialize the NVIC correctly by using a higher number in NVIC_SetPriority(), you won't get nested interrupts.

In your example, the SERCOM interrupt cannot preemt the timer. You would have to set the SERCOMs to zero (or anything smaller than 3) and the TIMER to priority 3.

• Please check my description again. I don't want the SERCOM preempting the timer, I want the timer preempting the SERCOM. This is why I do my measurement in the timer, and this is why I put the time-wasting float operations in the SERCOM: to make it visible if it's not preempted. – vsz Aug 22 '17 at 11:35
• @vsz However, on the subject of pre-emption have you looked at the preempt priorities as discussed here: embeddedgurus.com/state-space/2014/02/… – DiBosco Aug 22 '17 at 11:44
• @DiBosco : I know about that, but by using NVIC_SetPriority() the correct values are shifted accordingly. – vsz Aug 22 '17 at 11:57
• Show us your code. You may simply have a bug in your testing code. – Turbo J Aug 22 '17 at 12:15