ARM: RTOS delay accuracy
Information in this knowledgebase article applies to:
In our RTOS based application we use delay functions provided by the RTOS. However, when we verify the actually passed time until the delayed thread continues, we noticed, that time is always shorter than the specified timeout. This is particularly critical, when the minimal possible timeout 1 was specified in the delay function call. Examples are:
osDelay(/* in ms */ 1) ; /* in CMSIS RTOS */ os_dly_wait(/* in ticks */ 1) ; /* in KEIL RL-ARM RTX */
Then we see, sometimes the actual timeout is almost 0, which is shorter than the actually required timeout. What is the reason for this?
The RTOS has a minimal time resolution of the tick interval time, which is specified in the RTOS configuration. It can only execute delays, which count in n multiple of this time. On each completed tick interval the delay count gets decremented by 1 and if it reaches 0, the timeout is expired and the delayed thread resumes.
The call to the delay function happens now somewhere in the middle of this tick interval. So the first waited interval is not a complete tick interval time, but only the rest of the current tick interval time. This can also be almost no time until the next tick happens, which also explains the observed behaviour.
To wait at least the minimal specifiable delay time, add the time equivalent of 1 tick interval to the requested timeout. It can look like this:
osDelay((1 + (OS_TICK /* from RTX config */ + 1000 - 1) / 1000) ; /* in CMSIS RTOS */ os_dly_wait(1 /* rest of current tick */ + 1) ; /* in KEIL RL-ARM RTX */
Or, if you require more accurate time, use custom wait functions.
The CMSIS-RTOS version 4.80, which was released with the
CMSIS pack 4.5.0, reverts the change made in the previous version
4.79. From now on the timeouts will be handled again as in CMSIS-RTOS
version 4.78 and before. So, the actual timeout will be shorter than
the requested timeout, as discussed in this article. See also the
CMSIS-RTOS revision history for reference.
tick = (((1000U * millisec) + os_clockrate - 1U) / os_clockrate) + 1 /*4.79 adds 1*/;
The CMSIS-RTOS version 4.79, which was released with the CMSIS pack 4.4.0, behaves uniquely, enforcing a minimum. In this version the internal ms to tick conversion adds 1 tick to the result, which makes sure the program waits at least the requested timeout without needing to adjust the timeout parameter in the application. See also the CMSIS-RTOS revision history for reference.
The following Discussion Forum threads may provide information related to this topic.
Last Reviewed: Wednesday, January 25, 2017
of your data.