SEGGER - Jobs
emWin upgrade     Trade-In program     Web shop

embOS Fast context switching

embOS is designed to perform fast context switches. This section describes two different methods to calculate the execution time of a context switch from a task with lower priority to a task with a higher priority.

The first method uses port pins and requires an oscilloscope. The second method uses the high-resolution measurement functions. Example programs for both methods are supplied in the Application directory of your embOS shipment.

SEGGER uses these programs to benchmark the embOS performance. You can use these examples to evaluate the benchmark results. Please note that the actual performance depends on many factors (CPU, clock speed, toolchain, memory model, optimization, configuration, etc.).

Measurement with port pins and oscilloscope

The context switching time is the time between switching the LED on and off. If the LED is switched on with an active high signal, the context switching time is the time between rising and falling edge of the signal. If the LED is switched on with an active low signal, the signal polarity is reversed. The RZ/A1 example below use active low LEDs.

The real context switching time is shorter, because the signal also contains the overhead of switching the LED on and off. The time of this overhead is also displayed on the oscilloscope as a small peak right before the task switching time display and has to be subtracted from the displayed context switching time. The picture below shows a simplified oscilloscope signal with an active-low LED signal (low means LED is illuminated). There are switching points to determine:

  • A = LED is switched on for overhead measurement
  • B = LED is switched off for overhead measurement
  • C = LED is switched on right before context switch in low-prio task
  • D = LED is switched off right after context switch in high-prio task

The time needed to switch the LED on and off in subroutines is marked as time tAB. The time needed for a complete context switch including the time needed to switch the LED on and off in subroutines is marked as time tCD.
The context switching time tCS is calculated as follows: tCS = tCD - tAB

 

Example measurements with Renesas RZ/A1

Task switching time has been measured with the parameters listed below:

embOS Version V4.14
Application program OS_MeasureCST_Scope.c
Hardware Renesas RSKRZ/A1
Program is executing in RAM
CPU Mode Thumb2
Compiler used SEGGER Embedded Studio V2.10B
CPU frequency (fCPU) 399.0 MHz
CPU clock cycle (tCycle): tCycle = 1 / fCPU = 1 / 399.0 MHz = 2.506 nsec


Measuring tAB and tCD

 

Resulting context switching time and number of cycles
The time which is required for the pure context switch is:
tContextSwitch = tCD - tAB = 479 Cycles - 192 Cycles => 287 Cycles (0.72 usec @399 MHz).
  

Download the embOS context switching time sample for SEGGER Embedded Studio to test, compare and verify our context switching time measurements.

 



Measurement with port pins and oscilloscope

The example file OS_MeasureCST_Scope.c uses the BSP.c module to set and clear a port pin. This allows measuring the context switch time with an oscilloscope. The following source code is excerpt from OS_MeasureCST_Scope.c:

#include "RTOS.h"
#include "BSP.h"

static OS_STACKPTR int StackHP[128], StackLP[128]; // Task stacks
static OS_TASK TCBHP, TCBLP;                       // Task-control-blocks

/*********************************************************************
*
*       HPTask()
*/
static void HPTask(void) {
  while (1) {
    OS_Suspend(NULL); // Suspend high priority task
    BSP_ClrLED0(0);   // Stop measurement
  }
}

/*********************************************************************
*
*       LPTask()
*/
static void LPTask(void) {
  while (1) {
    OS_Delay(100); // Synchronize to tick to avoid jitter
    //
    // Display measurement overhead
    //
    BSP_SetLED0(0);
    BSP_ClrLED0(0);
    //
    // Perform measurement
    //
    BSP_SetLED0(0);    // Start measurement
    OS_Resume(&TCBHP); // Resume high priority task to force task switch
  }
}

/*********************************************************************
*
*       main()
*/
int main(void) {
  OS_IncDI();    // Initially disable interrupts
  OS_InitKern(); // Initialize OS
  OS_InitHW();   // Initialize Hardware for OS
  BSP_Init();    // Initialize LED ports
  OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
  OS_CREATETASK(&TCBLP, "LP Task", LPTask, 99, StackLP);
  OS_Start();    // Start multitasking
  return 0;
}

 

Measurement with high-resolution timer

The context switch time may be measured with the high-resolution timer.
The example OS_MeasureCST_HRTimer_embOSView.c uses a high-resolution timer to measure the context switch time from a low priority task to a high priority task and displays the results on embOSView.

#include "RTOS.h"
#include "stdio.h"

static OS_STACKPTR int StackHP[128], StackLP[128]; // Task stacks
static OS_TASK TCBHP, TCBLP;                       // Task-control-blocks
static OS_U32 _Time;                               // Timer values

/*********************************************************************
*
*       HPTask()
*/
static void HPTask(void) {
  while (1) {
    OS_Suspend(NULL);      // Suspend high priority task
    OS_Timing_End(&_Time); // Stop measurement
  }
}

/*********************************************************************
*
*       LPTask()
*/
static void LPTask(void) {
  char   acBuffer[100];   // Output buffer
  OS_U32 MeasureOverhead; // Time for Measure Overhead
  OS_U32 v;

  //
  // Measure Overhead for time measurement so we can take this into account by subtracting it
  //
  OS_Timing_Start(&MeasureOverhead);
  OS_Timing_End(&MeasureOverhead);
  //
  // Perform measurements in endless loop
  //
  while (1) {
    OS_Delay(100);           // Sync. to tick to avoid jitter
    OS_Timing_Start(&_Time); // Start measurement
    OS_Resume(&TCBHP);       // Resume high priority task to force task switch
    v =  OS_Timing_GetCycles(&_Time);
    v -= OS_Timing_GetCycles(&MeasureOverhead);  // Calculate real context switching time
    v =  OS_ConvertCycles2us(1000 * v);          // Convert cycles to nano-seconds, increase time resolution
    sprintf(acBuffer, "Context switch time: %u.%.3u usecr", v / 1000uL, v % 1000uL); // Create result text
    OS_SendString(acBuffer);                     // Print out result
  }
}

/*********************************************************************
*
*       main()
*/
int main(void) {
  OS_IncDI();    // Initially disable interrupts
  OS_InitKern(); // Initialize OS
  OS_InitHW();   // Initialize Hardware for OS
  OS_CREATETASK(&TCBHP, "HP Task", HPTask, 100, StackHP);
  OS_CREATETASK(&TCBLP, "LP Task", LPTask, 99, StackLP);
  OS_Start();    // Start multitasking
  return 0;
}

The example program calculates and subtracts the measurement overhead itself, so there is no need to do this. The results will be transmitted to embOSView, so the example runs on every target that supports UART communication to embOSView. The example program OS_MeasureCST_HRTimer_Printf.c is equal to the example program OS_MeasureCST_HRTimer_embOSView.c but displays the results with the printf() function for those debuggers which support terminal output emulation.