10

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.

AndrejaKo
  • 23,261
  • 25
  • 110
  • 186
  • 1
    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"'. – Tut Sep 28 '17 at 13:19
  • @Tut No, in this case, it's pure C, but thanks for the tip! – AndrejaKo Sep 28 '17 at 13:25
  • 1
    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. – Sean Houlihane Sep 28 '17 at 15:03
  • 1
    @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. – AndrejaKo Sep 28 '17 at 18:39
  • @AndrejaKo see my updated answer to quickly find all places where SysTick is treated as an interrupt. – followed Monica to Codidact Sep 28 '17 at 19:40

2 Answers2

20

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().

4

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

Jeroen3
  • 21,976
  • 36
  • 73
  • 1
    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. – followed Monica to Codidact Sep 28 '17 at 13:25
  • 1
    @berendi That is correct. But they call every interrupt an exception since it is an exception to normal program flow. – Jeroen3 Sep 28 '17 at 14:10
  • @Jeroen3 `The fundamental difference between the systick and peripheral interrupts is that the SysTick is guaranteed to be at priority 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.` everything here is not the truth. It does not have any guaranteed priority and can be clocked by another clock source (if refeference clock is provided by the implementation) than the core clock. What is the source document of this revelations? – 0___________ Sep 28 '17 at 17:00
  • 1
    @PeterJ_01 Guaranteed might indeed not be the correct word. Do you know parts with a asynchronously clocked **system tick**? – Jeroen3 Sep 28 '17 at 17:49
  • How the internal clock tree is designed is 100% up to chip manufacturer. It does not matter if there are any commercially available chips. Just this part of your answer is 100% wrong. `Guaranteed might indeed not be the correct word` - it is not the wrong word it is your wrong assumption that SysTick has constant priority. But it is the same as any other interrupt except HW exceptions which have the fixed priorities. **IMO your answer is misleading and wrong and should be deleted.** – 0___________ Sep 28 '17 at 18:34
  • 1
    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? – supercat Sep 28 '17 at 21:38
  • @supercat Precisely, you can't. – Jeroen3 Sep 29 '17 at 07:12
  • 1
    @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. – Jeroen3 Sep 29 '17 at 07:13
  • IRQ **number** 6 not the priority 6, which makes a **huge** difference. Anyway the number is secondary. – 0___________ Sep 29 '17 at 07:17
  • @PeterJ_01 If no priorities have been set, the number is the priority. Hence "base priority". – Jeroen3 Sep 29 '17 at 07:27