FreeRTOS is a popular real-time operating system (RTOS) used in many embedded systems. One key feature of FreeRTOS is its ability to quickly switch between different tasks using a context switch. The context switch time is an important metric that impacts real-time performance.
In short, the context switch time refers to the time it takes for the CPU to save the context of one task and load the context of another task. This allows the CPU to resume executing a different task. A faster context switch time allows an RTOS like FreeRTOS to rapidly interleave execution between multiple tasks, meeting real-time requirements.
What Happens During a Context Switch?
When a context switch occurs in FreeRTOS, the following steps generally happen:
- The context (register values, stack pointer, etc.) of the current running task is saved by the CPU so it can be resumed later.
- The scheduler selects the next highest priority task that is ready to run.
- The context of the selected task is restored onto the CPU registers.
- The scheduler triggers a switch to the restored task, and it resumes execution.
The register values that form the task context are architecture specific. For example, on ARM Cortex-M CPUs, the context may include CPU registers like the program counter, stack pointer, link register, and general purpose registers R0-R12.
The steps to save and restore this context during each switch allow the tasks to be interleaved while keeping their data secure and separate from each other.
What Factors Affect Context Switch Time?
There are several factors that affect the context switch time in FreeRTOS:
- Number of registers to save/restore – More CPU registers mean more data to copy during a switch.
- Stack usage – Deeper stack usage takes longer to save and restore.
- Interrupt handling – Impact of disabling/restoring interrupts around the switch.
- Optimized context switching code – Efficient assembly code can accelerate the required steps.
- CPU speed and cycles – Faster CPU cores can execute the steps more quickly.
- FPU registers – Saving floating point state adds overhead if used.
- Peripheral states – Some RTOSes may save/restore additional peripheral states.
The tradeoffs around these factors influence how a RTOS like FreeRTOS is configured and optimized on a given microcontroller architecture.
Measuring Context Switch Time
The context switch time can be measured by profiling the RTOS execution with a debugger or analyzer tool. A common technique is:
- Trigger on the start of a context switch.
- Enable cycle counting.
- Trigger again on the end of the context switch.
- Read the cycle counter difference.
This measures the processor cycles consumed between the start and end of the switch. This cycle count can be converted into time based on the known CPU clock speed.
Measuring just the switching core time avoids inaccuracies from interrupt latency or other overhead outside the RTOS itself. Some profilers and debug tools like SEGGER SystemView can automate this switching measurement.
Optimizing Context Switch Time
A faster context switch time is a key optimization goal for real-time operating systems. Here are some ways FreeRTOS can be optimized to reduce switching time on ARM Cortex-M CPUs:
- Minimize the stack usage of each task to save/restore less data.
- Disable interrupts around switching to avoid latency.
- Use context switch macros coded in efficient ARM assembly.
- Configure a Cortex-M0+ CPU to use its local registers for fast context saving.
- Adjust compiler settings to optimize for speed during switching.
- Reduce overall number of switches needed through proper design.
- Choose a fast Cortex-M4/M7 CPU if the application requires floating point.
Optimized FreeRTOS ports like those from ARM, STMicro, NXP, or silicon vendors often apply some of these techniques to achieve very fast context switch times of under 5-15 microseconds on Cortex-M CPUs.
Context Switch Time Examples
To illustrate typical context switch times, here are some specific examples from popular ARM MCUs running FreeRTOS:
- NXP LPC1769 Cortex-M3 – 12 us typical context switch time
- STM32F407 Cortex-M4 – 7 us typical context switch time
- Microchip SAMV71 Cortex-M7 – 6 us typical context switch time
- NXP iMX RT1050 Cortex-M7 – 5 us typical context switch time
Higher end Cortex-M7 MCUs can achieve very fast switch times of 5 microseconds or less. Slower Cortex-M0/M0+ chips may range from 15-25 microseconds depending on configuration.
These short durations allow FreeRTOS to rapidly multitask numerous tasks on ARM chips to meet hard real-time requirements.
When Does Context Switching Occur?
Context switching occurs at the following times in FreeRTOS:
- When a running task calls an API to voluntarily yield execution.
- When a task is preempted by a newly ready higher priority task.
- When a task blocks on synchronization like a queue or semaphore.
- When a higher priority task becomes ready during an interrupt.
- When a task’s allocated time slice expires (if time slicing is enabled).
The scheduler will determine if a context switch is needed at these points by checking if a higher priority task is actually ready to run next.
Context Switch Time vs Interrupt Latency
Interrupt latency and context switch time are sometimes confused, but they refer to different things:
- Interrupt Latency – The time from the hardware interrupt signal to start of the ISR code.
- Context Switch Time – The time to save one task context and load another task’s context.
Interrupt latency includes overheads like pipeline flushing, stacking, decoding, etc. This occurs before the RTOS context switching to the ISR task.
A long interrupt latency can increase the overall context switch time. But optimizing the interrupt handling code itself has the most impact on pure interrupt latency.
The context switch time is a key metric that reflects an RTOS’s ability to rapidly multitask between threads and processes. For FreeRTOS on ARM Cortex-M CPUs, typical context switch times can range from 5-25 microseconds depending on the microcontroller performance and configuration.
Faster context switching allows more responsive real-time performance. The register saving/restoring and other steps during the switch can be optimized to minimize the overall context switch duration. Understanding and measuring context switch time helps tune FreeRTOS applications for the best real-time behavior on ARM-based systems.