This document outlines some useful notes about
The following terms will be used in this document to avoid confusion between the different FreeRTOS versions currently in ESP-IDF
This directory contains a copy of SMP FreeRTOS based off of upstream commit 2eff03708
components/freertos/FreeRTOS-Kernelcomponents/freertos/FreeRTOS-Kernel-SMP
port.c and portmacro.h were mostly re-written from scratchtasks.c in order to be compatible with IDF.#ifdef ESP_PLATFORMCONFIG_FREERTOS_SMP is set in menuconfig#ifdef CONFIG_FREERTOS_SMP. Thus SMP FreeRTOS changes should have no effect on mainline ESP-IDF if CONFIG_FREERTOS_SMP is disabled.This section covers
IDF FreeRTOS:
SMP FreeRTOS:
Changes Made:
xTaskCreate...AffinitySet() to allow creation of tasks with affinity (instead of requiring a separate call to set the affinity).xTaskCreate...PinnedToCore() functions to call xTaskCreate...AffinitySet()IDF FreeRTOS:
vTaskSuspendAll() on one core has no effect on the other)vTaskSuspendAll() will only disable task switching on that core.SMP FreeRTOS:
vTaskSuspendAll() is global (no cores can switch tasks once the scheduler is disabled)Changes Made:
vTaskSuspendAll()/xTaskResumeAll() in ESP-IDF with vTaskPreemptionDisable()/vTaskPreemptionEnable() when using SMP FreeRTOSIDF FreeRTOS:
portENTER_CRITICAL()/portEXIT_CRITICAL() modified to accept a spinlock argumentportTRY_ENTER_CRITICAL() to allow for timeout to be specified when entering critical sectionsSMP FreeRTOS:
portENTER_CRITICAL()/portEXIT_CRITICAL() does not accept arguments. Maps directly to vTaskEnterCritical()/vTaskExitCritical()Changes Made:
portENTER_CRITICAL(...)/portEXIT_CRITICAL(...) now accepts VA_ARGS
vTaskEnterCritical()Todo:
IDF FreeRTOS:
prvIdleTask()prvIdleTask() calls a custom esp_vApplicationIdleHook(), mostly used to feed the task watchdogSMP FreeRTOS:
prvIdleTask() and prvMinimalIdleTask()
prvMinimalIdleTask() simply calls the vApplicationMinimalIdleHook()prvIdleTask() calls prvCheckTasksWaitingTermination(), vApplicationIdleHook(), vApplicationMinimalIdleHook(), and handles tickless idle.prvIdleTask() task is created and N-1 prvMinimalIdleTask() tasks are created.Changes Made:
esp_vApplicationIdleHook() is now called from vApplicationMinimalIdleHook() since every idle task calls the vApplicationMinimalIdleHook().prvIdleTask() is solely responsible for calling prvCheckTasksWaitingTermination() but can run on any core, multiple IDF cleanup routines are now routed through portCLEAN_UP_TCB()
portCLEAN_UP_TCB() -> vPortCleanUpCoprocArea() and can clean FPU save areas across cores.portCLEAN_UP_TCB() -> vPortTLSPointersDelCb()Todo:
configIDLE_SHOULD_YIELDIDF FreeRTOS:
xTaskIncrementTick() independently. xTaskIncrementTick() has been modified as such:
vApplicationTickHook()esp_vApplicationTickHook() used to feed the interrupt watchdog.SMP FreeRTOS:
xTaskIncrementTick() only be called from one core (core 0 in our case). That core's tick interrupt is solely responsible for the following via its call to xTaskIncrementTick():
prvYieldCore() on each core that needs to yield)vApplicationTickHook()Changes Made:
xPortSysTickHandler()) and will:
esp_vApplicationTickHook() in order to feed the interrupt WDT on behalf of the current core.xTaskIncrementTick() only on core 0.Todo:
IDF FreeRTOS added multiple features/APIs that are specific to IDF. For SMP FreeRTOS, these features/APIs have either been:
freertos_tasks_c_additions.h/idf_additions.h respectively. Users should #include "freertos/idf_additions.h manually so that we can keep the SMP FreeRTOS API clean.xTaskCreatePinnedToCore()/xTaskCreateStaticPinnedToCore()xTaskCreate...AffinitySet() API has been added in order to apply a core affinity on task creation.xTaskCreate...PinnedToCore() now just wrap the xTaskCreate...AffinitySet() equivalent functions and handle the conversion of a core ID into a core affinity mask.xTaskCreate...PinnedToCore() is now provided via idf_additions.hvTaskSetThreadLocalStoragePointerAndDelCallback()configNUM_THREAD_LOCAL_STORAGE_POINTERS will be doubled (in order to store the callback pointers in the same array as the TLSPs themselves)vTaskSetThreadLocalStoragePointerAndDelCallback() moved to freertos_tasks_c_additions.h/idf_additions.hportCLEAN_UP_TCB()xTaskGetCurrentTaskHandleForCPU()freertos_tasks_c_additions.h/idf_additions.h for nowTodo: Check if this can be upstreamed
xTaskGetIdleTaskHandleForCPU()freertos_tasks_c_additions.h/idf_additions.hTodo: This needs to be deprecated as there is no longer the concept of idle tasks pinned to a particular CPU
xTaskGetAffinity()freertos_tasks_c_additions.h/idf_additions.h and simple wraps vTaskCoreAffinityGet()tskNO_AFFINITY even if the task is not completely unpinned.Todo: This needs to be deprecated and users should call vTaskCoreAffinityGet() instead