6
\$\begingroup\$

I'm using an STM32F303 MCU and I've noticed that the SysTick can be set up to cause an exception, which seems to mentioned quite often in various User Guides. This way, it will have a priority level higher than regular Interrupts.

On the other hand, it seems to be possible to set up Systick as an interrupt in NVIC as well. It has its own interrupt request number and it seems it can be set to pending state. Because the NVIC interrupts have programable priority levels, we could also set it up this way as well.

I'm not really sure what's the difference between these two approaches using the SysTick.

\$\endgroup\$
  • 1
    \$\begingroup\$ Just a shot in the dark: Is your program by any chance in C++? If so, remember you will need to wrap your SysTick_Handler or it's declaration in 'extern "C"'. \$\endgroup\$ – Tut Sep 28 '17 at 13:19
  • \$\begingroup\$ @Tut No, in this case, it's pure C, but thanks for the tip! \$\endgroup\$ – AndrejaKo Sep 28 '17 at 13:25
  • 1
    \$\begingroup\$ Can you expand on your second paragraph, maybe with examples. I wonder if there is some subtle confusion here. The NVIC handles all exceptions, including IRQs. \$\endgroup\$ – Sean Houlihane Sep 28 '17 at 15:03
  • 1
    \$\begingroup\$ @Sean Houlihane You nailed it! I'm actually just getting back into ARM programming after several years of Matlab. I got a project from a senior developer at my company which systematically tries to use SysTick as if it were a regular interrupt, resulting in my second paragraph, subtle confusion and numerous bus and hard faults. \$\endgroup\$ – AndrejaKo Sep 28 '17 at 18:39
  • \$\begingroup\$ @AndrejaKo see my updated answer to quickly find all places where SysTick is treated as an interrupt. \$\endgroup\$ – berendi Sep 28 '17 at 19:40
13
\$\begingroup\$

A couple of definitions first:

In the Cortex-M programming manual, an Exception is anything that breaks the normal program flow, and invokes a handler from the vector table, and Interrupts are a subset of Exceptions, coming from the peripherals outside the ARM core. Because SysTick is implemented in the Cortex-M core, it is considered an exception, but not an interrupt.

Exceptions have an Exception Number, starting from 0. Interrupts have an IRQ Number, starting from 0. Because all Interrupts are Exceptions, they all get an Exception Number, which is 16 higher than the IRQ Number. The Exceptions that are not Interrupts (including SysTick) have Exception Numbers in the 0-15 range, smaller than the Exception Numbers of the Interrupts. Somewhat confusingly, Exceptions that are not Interrupts have IRQ Numbers too, which by extension fall into the range from -16 to -1. SysTick has Exception Number 15, and IRQ Number -1.

I'm using an STM32F303 MCU and I've noticed that the SysTick can be set up to cause an exception, which seems to mentioned quite often in various User Guides. This way, it will have a priority level higher than regular Interrupts.

All exceptions except Reset, NMI, and Hardfault have configurable priorities. It's just configured differently for interrupts and other exceptions. See the CMSIS implementation as a clear example:

__STATIC_INLINE void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)
{
  if ((int32_t)(IRQn) < 0)
  {
    SCB->SHP[(((uint32_t)(int32_t)IRQn) & 0xFUL)-4UL] = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
  else
  {
    NVIC->IP[((uint32_t)(int32_t)IRQn)]               = (uint8_t)((priority << (8U - __NVIC_PRIO_BITS)) & (uint32_t)0xFFUL);
  }
}

You can call NVIC_SetPriority or manipulate SCB->SHP directly to give SysTick a lower priority than any other interrupt.

SysTick has indeed a default priority level that is higher than any interrupt, but that's only because at reset, all priorities are set to 0, and in case of a tie, the lower IRQ number wins, in this case, SysTick with -1.

On the other hand, it seems to be possible to set up Systick as an interrupt in NVIC as well. It has its own interrupt request number and it seems it can be set to pending state. Because the NVIC interrupts have programable priority levels, we could also set it up this way as well.

Only interrupts are configurable through the NVIC registers, and SysTick is not an interrupt. NVIC registers have no place for negative IRQ numbers, in bitmasks or elsewhere.

SysTick can indeed be set to a pending state, but that's done through SCB->ICSR, not in NVIC.

Note that NVIC_SetPriority() and NVIC_GetPriority() are the only NVIC_ functions in CMSIS that deal with negative IRQ numbers properly. Other functions like NVIC_SetPendingIRQ() or NVIC_EnableIRQ() just accept negative IRQ numbers happily, do some bit shuffling on them that results in a HUGE offset from the NVIC registers, and scribble some faraway memory address, possibly causing a hardfault, or other strange behaviour. HAL_NVIC_ functions do some bounds checking when you enable USE_FULL_ASSERT in your headers, but otherwise they just let invalid parameters through to the CMSIS NVIC functions.

EDIT

There is a neat trick to find all places where a function is called with a negative parameter. Put this into a common header:

#define NVIC_EnableIRQ(x) ((void)sizeof(char[x]))

It's a compile-time error whenever this construct is invoked with a negative number. Repeat this for every NVIC function except NVIC_SetPriority() and NVIC_GetPriority().

\$\endgroup\$
3
\$\begingroup\$

The fundamental difference between the systick and peripheral interrupts is that the systick is specified by ARM to be at IRQ 6 (0x003C) when it is available in the core.
It is also part of the ARM Cortex, clocked by the same clock and thus synchronous.

The other exceptions (interrupts) are up to the manufacturer to decide what base priority (offset) and source they have.

From the ST Programming Manual (PM0056):

A SysTick exception is an exception the system timer generates when it reaches zero. Software can also generate a SysTick exception. In an OS environment, the processor can use this exception as system tick.

A interrupt, or IRQ, is an exception signalled by a peripheral, or generated by a software request. All interrupts are asynchronous to instruction execution. In the system

\$\endgroup\$
  • 1
    \$\begingroup\$ Exception priorities are configurable on the Cortex-M series, except Reset, NMI and Hardfault. See the desciption of SCB->SHPR{1,2,3} in the programming manual. \$\endgroup\$ – berendi Sep 28 '17 at 13:25
  • 1
    \$\begingroup\$ @berendi That is correct. But they call every interrupt an exception since it is an exception to normal program flow. \$\endgroup\$ – Jeroen3 Sep 28 '17 at 14:10
  • 1
    \$\begingroup\$ @PeterJ_01 Guaranteed might indeed not be the correct word. Do you know parts with a asynchronously clocked system tick? \$\endgroup\$ – Jeroen3 Sep 28 '17 at 17:49
  • 1
    \$\begingroup\$ If the logic supplied by ARM feeds the clock signal to the systick counter as to other parts of the core (which I'm pretty sure it does), how could a chip manufacturer make systick non-synchronous? \$\endgroup\$ – supercat Sep 28 '17 at 21:38
  • 1
    \$\begingroup\$ @PeterJ_01 It will still be IRQ 6. But you can change the priority groups in the NVIC. But it will always be 6, in every Cortex you get. \$\endgroup\$ – Jeroen3 Sep 29 '17 at 7:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.