Why is the SysTick timer off by a few clock cycles?
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-10 11:36 PM
Hello all,
Sometime ago I was looking into configuring the SysTick timer for an stm32f407 mcu. As the CMSIS lib provides a function for this, this is kind of straight forward. To verify the configuration I measured the clock cycle count. When I was looking whether I configured the timer correctly, I discovered something I don't understand; the count between SysTick interrupts was slightly less then expected. I configured the SysTick to hit every 1 ms with a system clock of a 168 MHz, so I would expect that the interrupt would hit every 168000 clock ticks. However, I measure 167996.
Does anyone has an idea why this is?
Best regards,
Jurrien
#systick-config #interrupts- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-11 2:12 AM
How do you measure it?
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-11 2:21 AM
Thanks for the reply waclawek.jan. First I measured it using a trace tool in my IDE (TrueSTUDIO), but during my experiment I started to suspect that the deviation measured might be in the tool. Therefore, I changed to the clock cycle count register in the debug peripheral (DWT->CYCCNT), this gave me the same result.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-11 4:27 AM
The systick handler is as follow:
extern 'C' void SysTick_Handler(void)
{
static uint32_t count = DWT->CYCCNT;
uint32_t interval = DWT->CYCCNT - count;
count = DWT->CYCCNT;
if(interval) {
// useless, but should prevent the compiler from optimizing interval away
}
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
and the SysTick_Config call looks like:
// SystemCoreClock equals 168000000
if(SysTick_Config(SystemCoreClock / 1000)) {
// Error ...
return;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?
And finally the main loop is just a while(1) {} loop. I just rechecked the values of the experiment, and now they oscillate around
167980, but they are always below the 168000. I compiled this with the lowest optimization level (-O0), it should not matter expect that some values might be optimized out. To see the values I have a breakpoint on line 6 of the first code fragment.
Please let me know if I forgot an important detail.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-11 5:34 AM
Need more details.
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-11 6:15 AM
Hi,
can you check the SysTick Reload value (SysTick->LOAD) and SystemCoreClock value? The reload value is derived from SystemCoreClock value: reload = ((SystemCoreClock / 1000) -1)
On my side, on STM32F429I-DISC1 discovery board with HCLK=168MHz (*), SystemCoreClock=168000000 and SysTick->LOAD=167999.
(*) Clock config: HSE=8MHz, PLL source=HSE, PLL_M=4 N=168 P=2.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-11 8:19 AM
Guess how many cycles elapse between these two reads to
DWT->CYCCNT...:
uint32_t inteval = DWT->CYCCNT - count;
count = DWT->CYCCNT;
:-)
JW
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-15 5:51 AM
Thanks for your response, its much appreciated :-).
Waclawek.Jan
‌ . Unfortunately my life isn't so easy. I performed the test with several different clock frequency settings and different SysTick timer intervals, all resulted in different deviations. Also, the deviation depends on whether the mcu is active or not.TISSERAND.Bruno
‌ I checked theSysTick->LOAD. For me it's the 167999 as well.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-15 8:00 AM
Jan,
I have to admit, I did not look up the actual clock count for the load- and subtract instruction, but let assume (for a worst case calculation) the instructions take 3 cycles. (I suspect that the subtract will only be on cycle and the load instruction 2, but this would only make it worst). We have 1 instruction for reading count, 1 for DWT->CYCCNT and one for subtracting. So we execute 3 instruction, times 3 cycles is smaller then 20 cycles (168000 -
167980 = 20)
. But maybe more importantly, the amount of cycles should be constant right? And it isn't.I realize now that giving the code snippet was a bad idea. I encountered the problem some weeks ago. Back then, I had a program doing nothing expect for executing the SysTick irq. I measured the cycle count using an build in tool of Atollic's TrueSTUDIO, the SWV Exception Trace Log. I was surprised by the result so I tried several different configuration by changing the clock frequency and SysTick interval. Still using the SWV Exception Trace Log I measured different deviation depending on the configuration.
At first, I thought that this issue might be related to the measurement tool, so I had a discussion with the support for TrueSTUDIO. After a while we figured that, using the DWT->CYCCNT, we could show that this problem is not in the measurement tool. And so I ended on this forum.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Email to a Friend
- Report Inappropriate Content
‎2017-08-15 8:53 AM
Jurrien,
don't forget that
DWT->CYCCNT
is ticking continuously, all the time the program is executing. Imagine it's a real clock.
In the above snippet, you first read
DWT->CYCCNT
to calculate the time difference. Say, it's 16:
The you read it again to start measuring the time between two interrupts. But it took time to calculate the time difference, so say you read in 16:
Then the next interrupt chimes in and you read
DWT->CYCCNT
to calculate the time difference. Say, it's 17:
What is the span between two interrupts in this example?
JW
