- Added ...GetStaticBuffers functions that were upstreamed but not included in v10.5.1
## Kernel SMP Changes
List of changes to the Vanilla FreeRTOS V10.5.1 kernel in order to support dual-core SMP
### Scheduling Behavior Changes
- The kernel now executes two tasks concurrently
- The kernel now creates two IDLE tasks (pinned to each core)
- Tasks can be pinned to either core, or have no affinity (can run on both cores)
- Each core receives a tick interrupt, but only core 0 increments the tick count and unblocks timed out tasks
- Core 0 calls `xTaskIncrementTick()`
- Core 1 calls `xTaskIncrementTickOtherCores()`
- Each core independently calls `vTaskSwitchContext()` to pick the highest priority task it can currently run
- In single-core scheduling algorithm `taskSELECT_HIGHEST_PRIORITY_TASK()` unchanged
- In SMP, `prvSelectHighestPriorityTaskSMP()` is called. This will select the highest priority ready state task that...
- Has a compatible core affinity
- Is not being run by another core
- Each core can suspend scheduling independently (i.e., `vTaskSuspendAll()`)
### Configuration
Following configurations have been added
- Added `configNUMBER_OF_CORES` to specify the number of cores to build. Can be `1` for vanilla, or `2` for SMP, error otherwise
- Disable `configUSE_PORT_OPTIMISED_TASK_SELECTION` for SMP
### Data Structure Changes (`tasks.c`)
The following data fields have been expanded to have `configNUMBER_OF_CORES` copies:
-`pxCurrentTCBs`: Each core now has its own currently running task
-`xPendingReadyList`: Each core has its own list to pend ready tasks if the scheduler is suspended on the core
-`xYieldPending`: Each core has its own flag to track whether it has a pending yield
-`xIdleTaskHandle`: Each core now has its own idle task
-`uxSchedulerSuspended`: Each core can independently suspend scheduling on its core
-`ulTaskSwitchedInTime`: Each core tracks its own "task switched in" time
Their access is now indexed by a `xCoreID` if in SMP, or set to `0` in single core.
The following data structures have been added:
-`TCB_t.xCoreID`: All tasks now store their core affinity in a TCB member. Always set to 0 in single-core
### API Additions
The following APIs have been added to support SMP
-`xTaskCreatePinnedToCore()` and `xTaskCreateStaticPinnedToCore()` to create tasks with a core affinity
- In single-core, core affinity is ignored. Same behavior as `xTaskCreate()`
-`xTaskGetCoreID()` to get a task's affinity
- Add `ForCore()` versions of the following API
-`xTaskGetIdleTaskHandleForCore()`
-`xTaskGetCurrentTaskHandleForCore()`
-`ulTaskGetIdleRunTimeCounterForCore()`
### API Modifications
Added the following macros that abstract away single-core and SMP differences:
-`taskYIELD_CORE()` triggers a particular core to yield
-`taskIS_YIELD_REQUIRED()`/`taskIS_YIELD_REQUIRED_USING_PRIORITY()` check if current core requires a yield after a task is unblocked
-`taskIS_AFFINITY_COMPATIBLE()` check if a task has compatible affinity
-`taskIS_CURRENTLY_RUNNING()`/`taskIS_CURRENTLY_RUNNING_ON_CORE()` checks if a task is running on either core
-`taskCAN_BE_SCHEDULED()` checks if an unblocked task can be scheduled on any core
-`taskIS_SCHEDULER_SUSPENDED()` checks if the scheduler on the current core is suspended
-`taskSELECT_HIGHEST_PRIORITY_TASK()` selects the highest priority task to execute for the current core
-`prvGetTCBFromHandle()` updated in SMP to call `xTaskGetCurrentTaskHandle()` when the handle is `NULL`. Done so for thread safety (in case the current task switches cores at the same time).
The following functions were modified to accommodate SMP behavior:
-`prvInitialiseNewTask()`
- Added `xCoreID` argument to pin task on creation
- For single-core, `xCoreID` is hard coded to `0`
-`prvAddNewTaskToReadyList()`
- Checks if new task can be scheduled on core 1
-`vTaskDelete()`
- Checks if the deleted task is currently running on the other core.
- If so, sends a yield to the other core.
-`vTaskPrioritySet()`
- Checks if the task is currently running on the both cores, and yields the appropriate core if so
-`vTaskSuspend()`
- Checks if the task is currently running on the other core, and yields the other core if so.
-`prvTaskIsTaskSuspended()`
- Checks the `xPendingReadyList` of both cores to see if a task is suspended
-`xTaskResumeAll()`
- Limit catching up of tick counts to core 0 (given only core 0 calls `xTaskIncrementTick()`)
-`xTaskIncrementTick()`
- Limited to core 0
-`vTaskSwitchContext()`
- Switches context for current core
-`xTaskRemoveFromEventList()`
- Created SMP copy of the function
- Checks if `pxEventList` has already been emptied by the other core before removing
- Checks if task can be scheduled on both cores, adds it to the appropriate core's pending list if it can't be scheduled.
-`vTaskRemoveFromUnorderedEventList()`
- In SMP, check if the task can be scheduled before adding it to the appropriate list. Whereas in single-core, the scheduler is always suspended thus the unblocked task always goes onto the pending ready list.
-`eTaskConfirmSleepModeStatus()`
- Updated logic to determine whether sleep is possible in SMP by checking the status of both cores.
-`prvCheckTasksWaitingTermination()`
- Updated logic so that we don't delete tasks on `xTasksWaitingTermination` which are still currently running on the other core.
- In SMP, the function will now disables interrupts to ensure that the calling task does not switch cores while fetching the current core's TCB.
-`xTaskGetSchedulerState()`
- In SMP, the function now disables interrupts to ensure that the calling task does not switch cores while checking its own copy of `uxSchedulerSuspended`.
List of changes made to Vanilla FreeRTOS V10.5.1 header files to allow for building in ESP-IDF documentation build system.
- Removed leading header name line (e.g., `xxx.h`) in doxygen comment blocks. For example:
```c
/**
* xxx.h
*
* Documentation from some func
*/
void some_func(void);
```
- Removed leading `@code{c}` blocks in containing redundant function prototypes. For example:
```c
/**
*@code{c}
* void some_func(int var_a, int var_b);
*@endcode
*
* Documentation from some func
*/
void some_func(int var_a, int var_b);
```
- Added `/** @cond !DOC_EXCLUDE_HEADER_SECTION */` and `/** @endcond */` labels to exclude various doxygen sections from being included into documentation builds. These excluded sections include:
- In doxygen blocks that describe multiple related set of functions/macros, only the function/macro that matches the doxygen blocks parameters is included. For example:
```c
/**
* Description that covers both some_func() and some_func_extra()
- In functions/macros that are not meant to be directly called by users (i.e., internal), such as the various `Generic` variants of functions
- Some types/functions/macros are manually documented, thus are documented with regular comment blocks (i.e., `/* */`) instead of doxygen comment blocks (i.e., `/** */`). Some of these blocks are changed into doxygen blocks.
- Backported configTIMER_SERVICE_TASK_CORE_AFFINITY config option to enable configurability of the Timer Service task's core affinity.
- The change also entails updating the task creation APIs to use IDF-FreeRTOS task creation APIs, adding a assert check for valid affinity values and dropping the use of configUSE_CORE_AFFINITY.