Electronic – Why aren’t the interrupts nested in an ATSAM controller

cortex-m0interrupts

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.

Best Answer

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