The osDelay() function is used in embedded systems programming on ARM Cortex chips to insert a time delay or pause in program execution. It is part of CMSIS and can be called as osDelay(ms) where ms is the delay period in milliseconds. While osDelay() is simple to use, some common errors can occur that lead to incorrect delays or even system crashes.
Potential Causes of osDelay() Errors
Here are some typical reasons why osDelay() may not work as expected:
- Invalid system timer configuration – The system timer or SysTick timer provides the time base for osDelay(). If the timer is not set up properly or disabled, osDelay() will be unpredictable.
- Interrupts disabled – With interrupts disabled, the SysTick interrupt cannot fire to decrement the delay counter. This leads to much longer delays than intended.
- High interrupt load – If the processor is overwhelmed with interrupt requests, the SysTick interrupt may not fire consistently, affecting osDelay().
- Improper RTOS configuration – If the RTOS kernel has issues like priority inversion or resource starvation, it can affect thread scheduling and timing.
- Call context issues – osDelay() cannot be called from an ISR or with interrupts already disabled. Doing so can lock up the system.
- Timer rollover – If the delay period is too long, the SysTick counter can roll over causing incorrect delays.
- Multiple timing sources – If a different timer is used by some ISRs, it can clash with SysTick and impact osDelay().
Debugging Delays that are Too Long
When osDelay() stretches out for much longer than the supplied delay parameter, it suggests the SysTick interrupts are not occurring properly. Here are some debugging tips for long delays:
- Check SysTick configuration – Make sure the clock source, interrupt priority and other settings match your system and RTOS needs.
- Verify interrupts enabled – Set a breakpoint at the start of osDelay() to check if interrupts are already disabled before it is called.
- Inspect interrupt handler – Step through the SysTick handler code to ensure it is behaving correctly and decrementing the counter.
- Measure execution times – Use profiling or an oscilloscope to find ISRs or code segments that are taking too long to execute and fix accordingly.
- Change thread priorities – Boost the priority of threads and ISRs using osDelay() so they are not blocked for too long.
- Rule out RTOS issues – Review RTOS configuration, check for resource contention, priority inversion, stack overflows etc.
Debugging Delays that are Too Short
When the actual delays turn out to be much shorter than the osDelay() parameter value, look for these issues:
- Confirm units – Make sure the delay is specified in milliseconds. A common mistake is using microseconds instead.
- Check timer speed – For short delays, a 1 MHz SysTick timer will be inadequate. Faster timer speeds are needed.
- Aware of timer resolution – There is only 1 tick per millisecond, so delays below 10 ms may measure as 0 ms.
- Rule out rollover – Use profiling to ensure the delay counter does not overflow for long delay periods.
- Inspect compiler optimizations – Aggressive optimizations may eliminate or alter the delay loop code.
- Verify RTOS scheduler – Short delays may simply be skipped if the RTOS reschedules a thread immediately.
Techniques to Measure and Verify osDelay()
To gain insight into what osDelay() is actually doing, various timing measurement approaches can be used:
- Oscilloscope – Connect an oscilloscope to a GPIO pin toggled at the start and end of the delay loop.
- Logic analyzer – Monitor SysTick interrupts and thread state transitions.
- Debug timestamps – Instrument the code using DWT cycle counter registers to precisely measure delays.
- Printf profiling – Time delays by printing timestamps from inside the delay loop.
- RTOS hooks – Use RTOS hooks like osEventObserver to record thread events and timing.
- Stack profiling – Correlate stack usage with execution time to identify problem areas.
The specific approach depends on hardware capabilities, RTOS features, and tool availability. But the aim is to gain visibility into the actual delay achieved versus the intended delay.
Software Fixes for osDelay() Issues
If osDelay() errors persist even after hardware debugging, several software techniques can help:
- Refactor ISRs – Keep ISR execution times short and consistent by moving non-critical code out to threads.
- Avoid nesting delays – Calling osDelay() from within another osDelay() loop can lead to problems.
- Use timers instead of delays – For very precise or recurring delays, use hardware timers instead.
- Implement a software watchdog – To catch any freeze-ups due to osDelay() failures.
- Increase thread priorities – So that osDelay() threads get scheduled immediately.
- Reduce RTOS event notifications – Which can preempt delay loop execution and cause variations.
With shorter and better structured ISRs, optimal RTOS configuration, and reduced OS overhead, osDelay() behavior becomes much more predictable.
Tools for Analyzing osDelay() Issues
Besides an oscilloscope and logic analyzer, software tools are indispensable for debugging osDelay() problems:
- Perf counters – Built-in ARM DWT performance counters to profile code execution.
- SEGGER SystemView – Provides RTOS visualization and event tracing.
- SEGGER Ozone – Debugging and profiling tool with call stack analysis.
- Keil μVision – Popular IDE with emulator, RTOS view, and profiling.
- IAR Workbench – IDE and debugger with stack visualization and analysis.
- Valgrind – Dynamic analysis tools including callgrind profiler.
- GDB – ARM toolchain debugger with QEMU virtual platform support.
By leveraging such tools, developers can gain unparalleled insight into their RTOS thread activity, interrupt behavior, and timing issues that impact osDelay() and other kernel blocking functions.
Conclusion
osDelay() is meant to offer simple millisecond delays in embedded projects based on ARM Cortex MCUs. However, its dependency on the SysTick timer and RTOS scheduler means that many factors can derail it leading to incorrect timing. By learning the typical pitfalls, applying debugging techniques focused on visibility into the OS, and using performance analysis tools, developers can identify and resolve osDelay() errors.