# vPortSuppressTicksAndSleep SysTick implementation wrong?

**URL:** <https://forums.freertos.org/t/vportsuppressticksandsleep-systick-implementation-wrong/13521>\
**Category:** ARM\
**Created:** [September 22, 2021, 7:23pm UTC](https://forums.freertos.org/t/vportsuppressticksandsleep-systick-implementation-wrong/13521 "2021-09-22T19:23:17Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jefflongo](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/jefflongo/32/1917_2.png) [@jefflongo](https://forums.freertos.org/u/jefflongo)\
**Post date:** [September 22, 2021, 7:23pm UTC](https://forums.freertos.org/t/vportsuppressticksandsleep-systick-implementation-wrong/13521/1 "2021-09-22T19:23:17Z")

</div>

Hello,

I have been taking a look at the default implementation of `vPortSuppressTicksAndSleep` for ARM\_CM4F which uses SysTick and can’t help but feeling that the code is incorrect (freertos-kernel-10.4.1/portable/GCC/ARM\_CM4F/port.c).

In summary, the default implementation changes the reload value of the SysTick timer to wake up on the scheduled RTOS tick. The relevant line of code is here:

```auto
ulReloadValue = portNVIC_SYSTICK_CURRENT_VALUE_REG + ( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) );

```

Where `ulTimerCountsForOneTick` is the ratio of the SysTick frequency to the RTOS tick frequency, and `xExpectedIdleTime` is the difference between the next task unblock time and the current RTOS tick.

Then later, when it has been decided to sleep:

```auto
            portNVIC_SYSTICK_LOAD_REG = ulReloadValue;
            portNVIC_SYSTICK_CURRENT_VALUE_REG = 0UL;

```

The portion of this code `( ulTimerCountsForOneTick * ( xExpectedIdleTime - 1UL ) )` computes the number complete RTOS ticks to wait, in units of SysTick. Then `portNVIC_SYSTICK_CURRENT_VALUE_REG` is added to compensate for the currently-in-progress RTOS tick. However, the flaw that I’m seeing is in the way that the SysTick timer works: According to ARM’s Cortex-M4 Generic User Manual (DUI0553) the SysTick timer value starts at 0, reloads to the current `LOAD` value on the next cycle, and downcounts each cycle, triggering an exception on the cycle that transitions `VAL` from 1 to 0.

Take the simple example below, with the system tick frequency at 2Hz and the RTOS frequency at 1Hz. The `LOAD` value for the SysTick is set to the desired frequency - 1 (i.e. `LOAD = 1`).

 ![image](https://d2v6vdsk2p900z.cloudfront.net/original/2X/0/0d2befe3ec06a257990cf5560f2efe058de2b48f.png)

On SysTick cycle 0, `VAL` is set to 0. On cycle 1, `VAL` is reloaded to 1. On cycle 2, `VAL` transitions from 1 to 0, triggering an interrupt, incrementing the RTOS tick by 1. This then repeats. Assume the RTOS decides to sleep at the time marked “now” (current RTOS tick = 1), and `xExpectedIdleTime` is 2 ticks (wake up on or before RTOS tick 3).

The reload value computation computes the number of complete RTOS ticks to wait as `( 2 * ( 2 - 1) == 2` correctly. However, consider the tick-in-progress portion of the computation: `portNVIC_SYSTICK_CURRENT_VALUE_REG` will return 0, leading `ulReloadValue` to be 2. `VAL` is set to 0 and `LOAD` is set to 2. On SysTick cycle 3, `VAL` is set to 2. `VAL` will transition from 1 to 0 on SysTick cycle 5, earlier than the expected SysTick cycle 6. If you were to instead mark the “now” point to be just after SysTick cycle 3, and perform the same computation, you wake up 1 SysTick tick too late.

In summation, the computation is incorrect as a result of SysTick starting from 0 on the first cycle, and interrupting on transition from 1 to 0 as opposed to starting from `LOAD`, and interrupting from 0 to `LOAD`. If the latter case were true, the computation would be correct.

Sorry for the long post. Am I missing something? Or is the computation just wrong?

Best,  
Jeff

---

<div class="post-metadata">

**Author:** ![rtel](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/rtel/32/31_2.png) [@rtel](https://forums.freertos.org/u/rtel)\
**Post date:** [September 22, 2021, 11:09pm UTC](https://forums.freertos.org/t/vportsuppressticksandsleep-systick-implementation-wrong/13521/2 "2021-09-22T23:09:30Z")

</div>

I really appreciate the depth of your report. It will take some time to dig into. From what you have written it seems the mistake is not taking into account the “on the next cycle”, implying there is one additional clock cycle as the code assumes the reload occurs within the same cycle.

If this is correct then it seems the difference will be minimal, although it should be corrected. By minimal I mean one cycle of a fast clock - normally in the tens of MHz. Is that correct, or is the difference greater than this?

---

<div class="post-metadata">

**Author:** ![jefflongo](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/jefflongo/32/1917_2.png) [@jefflongo](https://forums.freertos.org/u/jefflongo)\
**Post date:** [September 22, 2021, 11:44pm UTC](https://forums.freertos.org/t/vportsuppressticksandsleep-systick-implementation-wrong/13521/3 "2021-09-22T23:44:10Z")

</div>

Hi Richard,

Thanks for the response. You are correct: the question is whether `VAL` is reloaded right away or on the next cycle. I’m leaning towards it reloading on the next cycle for this reason - assume you want to generate a SysTick exception every 5 cycles (and thus set `LOAD` to 4). If `VAL` were reloaded instantly, and not on the next cycle, the first period would be short by 1 cycle, (due to the exception being generated on transition from 1 to 0). The Keil M4 SysTick man page (sorry, it won’t let me post links yet) also mentions `VAL` being wrapped on the _next_ cycle, though this says nothing about the behavior when setting `LOAD` and enabling the timer.

As for the difference in behavior, it’s true that the side-effects are small in the average case - you wake up one cycle late. However, if you happen to enter sleep while `VAL` is 0 (probably a rare case), you wake up `LOAD` cycles early, which is a bit worse.

---

<div class="post-metadata">

**Author:** ![jefftenney](https://d3iykfbgfh8zhg.cloudfront.net/user_avatar/forums.freertos.org/jefftenney/32/1314_2.png) [@jefftenney](https://forums.freertos.org/u/jefftenney)\
**Post date:** [September 23, 2021, 3:36pm UTC](https://forums.freertos.org/t/vportsuppressticksandsleep-systick-implementation-wrong/13521/4 "2021-09-23T15:36:26Z")

</div>

Hi @jefflongo,

Stopping SysTick on zero is an issue in the current implementation. As you noted, it causes an early wake up, or in other words, it causes `xTickCount` to jump ahead. In the worst case, it can cause `xTickCount` to jump ahead by the _entire_ expected idle time.

[This PR](https://github.com/FreeRTOS/FreeRTOS-Kernel/pull/59) includes the fixes.

The other issue of being off by one systick count is actually swallowed up by `ulStoppedTimerCompensation` which addresses not only that issue but the duration of time the timer is stopped. For what it’s worth my own testing indicated the timer loads from the load register on the _next_ cycle after the timer is enabled, just as you suspected.

Jeff T
