FreeRTOS : How to measure context switching time?

4.8k views Asked by At

I want to measure the overhead of context switching time.

Here is my idea to do that:

There are two task:

  1. taskA
  2. idle

I create a task as below:

void calculate_ct(void *pvParameters)
{
    int i = 0; 
    for(; i < 100; i++)
    {
        vTaskDelay(100 / portTICK_RATE_MS); // delay 100 ms
    }    
    // get_time();
    vTaskDelete(NULL);
}

When task call vTaskDelay() , it will turn into block state. It means that happen a context switch to idle task.

Can I use get_time() at the end and minus the delay time(10 * 100ms) to get the total overhead of context switching time and make the overhead divide by 10 to get the average of the overhead of context switching time?

get time() as below:

unsigned int get_reload()
{
    return *(uint32_t *) 0xE000E014;
}

unsigned int get_current()
{
    return *(uint32_t *) 0xE000E018;
}

unsigned int get_time()
{
    static unsigned int const *reload = (void *) 0xE000E014;
    static unsigned int const *current = (void *) 0xE000E018;
    static const unsigned int scale = 1000000 / configTICK_RATE_HZ;
                                    /* microsecond */
    return xTaskGetTickCount() * scale + (*reload - *current) * (1.0) / (*reload / scale);
}
2

There are 2 answers

1
Martin James On

I would probably go with two threads that continually swap a unit around two semaphores until some count is reached. With a high enough count you could time it with a stopwatch and then divide by the count to get an interval that is almost all context-switching time.

2
Richard On

First, information that is not specific to FreeRTOS:

Most attempts to measure the context switch time measure the time to execute a function, that happens to have a context switch in it. Therefore the time you measure will depend on the function you choose, and is not related to the context switch time. That is true when measuring a time for one RTOS, it is more complex when trying to compare RTOSes as the functions chosen will include very different functionality across the different RTOSes - making the comparison largely useless, although people don't realise this, and take it an an 'absolute'. After all, the way to get the fastest switch time is to remove all the functionality, or to break the scheduling policy so less logic needs to execute.

If you want to measure the context switch time, then just measure that, and don't try to measure function execution time as the context switch will be a small fraction of the time you actually measure.

Then FreeRTOS specific details:

Information on the number of cycles taken in a context switch is shown here: http://www.freertos.org/FAQMem.html#ContextSwitchTime . You need to configure the system as follows:

Set configUSE_PORT_OPTIMISED_TASK_SELECTION to 1 - that will use one or more asm instructions to select the next task to run, rather than use a generic C implementation.

Set configCHECK_FOR_STACK_OVERFLOW to 0 - that will remove stack overflow checking, which is about the longest thing that executes in a context switch.

Ensure compiler optimisation is set to optimise for speed.

Ensure there are not trace macros defined. Trace macros add code into the kernel.

Ensure configGENERATE_RUN_TIME_STATS is set to 0 - that will remove code that gathers statistics.

FreeRTOS includes trace macros that allow you to insert code into the context switch. You can use those macros to set outputs that can then be measured on a scope. That will allow you to measure the context switch, rather than interrupt entry time, but you will also measure the time taken to set or clear an output - which will vary form architecture to architecture.

Do you want to measure the context switch time, or the time to execute a function that has a context switch in it?