Просмотр исходного кода

Merge branch 'refactor/freertos_move_idf_specific_functions' into 'master'

refactor(freertos/idf): Move IDF FreeRTOS API additions to header files

Closes IDF-7201, IDF-3873, and IDF-7907

See merge request espressif/esp-idf!25615
Darian 2 лет назад
Родитель
Сommit
c60cbcee5c
23 измененных файлов с 834 добавлено и 968 удалено
  1. 1 5
      components/freertos/CMakeLists.txt
  2. 24 6
      components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h
  3. 0 19
      components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h
  4. 2 1
      components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c
  5. 0 11
      components/freertos/FreeRTOS-Kernel-SMP/tasks.c
  6. 9 7
      components/freertos/FreeRTOS-Kernel/event_groups.c
  7. 26 1
      components/freertos/FreeRTOS-Kernel/include/freertos/FreeRTOS.h
  8. 56 341
      components/freertos/FreeRTOS-Kernel/include/freertos/task.h
  9. 2 0
      components/freertos/FreeRTOS-Kernel/queue.c
  10. 2 0
      components/freertos/FreeRTOS-Kernel/stream_buffer.c
  11. 27 414
      components/freertos/FreeRTOS-Kernel/tasks.c
  12. 2 0
      components/freertos/FreeRTOS-Kernel/timers.c
  13. 0 2
      components/freertos/config/include/freertos/FreeRTOSConfig.h
  14. 42 0
      components/freertos/esp_additions/freertos_compatibility.c
  15. 444 83
      components/freertos/esp_additions/freertos_tasks_c_additions.h
  16. 105 0
      components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h
  17. 63 61
      components/freertos/esp_additions/include/freertos/idf_additions.h
  18. 0 14
      components/freertos/linker.lf
  19. 14 3
      components/freertos/linker_common.lf
  20. 4 0
      components/freertos/port_systick.c
  21. 4 0
      components/freertos/test_apps/freertos/port/test_fpu_in_isr.c
  22. 4 0
      components/freertos/test_apps/freertos/port/test_fpu_in_task.c
  23. 3 0
      tools/mocks/freertos/CMakeLists.txt

+ 1 - 5
components/freertos/CMakeLists.txt

@@ -99,13 +99,9 @@ endif()
 
 # Add ESP-additions source files
 list(APPEND srcs
+    "esp_additions/freertos_compatibility.c"
     "esp_additions/idf_additions.c")
 
-if(kernel_impl STREQUAL "FreeRTOS-Kernel")
-    list(APPEND srcs
-        "esp_additions/freertos_compatibility.c")
-endif()
-
 if(arch STREQUAL "linux")
     # Check if we need to address the FreeRTOS EINTR coexistence with linux system calls if we're building without
     # lwIP, we need to use linux system select which will receive EINTR event on every FreeRTOS interrupt, we

+ 24 - 6
components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h

@@ -1393,11 +1393,29 @@ typedef StaticStreamBuffer_t StaticMessageBuffer_t;
 #endif
 /* *INDENT-ON* */
 
-/* IDF API additions have been moved to idf_additions.h when building for
- * Amazon SMP FreeRTOS. However, the rest of ESP-IDF has not been updated to
- * include this header explicitly when calling this additional API. Thus, we
- * include this here as a workaround until the rest of ESP-IDF can be updated
- * to include idf_additions.h explicitly. */
-#include "freertos/idf_additions.h"
+/*-----------------------------------------------------------
+* IDF Compatibility
+*----------------------------------------------------------*/
+
+#ifdef ESP_PLATFORM
+
+    /*
+     * Include ESP-IDF API additions implicitly for compatibility reasons.
+     *
+     * ESP-IDF API additions were previously added directly to FreeRTOS headers
+     * (e.g., task.h, queue.h). These APIs have now been moved to
+     * idf_additions.h.
+     *
+     * To ensure there are no breaking changes, we include idf_additions.h
+     * implicitly here so that those API additions are still accessible. Given
+     * that FreeRTOS.h must be included first before calling any FreeRTOS API,
+     * any existing source code can continue using these relocated APIs without
+     * any additional header inclusions via this implicit inclusion.
+     *
+     * Todo: Deprecate this implicit inclusion by ESP-IDF v6.0 (IDF-8126)
+     */
+    #include "freertos/idf_additions.h"
+
+#endif /* ESP_PLATFORM */
 
 #endif /* INC_FREERTOS_H */

+ 0 - 19
components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h

@@ -3306,25 +3306,6 @@ void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNC
  */
 void vTaskYieldWithinAPI( void );
 
-/* ------------------------------------------------ IDF Compatibility --------------------------------------------------
- *
- * ------------------------------------------------------------------------------------------------------------------ */
-
-#ifdef ESP_PLATFORM
-
-#if ( configNUM_CORES > 1 )
-/*
-Workaround for non-thread safe multi-core OS startup (see IDF-4524)
-This function must be called with interrupts disabled on all cores other than
-core 0 during startup.
-*/
-void vTaskStartSchedulerOtherCores( void );
-#endif // configNUM_CORES > 1
-
-#include "freertos/idf_additions.h"
-
-#endif //ESP_PLATFORM
-
 /* *INDENT-OFF* */
 #ifdef __cplusplus
     }

+ 2 - 1
components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c

@@ -18,6 +18,7 @@
 #include "xtensa/config/core.h"
 #include "xtensa/config/core-isa.h"
 #include "xtensa/xtruntime.h"
+#include "esp_private/freertos_idf_additions_priv.h"
 #include "esp_private/esp_int_wdt.h"
 #include "esp_private/systimer.h"
 #include "esp_private/periph_ctrl.h"
@@ -328,7 +329,7 @@ BaseType_t xPortStartScheduler( void )
 #if configNUM_CORES > 1
     // Workaround for non-thread safe multi-core OS startup (see IDF-4524)
     if (xPortGetCoreID() != 0) {
-        vTaskStartSchedulerOtherCores();
+        prvStartSchedulerOtherCores();
     }
 #endif // configNUM_CORES > 1
 

+ 0 - 11
components/freertos/FreeRTOS-Kernel-SMP/tasks.c

@@ -6506,14 +6506,3 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
     #endif
 
 #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
-
-#if ( ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1 ) )
-/*
-Workaround for non-thread safe multi-core OS startup (see IDF-4524)
-*/
-void vTaskStartSchedulerOtherCores( void )
-{
-    /* This function is always called with interrupts disabled*/
-    xSchedulerRunning = pdTRUE;
-}
-#endif // ( ESP_PLATFORM == 1 ) && ( configNUM_CORES > 1

+ 9 - 7
components/freertos/FreeRTOS-Kernel/event_groups.c

@@ -3,7 +3,7 @@
  *
  * SPDX-License-Identifier: MIT
  *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
  */
 
 /*
@@ -45,6 +45,8 @@
 #include "task.h"
 #include "timers.h"
 #include "event_groups.h"
+/* Include private IDF API additions for critical thread safety macros */
+#include "esp_private/freertos_idf_additions_priv.h"
 
 /* Lint e961, e750 and e9021 are suppressed as a MISRA exception justified
  * because the MPU ports require MPU_WRAPPERS_INCLUDED_FROM_API_FILE to be defined
@@ -566,8 +568,8 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
     #if ( configNUM_CORES > 1 )
 
         /* We are about to traverse a task list which is a kernel data structure.
-         * Thus we need to call vTaskTakeKernelLock() to take the kernel lock. */
-        vTaskTakeKernelLock();
+         * Thus we need to call prvTakeKernelLock() to take the kernel lock. */
+        prvTakeKernelLock();
     #endif /* configNUM_CORES > 1 */
     {
         traceEVENT_GROUP_SET_BITS( xEventGroup, uxBitsToSet );
@@ -642,7 +644,7 @@ EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup,
     }
     #if ( configNUM_CORES > 1 )
         /* Release the previously taken kernel lock. */
-        vTaskReleaseKernelLock();
+        prvReleaseKernelLock();
     #endif /* configNUM_CORES > 1 */
     ( void ) prvEXIT_CRITICAL_OR_RESUME_ALL( &( pxEventBits->xEventGroupLock ) );
 
@@ -659,8 +661,8 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup )
     #if ( configNUM_CORES > 1 )
 
         /* We are about to traverse a task list which is a kernel data structure.
-         * Thus we need to call vTaskTakeKernelLock() to take the kernel lock. */
-        vTaskTakeKernelLock();
+         * Thus we need to call prvTakeKernelLock() to take the kernel lock. */
+        prvTakeKernelLock();
     #endif /* configNUM_CORES > 1 */
     {
         traceEVENT_GROUP_DELETE( xEventGroup );
@@ -675,7 +677,7 @@ void vEventGroupDelete( EventGroupHandle_t xEventGroup )
     }
     #if ( configNUM_CORES > 1 )
         /* Release the previously taken kernel lock. */
-        vTaskReleaseKernelLock();
+        prvReleaseKernelLock();
     #endif /* configNUM_CORES > 1 */
     prvEXIT_CRITICAL_OR_RESUME_ALL( &( pxEventBits->xEventGroupLock ) );
 

+ 26 - 1
components/freertos/FreeRTOS-Kernel/include/freertos/FreeRTOS.h

@@ -3,7 +3,7 @@
  *
  * SPDX-License-Identifier: MIT
  *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
  */
 
 /*
@@ -1404,4 +1404,29 @@ typedef StaticStreamBuffer_t StaticMessageBuffer_t;
 #endif
 /* *INDENT-ON* */
 
+/*-----------------------------------------------------------
+* IDF Compatibility
+*----------------------------------------------------------*/
+
+#ifdef ESP_PLATFORM
+
+    /*
+     * Include ESP-IDF API additions implicitly for compatibility reasons.
+     *
+     * ESP-IDF API additions were previously added directly to FreeRTOS headers
+     * (e.g., task.h, queue.h). These APIs have now been moved to
+     * idf_additions.h.
+     *
+     * To ensure there are no breaking changes, we include idf_additions.h
+     * implicitly here so that those API additions are still accessible. Given
+     * that FreeRTOS.h must be included first before calling any FreeRTOS API,
+     * any existing source code can continue using these relocated APIs without
+     * any additional header inclusions via this implicit inclusion.
+     *
+     * Todo: Deprecate this implicit inclusion by ESP-IDF v6.0 (IDF-8126)
+     */
+    #include "freertos/idf_additions.h"
+
+#endif /* ESP_PLATFORM */
+
 #endif /* INC_FREERTOS_H */

+ 56 - 341
components/freertos/FreeRTOS-Kernel/include/freertos/task.h

@@ -3,7 +3,7 @@
  *
  * SPDX-License-Identifier: MIT
  *
- * SPDX-FileContributor: 2016-2022 Espressif Systems (Shanghai) CO LTD
+ * SPDX-FileContributor: 2016-2023 Espressif Systems (Shanghai) CO LTD
  */
 
 /*
@@ -285,204 +285,6 @@ typedef enum
  * TASK CREATION API
  *----------------------------------------------------------*/
 
-/**
- * Create a new task with a specified affinity and add it to the list of tasks
- * that are ready to run.
- *
- * This function is similar to xTaskCreate, but allows setting task affinity
- * in SMP system.
- *
- * @param pxTaskCode Pointer to the task entry function.  Tasks
- * must be implemented to never return (i.e. continuous loop), or should be
- * terminated using vTaskDelete function.
- *
- * @param pcName A descriptive name for the task.  This is mainly used to
- * facilitate debugging.  Max length defined by configMAX_TASK_NAME_LEN - default
- * is 16.
- *
- * @param usStackDepth The size of the task stack specified as the number of
- * bytes. Note that this differs from vanilla FreeRTOS.
- *
- * @param pvParameters Pointer that will be used as the parameter for the task
- * being created.
- *
- * @param uxPriority The priority at which the task should run.  Systems that
- * include MPU support can optionally create tasks in a privileged (system)
- * mode by setting bit portPRIVILEGE_BIT of the priority parameter.  For
- * example, to create a privileged task at priority 2 the uxPriority parameter
- * should be set to ( 2 | portPRIVILEGE_BIT ).
- *
- * @param[out] pvCreatedTask Used to pass back a handle by which the created task
- * can be referenced.
- *
- * @param xCoreID If the value is tskNO_AFFINITY, the created task is not
- * pinned to any CPU, and the scheduler can run it on any core available.
- * Values 0 or 1 indicate the index number of the CPU which the task should
- * be pinned to. Specifying values larger than (configNUM_CORES - 1) will
- * cause the function to fail.
- *
- * @return pdPASS if the task was successfully created and added to a ready
- * list, otherwise an error code defined in the file projdefs.h
- *
- * @note If program uses thread local variables (ones specified with "__thread" keyword)
- * then storage for them will be allocated on the task's stack.
- *
- * Example usage:
- * @code{c}
- * // Task to be created.
- * void vTaskCode( void * pvParameters )
- * {
- *   for( ;; )
- *   {
- *       // Task code goes here.
- *   }
- * }
- *
- * // Function that creates a task.
- * void vOtherFunction( void )
- * {
- * static uint8_t ucParameterToPass;
- * TaskHandle_t xHandle = NULL;
- *
- *   // Create the task pinned to core 0, storing the handle.  Note that the passed parameter ucParameterToPass
- *   // must exist for the lifetime of the task, so in this case is declared static.  If it was just an
- *   // an automatic stack variable it might no longer exist, or at least have been corrupted, by the time
- *   // the new task attempts to access it.
- *   xTaskCreatePinnedToCore( vTaskCode, "NAME", STACK_SIZE, &ucParameterToPass, tskIDLE_PRIORITY, &xHandle, 0 );
- *   configASSERT( xHandle );
- *
- *   // Use the handle to delete the task.
- *   if( xHandle != NULL )
- *   {
- *      vTaskDelete( xHandle );
- *   }
- * }
- * @endcode
- * @cond !DOC_SINGLE_GROUP
- * \defgroup xTaskCreatePinnedToCore xTaskCreatePinnedToCore
- * @endcond
- * \ingroup Tasks
- */
-#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-    BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
-                                        const char * const pcName,
-                                        const configSTACK_DEPTH_TYPE usStackDepth,
-                                        void * const pvParameters,
-                                        UBaseType_t uxPriority,
-                                        TaskHandle_t * const pvCreatedTask,
-                                        const BaseType_t xCoreID );
-#endif
-
-/**
- * Create a new task with a specified affinity and add it to the list of tasks
- * that are ready to run.
- *
- * This function is similar to xTaskCreateStatic, but allows specifying
- * task affinity in an SMP system.
- *
- * @param pxTaskCode Pointer to the task entry function.  Tasks
- * must be implemented to never return (i.e. continuous loop), or should be
- * terminated using vTaskDelete function.
- *
- * @param pcName A descriptive name for the task.  This is mainly used to
- * facilitate debugging.  The maximum length of the string is defined by
- * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
- *
- * @param ulStackDepth The size of the task stack specified as the number of
- * bytes. Note that this differs from vanilla FreeRTOS.
- *
- * @param pvParameters Pointer that will be used as the parameter for the task
- * being created.
- *
- * @param uxPriority The priority at which the task will run.
- *
- * @param pxStackBuffer Must point to a StackType_t array that has at least
- * ulStackDepth indexes - the array will then be used as the task's stack,
- * removing the need for the stack to be allocated dynamically.
- *
- * @param pxTaskBuffer Must point to a variable of type StaticTask_t, which will
- * then be used to hold the task's data structures, removing the need for the
- * memory to be allocated dynamically.
- *
- * @param xCoreID If the value is tskNO_AFFINITY, the created task is not
- * pinned to any CPU, and the scheduler can run it on any core available.
- * Values 0 or 1 indicate the index number of the CPU which the task should
- * be pinned to. Specifying values larger than (configNUM_CORES - 1) will
- * cause the function to fail.
- *
- * @return If neither pxStackBuffer or pxTaskBuffer are NULL, then the task will
- * be created and pdPASS is returned.  If either pxStackBuffer or pxTaskBuffer
- * are NULL then the task will not be created and
- * errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY is returned.
- *
- * Example usage:
- * @code{c}
- *
- *  // Dimensions the buffer that the task being created will use as its stack.
- *  // NOTE:  This is the number of words the stack will hold, not the number of
- *  // bytes.  For example, if each stack item is 32-bits, and this is set to 100,
- *  // then 400 bytes (100 * 32-bits) will be allocated.
- * #define STACK_SIZE 200
- *
- *  // Structure that will hold the TCB of the task being created.
- *  StaticTask_t xTaskBuffer;
- *
- *  // Buffer that the task being created will use as its stack.  Note this is
- *  // an array of StackType_t variables.  The size of StackType_t is dependent on
- *  // the RTOS port.
- *  StackType_t xStack[ STACK_SIZE ];
- *
- *  // Function that implements the task being created.
- *  void vTaskCode( void * pvParameters )
- *  {
- *      // The parameter value is expected to be 1 as 1 is passed in the
- *      // pvParameters value in the call to xTaskCreateStaticPinnedToCore().
- *      configASSERT( ( uint32_t ) pvParameters == 1UL );
- *
- *      for( ;; )
- *      {
- *          // Task code goes here.
- *      }
- *  }
- *
- *  // Function that creates a task.
- *  void vOtherFunction( void )
- *  {
- *      TaskHandle_t xHandle = NULL;
- *
- *      // Create the task pinned to core 0 without using any dynamic memory allocation.
- *      xHandle = xTaskCreateStaticPinnedToCore(
- *                    vTaskCode,       // Function that implements the task.
- *                    "NAME",          // Text name for the task.
- *                    STACK_SIZE,      // Stack size in bytes, not words.
- *                    ( void * ) 1,    // Parameter passed into the task.
- *                    tskIDLE_PRIORITY,// Priority at which the task is created.
- *                    xStack,          // Array to use as the task's stack.
- *                    &xTaskBuffer,    // Variable to hold the task's data structure.
- *                    0 );             // Specify the task's core affinity
- *
- *      // puxStackBuffer and pxTaskBuffer were not NULL, so the task will have
- *      // been created, and xHandle will be the task's handle.  Use the handle
- *      // to suspend the task.
- *      vTaskSuspend( xHandle );
- *  }
- * @endcode
- * @cond !DOC_SINGLE_GROUP
- * \defgroup xTaskCreateStaticPinnedToCore xTaskCreateStaticPinnedToCore
- * @endcond
- * \ingroup Tasks
- */
-#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
-    TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode,
-                                                const char * const pcName,
-                                                const uint32_t ulStackDepth,
-                                                void * const pvParameters,
-                                                UBaseType_t uxPriority,
-                                                StackType_t * const pxStackBuffer,
-                                                StaticTask_t * const pxTaskBuffer,
-                                                const BaseType_t xCoreID );
-#endif /* configSUPPORT_STATIC_ALLOCATION */
-
 /**
  * @cond !DOC_EXCLUDE_HEADER_SECTION
  * task. h
@@ -526,8 +328,8 @@ typedef enum
  * facilitate debugging.  Max length defined by configMAX_TASK_NAME_LEN - default
  * is 16.
  *
- * @param usStackDepth The size of the task stack specified as the number of
- * bytes. Note that this differs from vanilla FreeRTOS.
+ * @param usStackDepth The size of the task stack specified as the NUMBER OF
+ * BYTES. Note that this differs from vanilla FreeRTOS.
  *
  * @param pvParameters Pointer that will be used as the parameter for the task
  * being created.
@@ -584,6 +386,7 @@ typedef enum
  * \ingroup Tasks
  */
 #if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
+
     static inline __attribute__( ( always_inline ) )
     BaseType_t xTaskCreate( TaskFunction_t pxTaskCode,
                             const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
@@ -592,8 +395,31 @@ typedef enum
                             UBaseType_t uxPriority,
                             TaskHandle_t * const pxCreatedTask ) PRIVILEGED_FUNCTION
     {
-        return xTaskCreatePinnedToCore( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask, tskNO_AFFINITY );
+        /*
+         * The idf_additions.h has not been included here yet due to inclusion
+         * order. Thus we manually declare the function here.
+         */
+        extern BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
+                                                   const char * const pcName,
+                                                   const configSTACK_DEPTH_TYPE usStackDepth,
+                                                   void * const pvParameters,
+                                                   UBaseType_t uxPriority,
+                                                   TaskHandle_t * const pvCreatedTask,
+                                                   const BaseType_t xCoreID );
+
+        /*
+         * Call the "PinnedToCore" version with tskNO_AFFINITY to create
+         * an unpinned task.
+         */
+        return xTaskCreatePinnedToCore( pxTaskCode,
+                                        pcName,
+                                        usStackDepth,
+                                        pvParameters,
+                                        uxPriority,
+                                        pxCreatedTask,
+                                        tskNO_AFFINITY );
     }
+
 #endif /* if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
 
 /**
@@ -630,8 +456,8 @@ typedef enum
  * facilitate debugging.  The maximum length of the string is defined by
  * configMAX_TASK_NAME_LEN in FreeRTOSConfig.h.
  *
- * @param ulStackDepth The size of the task stack specified as the number of
- * bytes. Note that this differs from vanilla FreeRTOS.
+ * @param ulStackDepth The size of the task stack specified as the NUMBER OF
+ * BYTES. Note that this differs from vanilla FreeRTOS.
  *
  * @param pvParameters Pointer that will be used as the parameter for the task
  * being created.
@@ -706,8 +532,8 @@ typedef enum
  * @endcode
  * \ingroup Tasks
  */
-
 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
+
     static inline __attribute__( ( always_inline ) )
     TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
                                     const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
@@ -717,8 +543,32 @@ typedef enum
                                     StackType_t * const puxStackBuffer,
                                     StaticTask_t * const pxTaskBuffer ) PRIVILEGED_FUNCTION
     {
-        return xTaskCreateStaticPinnedToCore( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, tskNO_AFFINITY );
+        /*
+         * The idf_additions.h has not been included here yet due to inclusion
+         * order. Thus we manually declare the function here.
+         */
+        extern TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode,
+                                                            const char * const pcName,
+                                                            const uint32_t ulStackDepth,
+                                                            void * const pvParameters,
+                                                            UBaseType_t uxPriority,
+                                                            StackType_t * const pxStackBuffer,
+                                                            StaticTask_t * const pxTaskBuffer,
+                                                            const BaseType_t xCoreID );
+        /*
+         * Call the "PinnedToCore" version with tskNO_AFFINITY to create
+         * an unpinned task.
+         */
+        return xTaskCreateStaticPinnedToCore( pxTaskCode,
+                                              pcName,
+                                              ulStackDepth,
+                                              pvParameters,
+                                              uxPriority,
+                                              puxStackBuffer,
+                                              pxTaskBuffer,
+                                              tskNO_AFFINITY );
     }
+
 #endif /* configSUPPORT_STATIC_ALLOCATION */
 
 /**
@@ -1950,21 +1800,6 @@ UBaseType_t uxTaskGetStackHighWaterMark( TaskHandle_t xTask ) PRIVILEGED_FUNCTIO
  */
 configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
 
-/**
- * Returns the start of the stack associated with xTask.
- *
- * INCLUDE_pxTaskGetStackStart must be set to 1 in FreeRTOSConfig.h for
- * this function to be available.
- *
- * Returns the lowest stack memory address, regardless of whether the stack grows up or down.
- *
- * @param xTask Handle of the task associated with the stack returned.
- * Set xTask to NULL to return the stack of the calling task.
- *
- * @return A pointer to the start of the stack.
- */
-uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
-
 /* When using trace macros it is sometimes necessary to include task.h before
  * FreeRTOS.h.  When this is done TaskHookFunction_t will not yet have been defined,
  * so the following two prototypes will cause a compilation error.  This can be
@@ -2039,7 +1874,6 @@ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
                                             BaseType_t xIndex,
                                             void * pvValue ) PRIVILEGED_FUNCTION;
 
-
     /**
      * Get local storage pointer specific to the given task.
      *
@@ -2056,39 +1890,6 @@ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
     void * pvTaskGetThreadLocalStoragePointer( TaskHandle_t xTaskToQuery,
                                                BaseType_t xIndex ) PRIVILEGED_FUNCTION;
 
-    #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 )
-
-        /**
-         * Prototype of local storage pointer deletion callback.
-         */
-        typedef void (*TlsDeleteCallbackFunction_t)( int, void * );
-
-        /**
-         * Set local storage pointer and deletion callback.
-         *
-         * Each task contains an array of pointers that is dimensioned by the
-         * configNUM_THREAD_LOCAL_STORAGE_POINTERS setting in FreeRTOSConfig.h.
-         * The kernel does not use the pointers itself, so the application writer
-         * can use the pointers for any purpose they wish.
-         *
-         * Local storage pointers set for a task can reference dynamically
-         * allocated resources. This function is similar to
-         * vTaskSetThreadLocalStoragePointer, but provides a way to release
-         * these resources when the task gets deleted. For each pointer,
-         * a callback function can be set. This function will be called
-         * when task is deleted, with the local storage pointer index
-         * and value as arguments.
-         *
-         * @param xTaskToSet  Task to set thread local storage pointer for
-         * @param xIndex The index of the pointer to set, from 0 to
-         *               configNUM_THREAD_LOCAL_STORAGE_POINTERS - 1.
-         * @param pvValue  Pointer value to set.
-         * @param pvDelCallback  Function to call to dispose of the local
-         *                       storage pointer when the task is deleted.
-         */
-        void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback);
-    #endif
-
 #endif /* if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS > 0 ) */
 
 #if ( configCHECK_FOR_STACK_OVERFLOW > 0 )
@@ -3439,58 +3240,6 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION;
  *----------------------------------------------------------*/
 /** @cond !DOC_EXCLUDE_HEADER_SECTION */
 
-/*
- * Various convenience macros for critical sections and scheduler suspension
- * called by other FreeRTOS sources and not meant to be called by the
- * application. The behavior of each macro depends on whether FreeRTOS is
- * currently configured for SMP or single core.
- */
-#if ( configNUM_CORES > 1 )
-    #define prvENTER_CRITICAL_OR_SUSPEND_ALL( x )  taskENTER_CRITICAL( ( x ) )
-    #define prvEXIT_CRITICAL_OR_RESUME_ALL( x )    ( { taskEXIT_CRITICAL( ( x ) ); pdFALSE; } )
-    #define prvENTER_CRITICAL_OR_MASK_ISR( pxLock, uxInterruptStatus ) \
-        taskENTER_CRITICAL_ISR( ( pxLock ) );                          \
-        ( void ) ( uxInterruptStatus );
-    #define prvEXIT_CRITICAL_OR_UNMASK_ISR( pxLock, uxInterruptStatus ) \
-        taskEXIT_CRITICAL_ISR( ( pxLock ) );                            \
-        ( void ) ( uxInterruptStatus );
-#else /* configNUM_CORES > 1 */
-    #define prvENTER_CRITICAL_OR_SUSPEND_ALL( x )  ( { vTaskSuspendAll(); ( void ) ( x ); } )
-    #define prvEXIT_CRITICAL_OR_RESUME_ALL( x )    xTaskResumeAll()
-    #define prvENTER_CRITICAL_OR_MASK_ISR( pxLock, uxInterruptStatus )  \
-        ( uxInterruptStatus ) = portSET_INTERRUPT_MASK_FROM_ISR();      \
-        ( void ) ( pxLock );
-    #define prvEXIT_CRITICAL_OR_UNMASK_ISR( pxLock, uxInterruptStatus )  \
-        portCLEAR_INTERRUPT_MASK_FROM_ISR( ( uxInterruptStatus ) );      \
-        ( void ) ( pxLock );
-#endif /* configNUM_CORES > 1 */
-
-/*
- * Return the handle of the task running on a certain CPU. Because of
- * the nature of SMP processing, there is no guarantee that this
- * value will still be valid on return and should only be used for
- * debugging purposes.
- */
-TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid );
-
-/**
- * Get the handle of idle task for the given CPU.
- *
- * xTaskGetIdleTaskHandleForCPU() is only available if
- * INCLUDE_xTaskGetIdleTaskHandle is set to 1 in FreeRTOSConfig.h.
- *
- * @param cpuid The CPU to get the handle for
- *
- * @return Idle task handle of a given cpu. It is not valid to call
- * xTaskGetIdleTaskHandleForCPU() before the scheduler has been started.
- */
-TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid );
-
-/*
- * Get the current core affinity of a task
- */
-BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
-
 /*
  * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS ONLY
  * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
@@ -3511,20 +3260,6 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ) PRIVILEGED_FUNCTION;
  */
 BaseType_t xTaskIncrementTick( void ) PRIVILEGED_FUNCTION;
 
-#if ( configNUM_CORES > 1 )
-
-/*
- * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS ONLY
- * INTENDED FOR USE WHEN IMPLEMENTING A PORT OF THE SCHEDULER AND IS
- * AN INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
- *
- * Called from all other cores except core 0 when their tick interrupt
- * occurs. This function will check if the current core requires time slicing,
- * and also call the application tick hook.
- */
-    BaseType_t xTaskIncrementTickOtherCores( void ) PRIVILEGED_FUNCTION;
-#endif /* configNUM_CORES > 1 */
-
 /*
  * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN
  * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
@@ -3577,26 +3312,6 @@ void vTaskPlaceOnEventListRestricted( List_t * const pxEventList,
                                       TickType_t xTicksToWait,
                                       const BaseType_t xWaitIndefinitely ) PRIVILEGED_FUNCTION;
 
-#if ( configNUM_CORES > 1 )
-
-/*
- * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN
- * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.
- *
- * This function is a wrapper to take the "xKernelLock" spinlock of tasks.c.
- * This lock is taken whenver any of the kernel's data structures are
- * accessed/modified, such as when adding/removing tasks to/from the delayed
- * task list or various event lists.
- *
- * This functions is meant to be called by xEventGroupSetBits() and
- * vEventGroupDelete() as both those functions will access event lists (instead
- * of delegating the entire responsibility to one of vTask...EventList()
- * functions).
- */
-    void vTaskTakeKernelLock( void );
-    void vTaskReleaseKernelLock( void );
-#endif /* configNUM_CORES > 1 */
-
 /*
  * THIS FUNCTION MUST NOT BE USED FROM APPLICATION CODE.  IT IS AN
  * INTERFACE WHICH IS FOR THE EXCLUSIVE USE OF THE SCHEDULER.

+ 2 - 0
components/freertos/FreeRTOS-Kernel/queue.c

@@ -43,6 +43,8 @@
 #include "FreeRTOS.h"
 #include "task.h"
 #include "queue.h"
+/* Include private IDF API additions for critical thread safety macros */
+#include "esp_private/freertos_idf_additions_priv.h"
 
 #if ( configUSE_CO_ROUTINES == 1 )
     #include "croutine.h"

+ 2 - 0
components/freertos/FreeRTOS-Kernel/stream_buffer.c

@@ -45,6 +45,8 @@
 #include "FreeRTOS.h"
 #include "task.h"
 #include "stream_buffer.h"
+/* Include private IDF API additions for critical thread safety macros */
+#include "esp_private/freertos_idf_additions_priv.h"
 
 #if ( configUSE_TASK_NOTIFICATIONS != 1 )
     #error configUSE_TASK_NOTIFICATIONS must be set to 1 to build stream_buffer.c

+ 27 - 414
components/freertos/FreeRTOS-Kernel/tasks.c

@@ -46,6 +46,8 @@
 #include "task.h"
 #include "timers.h"
 #include "stack_macros.h"
+/* Include private IDF API additions for critical thread safety macros */
+#include "esp_private/freertos_idf_additions_priv.h"
 
 #ifdef ESP_PLATFORM
     #undef _REENT_INIT_PTR
@@ -502,28 +504,6 @@ PRIVILEGED_DATA static volatile BaseType_t xSwitchingContext[ configNUM_CORES ]
 
 /*-----------------------------------------------------------*/
 
-/* Callback function prototypes. --------------------------*/
-#if ( configCHECK_FOR_STACK_OVERFLOW > 0 )
-
-    extern void vApplicationStackOverflowHook( TaskHandle_t xTask,
-                                               char * pcTaskName );
-
-#endif
-
-#if ( configUSE_TICK_HOOK > 0 )
-
-    extern void vApplicationTickHook( void ); /*lint !e526 Symbol not defined as it is an application callback. */
-
-#endif
-
-#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
-
-    extern void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,
-                                               StackType_t ** ppxIdleTaskStackBuffer,
-                                               uint32_t * pulIdleTaskStackSize ); /*lint !e526 Symbol not defined as it is an application callback. */
-
-#endif
-
 /* File private functions. --------------------------------*/
 
 /**
@@ -728,64 +708,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
 
 /*-----------------------------------------------------------*/
 
-#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
-
-    TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode,
-                                                const char * const pcName,
-                                                const uint32_t ulStackDepth,
-                                                void * const pvParameters,
-                                                UBaseType_t uxPriority,
-                                                StackType_t * const puxStackBuffer,
-                                                StaticTask_t * const pxTaskBuffer,
-                                                const BaseType_t xCoreID )
-    {
-        TCB_t * pxNewTCB;
-        TaskHandle_t xReturn;
-
-        configASSERT( portVALID_STACK_MEM( puxStackBuffer ) );
-        configASSERT( portVALID_TCB_MEM( pxTaskBuffer ) );
-        configASSERT( ( ( xCoreID >= 0 ) && ( xCoreID < configNUM_CORES ) ) || ( xCoreID == tskNO_AFFINITY ) );
-
-        #if ( configASSERT_DEFINED == 1 )
-            {
-                /* Sanity check that the size of the structure used to declare a
-                 * variable of type StaticTask_t equals the size of the real task
-                 * structure. */
-                volatile size_t xSize = sizeof( StaticTask_t );
-                configASSERT( xSize == sizeof( TCB_t ) );
-                ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
-            }
-        #endif /* configASSERT_DEFINED */
-
-        if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
-        {
-            /* The memory used for the task's TCB and stack are passed into this
-             * function - use them. */
-            pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
-            pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
-
-            #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
-                {
-                    /* Tasks can be created statically or dynamically, so note this
-                     * task was created statically in case the task is later deleted. */
-                    pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
-                }
-            #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
-
-            prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID );
-            prvAddNewTaskToReadyList( pxNewTCB );
-        }
-        else
-        {
-            xReturn = NULL;
-        }
-
-        return xReturn;
-    }
-
-#endif /* SUPPORT_STATIC_ALLOCATION */
-/*-----------------------------------------------------------*/
-
 #if ( ( portUSING_MPU_WRAPPERS == 1 ) && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
 
     BaseType_t xTaskCreateRestrictedStatic( const TaskParameters_t * const pxTaskDefinition,
@@ -885,100 +807,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB ) PRIVILEGED_FUNCTION;
 #endif /* portUSING_MPU_WRAPPERS */
 /*-----------------------------------------------------------*/
 
-#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
-
-    BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
-                                        const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
-                                        const configSTACK_DEPTH_TYPE usStackDepth,
-                                        void * const pvParameters,
-                                        UBaseType_t uxPriority,
-                                        TaskHandle_t * const pxCreatedTask,
-                                        const BaseType_t xCoreID )
-    {
-        TCB_t * pxNewTCB;
-        BaseType_t xReturn;
-
-        /* If the stack grows down then allocate the stack then the TCB so the stack
-         * does not grow into the TCB.  Likewise if the stack grows up then allocate
-         * the TCB then the stack. */
-        #if ( portSTACK_GROWTH > 0 )
-            {
-                /* Allocate space for the TCB.  Where the memory comes from depends on
-                 * the implementation of the port malloc function and whether or not static
-                 * allocation is being used. */
-                pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
-
-                if( pxNewTCB != NULL )
-                {
-                    /* Allocate space for the stack used by the task being created.
-                     * The base of the stack memory stored in the TCB so the task can
-                     * be deleted later if required. */
-                    pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
-
-                    if( pxNewTCB->pxStack == NULL )
-                    {
-                        /* Could not allocate the stack.  Delete the allocated TCB. */
-                        vPortFree( pxNewTCB );
-                        pxNewTCB = NULL;
-                    }
-                }
-            }
-        #else /* portSTACK_GROWTH */
-            {
-                StackType_t * pxStack;
-
-                /* Allocate space for the stack used by the task being created. */
-                pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
-
-                if( pxStack != NULL )
-                {
-                    /* Allocate space for the TCB. */
-                    pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
-
-                    if( pxNewTCB != NULL )
-                    {
-                        /* Store the stack location in the TCB. */
-                        pxNewTCB->pxStack = pxStack;
-                    }
-                    else
-                    {
-                        /* The stack cannot be used as the TCB was not created.  Free
-                         * it again. */
-                        vPortFree( pxStack );
-                    }
-                }
-                else
-                {
-                    pxNewTCB = NULL;
-                }
-            }
-        #endif /* portSTACK_GROWTH */
-
-        if( pxNewTCB != NULL )
-        {
-            #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
-                {
-                    /* Tasks can be created statically or dynamically, so note this
-                     * task was created dynamically in case it is later deleted. */
-                    pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
-                }
-            #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
-
-            prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL, xCoreID );
-            prvAddNewTaskToReadyList( pxNewTCB );
-            xReturn = pdPASS;
-        }
-        else
-        {
-            xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
-        }
-
-        return xReturn;
-    }
-
-#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
-/*-----------------------------------------------------------*/
-
 static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
                                   const char * const pcName, /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
                                   const uint32_t ulStackDepth,
@@ -1528,15 +1356,6 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB )
 /*-----------------------------------------------------------*/
 
 #if ( INCLUDE_xTaskDelayUntil == 1 )
-    #ifdef ESP_PLATFORM
-        /* backward binary compatibility - remove later */
-        #undef vTaskDelayUntil
-        void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
-                              const TickType_t xTimeIncrement )
-        {
-            xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement );
-        }
-    #endif // ESP_PLATFORM
 
     BaseType_t xTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
                                 const TickType_t xTimeIncrement )
@@ -3014,12 +2833,6 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery ) /*lint !e971 Unqualified char
         return xIdleTaskHandle[ xPortGetCoreID() ];
     }
 
-    TaskHandle_t xTaskGetIdleTaskHandleForCPU( UBaseType_t cpuid )
-    {
-        configASSERT( cpuid < configNUM_CORES );
-        configASSERT( ( xIdleTaskHandle[ cpuid ] != NULL ) );
-        return xIdleTaskHandle[ cpuid ];
-    }
 #endif /* INCLUDE_xTaskGetIdleTaskHandle */
 /*----------------------------------------------------------*/
 
@@ -3367,90 +3180,6 @@ BaseType_t xTaskIncrementTick( void )
 
     return xSwitchRequired;
 }
-
-#if ( configNUM_CORES > 1 )
-    BaseType_t xTaskIncrementTickOtherCores( void )
-    {
-        /* Minor optimization. This function can never switch cores mid
-         * execution */
-        BaseType_t xCoreID = xPortGetCoreID();
-        BaseType_t xSwitchRequired = pdFALSE;
-
-        /* This function should never be called by Core 0. */
-        configASSERT( xCoreID != 0 );
-
-        /* Called by the portable layer each time a tick interrupt occurs.
-         * Increments the tick then checks to see if the new tick value will cause any
-         * tasks to be unblocked. */
-        traceTASK_INCREMENT_TICK( xTickCount );
-
-        if( uxSchedulerSuspended[ xCoreID ] == ( UBaseType_t ) 0U )
-        {
-            /* We need take the kernel lock here as we are about to access
-             * kernel data structures. */
-            taskENTER_CRITICAL_ISR( &xKernelLock );
-
-            /* A task being unblocked cannot cause an immediate context switch
-             * if preemption is turned off. */
-            #if ( configUSE_PREEMPTION == 1 )
-                {
-                    /* Check if core 0 calling xTaskIncrementTick() has
-                     * unblocked a task that can be run. */
-                    if( uxTopReadyPriority > pxCurrentTCB[ xCoreID ]->uxPriority )
-                    {
-                        xSwitchRequired = pdTRUE;
-                    }
-                    else
-                    {
-                        mtCOVERAGE_TEST_MARKER();
-                    }
-                }
-            #endif /* if ( configUSE_PREEMPTION == 1 ) */
-
-            /* Tasks of equal priority to the currently running task will share
-             * processing time (time slice) if preemption is on, and the application
-             * writer has not explicitly turned time slicing off. */
-            #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
-                {
-                    if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB[ xCoreID ]->uxPriority ] ) ) > ( UBaseType_t ) 1 )
-                    {
-                        xSwitchRequired = pdTRUE;
-                    }
-                    else
-                    {
-                        mtCOVERAGE_TEST_MARKER();
-                    }
-                }
-            #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
-
-            /* Release the previously taken kernel lock as we have finished
-             * accessing the kernel data structures. */
-            taskEXIT_CRITICAL_ISR( &xKernelLock );
-
-            #if ( configUSE_PREEMPTION == 1 )
-                {
-                    if( xYieldPending[ xCoreID ] != pdFALSE )
-                    {
-                        xSwitchRequired = pdTRUE;
-                    }
-                    else
-                    {
-                        mtCOVERAGE_TEST_MARKER();
-                    }
-                }
-            #endif /* configUSE_PREEMPTION */
-        }
-
-        #if ( configUSE_TICK_HOOK == 1 )
-            {
-                vApplicationTickHook();
-            }
-        #endif
-
-        return xSwitchRequired;
-    }
-#endif /* ( configNUM_CORES > 1 ) */
-
 /*-----------------------------------------------------------*/
 
 #if ( configUSE_APPLICATION_TASK_TAG == 1 )
@@ -4008,20 +3737,6 @@ BaseType_t xTaskRemoveFromEventList( const List_t * const pxEventList )
 }
 /*-----------------------------------------------------------*/
 
-#if ( configNUM_CORES > 1 )
-    void vTaskTakeKernelLock( void )
-    {
-        /* We call the tasks.c critical section macro to take xKernelLock */
-        taskENTER_CRITICAL( &xKernelLock );
-    }
-
-    void vTaskReleaseKernelLock( void )
-    {
-        /* We call the tasks.c critical section macro to release xKernelLock */
-        taskEXIT_CRITICAL( &xKernelLock );
-    }
-#endif /* configNUM_CORES > 1 */
-
 void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
                                         const TickType_t xItemValue )
 {
@@ -4032,7 +3747,7 @@ void vTaskRemoveFromUnorderedEventList( ListItem_t * pxEventListItem,
 
         /* THIS FUNCTION MUST BE CALLED WITH THE KERNEL LOCK ALREADY TAKEN.
          * It is used by the event flags implementation, thus those functions
-         * should call vTaskTakeKernelLock() before calling this function. */
+         * should call prvTakeKernelLock() before calling this function. */
     #else /* configNUM_CORES > 1 */
 
         /* THIS FUNCTION MUST BE CALLED WITH THE SCHEDULER SUSPENDED.  It is used by
@@ -4442,79 +4157,42 @@ static portTASK_FUNCTION( prvIdleTask, pvParameters )
 
 #if ( configNUM_THREAD_LOCAL_STORAGE_POINTERS != 0 )
 
-    #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 )
-
-        void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet,
-                                                              BaseType_t xIndex,
-                                                              void * pvValue,
-                                                              TlsDeleteCallbackFunction_t xDelCallback )
+    void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
+                                            BaseType_t xIndex,
+                                            void * pvValue )
+    {
+        #if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 )
         {
-            TCB_t * pxTCB;
-
-            /* If TLSP deletion callbacks are enabled, then
-             * configNUM_THREAD_LOCAL_STORAGE_POINTERS is doubled in size so
-             * that the latter half of the pvThreadLocalStoragePointers stores
-             * the deletion callbacks. */
-            if( xIndex < ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) )
-            {
-                #if ( configNUM_CORES > 1 )
-
-                    /* For SMP, we need to take the kernel lock here as we
-                     * another core could also update this task's TLSP at the
-                     * same time. */
-                    taskENTER_CRITICAL( &xKernelLock );
-                #endif /* ( configNUM_CORES > 1 ) */
-
-                pxTCB = prvGetTCBFromHandle( xTaskToSet );
-                /* Store the TLSP by indexing the first half of the array */
-                pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
-                /* Store the TLSP deletion callback by indexing the second half
-                 * of the array. */
-                pxTCB->pvThreadLocalStoragePointers[ ( xIndex + ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ) ] = ( void * ) xDelCallback;
-
-                #if ( configNUM_CORES > 1 )
-                    /* Release the previously taken kernel lock. */
-                    taskEXIT_CRITICAL( &xKernelLock );
-                #endif /* configNUM_CORES > 1 */
-            }
+            /* TLSP Deletion Callbacks are enabled. Call the TLSPDC funciton
+             * instead with a NULL callback. */
+            vTaskSetThreadLocalStoragePointerAndDelCallback( xTaskToSet, xIndex, pvValue, NULL );
         }
-
-        void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
-                                                BaseType_t xIndex,
-                                                void * pvValue )
+        #else /* configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 */
         {
-            vTaskSetThreadLocalStoragePointerAndDelCallback( xTaskToSet, xIndex, pvValue, ( TlsDeleteCallbackFunction_t ) NULL );
-        }
+            TCB_t * pxTCB;
 
+            #if ( configNUM_CORES > 1 )
 
-    #else /* if ( configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 ) */
-        void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet,
-                                                BaseType_t xIndex,
-                                                void * pvValue )
-        {
-            TCB_t * pxTCB;
+                /* For SMP, we need to take the kernel lock here as we
+                 * another core could also update this task's TLSP at the
+                 * same time. */
+                taskENTER_CRITICAL( &xKernelLock );
+            #endif /* ( configNUM_CORES > 1 ) */
 
             if( xIndex < configNUM_THREAD_LOCAL_STORAGE_POINTERS )
             {
-                #if ( configNUM_CORES > 1 )
-
-                    /* For SMP, we need to take the kernel lock here as we
-                     * another core could also update this task's TLSP at the
-                     * same time. */
-                    taskENTER_CRITICAL( &xKernelLock );
-                #endif /* ( configNUM_CORES > 1 ) */
-
                 pxTCB = prvGetTCBFromHandle( xTaskToSet );
                 configASSERT( pxTCB != NULL );
                 pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
-
-                #if ( configNUM_CORES > 1 )
-                    /* Release the previously taken kernel lock. */
-                    taskEXIT_CRITICAL( &xKernelLock );
-                #endif /* configNUM_CORES > 1 */
             }
+
+            #if ( configNUM_CORES > 1 )
+                /* Release the previously taken kernel lock. */
+                taskEXIT_CRITICAL( &xKernelLock );
+            #endif /* configNUM_CORES > 1 */
         }
-    #endif /* configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 */
+        #endif /* configTHREAD_LOCAL_STORAGE_DELETE_CALLBACKS == 1 */
+    }
 
 #endif /* configNUM_THREAD_LOCAL_STORAGE_POINTERS */
 /*-----------------------------------------------------------*/
@@ -4773,16 +4451,6 @@ static void prvCheckTasksWaitingTermination( void )
 #endif /* configUSE_TRACE_FACILITY */
 /*-----------------------------------------------------------*/
 
-BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
-{
-    TCB_t * pxTCB;
-
-    pxTCB = prvGetTCBFromHandle( xTask );
-
-    return pxTCB->xCoreID;
-}
-/*-----------------------------------------------------------*/
-
 #if ( configUSE_TRACE_FACILITY == 1 )
 
     static UBaseType_t prvListTasksWithinSingleList( TaskStatus_t * pxTaskStatusArray,
@@ -4905,20 +4573,6 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
 
 #endif /* INCLUDE_uxTaskGetStackHighWaterMark */
 /*-----------------------------------------------------------*/
-#if ( INCLUDE_pxTaskGetStackStart == 1 )
-
-    uint8_t * pxTaskGetStackStart( TaskHandle_t xTask )
-    {
-        TCB_t * pxTCB;
-        uint8_t * uxReturn;
-
-        pxTCB = prvGetTCBFromHandle( xTask );
-        uxReturn = ( uint8_t * ) pxTCB->pxStack;
-
-        return uxReturn;
-    }
-
-#endif /* INCLUDE_pxTaskGetStackStart */
 
 #if ( INCLUDE_vTaskDelete == 1 )
 
@@ -5006,7 +4660,7 @@ static void prvResetNextTaskUnblockTime( void )
 }
 /*-----------------------------------------------------------*/
 
-#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) || ( configNUM_CORES > 1 ) )
+#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
 
     TaskHandle_t xTaskGetCurrentTaskHandle( void )
     {
@@ -5020,19 +4674,6 @@ static void prvResetNextTaskUnblockTime( void )
         return xReturn;
     }
 
-    TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t cpuid )
-    {
-        TaskHandle_t xReturn = NULL;
-
-        /*Xtensa-specific: the pxCurrentPCB pointer is atomic so we shouldn't need a lock. */
-        if( cpuid < configNUM_CORES )
-        {
-            xReturn = pxCurrentTCB[ cpuid ];
-        }
-
-        return xReturn;
-    }
-
 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
 /*-----------------------------------------------------------*/
 
@@ -5772,16 +5413,6 @@ TickType_t uxTaskResetEventItemValue( void )
 
 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
 
-    #ifdef ESP_PLATFORM /* IDF-3851 */
-        /* included here for backward binary compatibility */
-        #undef ulTaskNotifyTake
-        uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit,
-                                   TickType_t xTicksToWait )
-        {
-            return ulTaskGenericNotifyTake( tskDEFAULT_INDEX_TO_NOTIFY, xClearCountOnExit, xTicksToWait );
-        }
-    #endif // ESP-PLATFORM
-
     uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
                                       BaseType_t xClearCountOnExit,
                                       TickType_t xTicksToWait )
@@ -5854,18 +5485,6 @@ TickType_t uxTaskResetEventItemValue( void )
 
 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
 
-    #ifdef ESP_PLATFORM /* IDF-3851 */
-        /* included for backward compatibility */
-        #undef xTaskNotifyWait
-        BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
-                                    uint32_t ulBitsToClearOnExit,
-                                    uint32_t * pulNotificationValue,
-                                    TickType_t xTicksToWait )
-        {
-            return xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait );
-        }
-    #endif // ESP-PLATFORM
-
     BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
                                        uint32_t ulBitsToClearOnEntry,
                                        uint32_t ulBitsToClearOnExit,
@@ -6533,9 +6152,3 @@ static void prvAddCurrentTaskToDelayedList( TickType_t xTicksToWait,
     #endif
 
 #endif /* if ( configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H == 1 ) */
-
-/* If timers.c is not referenced anywhere, don't create the timer task to save RAM */
-BaseType_t __attribute__( ( weak ) ) xTimerCreateTimerTask( void )
-{
-    return pdPASS;
-}

+ 2 - 0
components/freertos/FreeRTOS-Kernel/timers.c

@@ -44,6 +44,8 @@
 #include "task.h"
 #include "queue.h"
 #include "timers.h"
+/* Include private IDF API additions for critical thread safety macros */
+#include "esp_private/freertos_idf_additions_priv.h"
 
 #if ( INCLUDE_xTimerPendFunctionCall == 1 ) && ( configUSE_TIMERS == 0 )
     #error configUSE_TIMERS must be set to 1 to make the xTimerPendFunctionCall() function available.

+ 0 - 2
components/freertos/config/include/freertos/FreeRTOSConfig.h

@@ -198,8 +198,6 @@
 #define INCLUDE_xTaskResumeFromISR                 1
 #define INCLUDE_xTimerPendFunctionCall             1
 #define INCLUDE_xTaskGetSchedulerState             1
-/* Unlisted */
-#define INCLUDE_pxTaskGetStackStart                1
 
 /* -------------------- Trace Macros ----------------------- */
 

+ 42 - 0
components/freertos/esp_additions/freertos_compatibility.c

@@ -35,3 +35,45 @@ BaseType_t xQueueGenericReceive( QueueHandle_t xQueue,
 
     return xQueueReceive( xQueue, pvBuffer, xTicksToWait );
 }
+
+/*
+ * vTaskDelayUntil() was deprecated into a macro and replaced by xTaskDelayUntil().
+ * This is added for pre-compiled libraries that depend on ulTaskNotifyTake()
+ * being a function.
+ *
+ * Todo: Remove this in v6.0 (IDF-3851)
+ */
+#undef vTaskDelayUntil
+void vTaskDelayUntil( TickType_t * const pxPreviousWakeTime,
+                      const TickType_t xTimeIncrement )
+{
+    xTaskDelayUntil( pxPreviousWakeTime, xTimeIncrement );
+}
+
+/*
+ * ulTaskNotifyTake() was turned into a macro. This is added for pre-compiled
+ * libraries that depend on ulTaskNotifyTake() being a function.
+ *
+ * Todo: Remove this in v6.0 (IDF-3851)
+ */
+#undef ulTaskNotifyTake
+uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit,
+                           TickType_t xTicksToWait )
+{
+    return ulTaskGenericNotifyTake( tskDEFAULT_INDEX_TO_NOTIFY, xClearCountOnExit, xTicksToWait );
+}
+
+/*
+ * xTaskNotifyWait() was turned into a macro. This is added for pre-compiled
+ * libraries that depend on xTaskNotifyWait() being a function.
+ *
+ * Todo: Remove this in v6.0 (IDF-3851)
+ */
+#undef xTaskNotifyWait
+BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
+                            uint32_t ulBitsToClearOnExit,
+                            uint32_t * pulNotificationValue,
+                            TickType_t xTicksToWait )
+{
+    return xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait );
+}

+ 444 - 83
components/freertos/esp_additions/freertos_tasks_c_additions.h

@@ -4,9 +4,8 @@
  * SPDX-License-Identifier: Apache-2.0
  */
 
-#pragma once
-
 #include "sdkconfig.h"
+#include "esp_assert.h"
 #include "freertos/idf_additions.h"
 #if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT
     #include "freertos/task_snapshot.h"
@@ -23,7 +22,7 @@
 
 /* ------------------------------------------------- Static Asserts ------------------------------------------------- */
 
-/**
+/*
  * Both StaticTask_t and TCB_t structures are provided by FreeRTOS sources.
  * This is just an additional check of the consistency of these structures.
  */
@@ -33,9 +32,139 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt
     _Static_assert( tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "CONFIG_FREERTOS_NO_AFFINITY must be the same as tskNO_AFFINITY" );
 #endif /* CONFIG_FREERTOS_SMP */
 
+/* ------------------------------------------------- Kernel Control ------------------------------------------------- */
+
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+/*
+ * Wrapper function to take "xKerneLock"
+ */
+    void prvTakeKernelLock( void )
+    {
+        /* We call the tasks.c critical section macro to take xKernelLock */
+        taskENTER_CRITICAL( &xKernelLock );
+    }
+
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+/*----------------------------------------------------------*/
+
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+/*
+ * Wrapper function to release "xKerneLock"
+ */
+    void prvReleaseKernelLock( void )
+    {
+        /* We call the tasks.c critical section macro to release xKernelLock */
+        taskEXIT_CRITICAL( &xKernelLock );
+    }
+
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+/*----------------------------------------------------------*/
+
+#if ( CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+/*
+ * Workaround for non-thread safe multi-core OS startup (see IDF-4524)
+ */
+    void prvStartSchedulerOtherCores( void )
+    {
+        /* This function is always called with interrupts disabled*/
+        xSchedulerRunning = pdTRUE;
+    }
+
+#endif /* ( CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+/*----------------------------------------------------------*/
+
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+    BaseType_t xTaskIncrementTickOtherCores( void )
+    {
+        /* Minor optimization. This function can never switch cores mid
+         * execution */
+        BaseType_t xCoreID = xPortGetCoreID();
+        BaseType_t xSwitchRequired = pdFALSE;
+
+        /* This function should never be called by Core 0. */
+        configASSERT( xCoreID != 0 );
+
+        /* Called by the portable layer each time a tick interrupt occurs.
+         * Increments the tick then checks to see if the new tick value will
+         * cause any tasks to be unblocked. */
+        traceTASK_INCREMENT_TICK( xTickCount );
+
+        if( uxSchedulerSuspended[ xCoreID ] == ( UBaseType_t ) 0U )
+        {
+            /* We need take the kernel lock here as we are about to access
+             * kernel data structures. */
+            taskENTER_CRITICAL_ISR( &xKernelLock );
+
+            /* A task being unblocked cannot cause an immediate context switch
+             * if preemption is turned off. */
+            #if ( configUSE_PREEMPTION == 1 )
+            {
+                /* Check if core 0 calling xTaskIncrementTick() has
+                 * unblocked a task that can be run. */
+                if( uxTopReadyPriority > pxCurrentTCB[ xCoreID ]->uxPriority )
+                {
+                    xSwitchRequired = pdTRUE;
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            #endif /* if ( configUSE_PREEMPTION == 1 ) */
+
+            /* Tasks of equal priority to the currently running task will share
+             * processing time (time slice) if preemption is on, and the application
+             * writer has not explicitly turned time slicing off. */
+            #if ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) )
+            {
+                if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ pxCurrentTCB[ xCoreID ]->uxPriority ] ) ) > ( UBaseType_t ) 1 )
+                {
+                    xSwitchRequired = pdTRUE;
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            #endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configUSE_TIME_SLICING == 1 ) ) */
+
+            /* Release the previously taken kernel lock as we have finished
+             * accessing the kernel data structures. */
+            taskEXIT_CRITICAL_ISR( &xKernelLock );
+
+            #if ( configUSE_PREEMPTION == 1 )
+            {
+                if( xYieldPending[ xCoreID ] != pdFALSE )
+                {
+                    xSwitchRequired = pdTRUE;
+                }
+                else
+                {
+                    mtCOVERAGE_TEST_MARKER();
+                }
+            }
+            #endif /* configUSE_PREEMPTION */
+        }
+
+        #if ( configUSE_TICK_HOOK == 1 )
+        {
+            vApplicationTickHook();
+        }
+        #endif
+
+        return xSwitchRequired;
+    }
+
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+/*----------------------------------------------------------*/
+
 /* -------------------------------------------------- Task Creation ------------------------------------------------- */
 
-#if CONFIG_FREERTOS_SMP
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
 
     BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
                                         const char * const pcName,
@@ -45,36 +174,126 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt
                                         TaskHandle_t * const pxCreatedTask,
                                         const BaseType_t xCoreID )
     {
-        BaseType_t ret;
+        BaseType_t xReturn;
 
-        #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) )
+        #if CONFIG_FREERTOS_SMP
         {
-            /* Convert xCoreID into an affinity mask */
-            UBaseType_t uxCoreAffinityMask;
-
-            if( xCoreID == tskNO_AFFINITY )
+            /* If using Amazon SMP FreeRTOS. This function is just a wrapper around
+             * xTaskCreate() or xTaskCreateAffinitySet(). */
+            #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
             {
-                uxCoreAffinityMask = tskNO_AFFINITY;
+                /* Convert xCoreID into an affinity mask */
+                UBaseType_t uxCoreAffinityMask;
+
+                /* Bit shifting << xCoreID is only valid if we have less than
+                 * 32 cores. */
+                ESP_STATIC_ASSERT( configNUM_CORES < 32 );
+
+                if( xCoreID == tskNO_AFFINITY )
+                {
+                    uxCoreAffinityMask = tskNO_AFFINITY;
+                }
+                else
+                {
+                    uxCoreAffinityMask = ( 1 << xCoreID );
+                }
+
+                xReturn = xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask );
             }
-            else
+            #else /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
             {
-                uxCoreAffinityMask = ( 1 << xCoreID );
+                xReturn = xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask );
             }
-
-            ret = xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask );
+            #endif /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
         }
-        #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */
+        #else /* CONFIG_FREERTOS_SMP */
         {
-            ret = xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask );
+            TCB_t * pxNewTCB;
+
+            /* If the stack grows down then allocate the stack then the TCB so the
+             * stack does not grow into the TCB.  Likewise if the stack grows up
+             * then allocate the TCB then the stack. */
+            #if ( portSTACK_GROWTH > 0 )
+            {
+                /* Allocate space for the TCB.  Where the memory comes from depends on
+                 * the implementation of the port malloc function and whether or not static
+                 * allocation is being used. */
+                pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) );
+
+                if( pxNewTCB != NULL )
+                {
+                    /* Allocate space for the stack used by the task being created.
+                     * The base of the stack memory stored in the TCB so the task can
+                     * be deleted later if required. */
+                    pxNewTCB->pxStack = ( StackType_t * ) pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
+
+                    if( pxNewTCB->pxStack == NULL )
+                    {
+                        /* Could not allocate the stack.  Delete the allocated TCB. */
+                        vPortFree( pxNewTCB );
+                        pxNewTCB = NULL;
+                    }
+                }
+            }
+            #else /* portSTACK_GROWTH */
+            {
+                StackType_t * pxStack;
+
+                /* Allocate space for the stack used by the task being created. */
+                pxStack = pvPortMalloc( ( ( ( size_t ) usStackDepth ) * sizeof( StackType_t ) ) ); /*lint !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack and this allocation is the stack. */
+
+                if( pxStack != NULL )
+                {
+                    /* Allocate space for the TCB. */
+                    pxNewTCB = ( TCB_t * ) pvPortMalloc( sizeof( TCB_t ) ); /*lint !e9087 !e9079 All values returned by pvPortMalloc() have at least the alignment required by the MCU's stack, and the first member of TCB_t is always a pointer to the task's stack. */
+
+                    if( pxNewTCB != NULL )
+                    {
+                        /* Store the stack location in the TCB. */
+                        pxNewTCB->pxStack = pxStack;
+                    }
+                    else
+                    {
+                        /* The stack cannot be used as the TCB was not created.  Free
+                         * it again. */
+                        vPortFree( pxStack );
+                    }
+                }
+                else
+                {
+                    pxNewTCB = NULL;
+                }
+            }
+            #endif /* portSTACK_GROWTH */
+
+            if( pxNewTCB != NULL )
+            {
+                #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e9029 !e731 Macro has been consolidated for readability reasons. */
+                {
+                    /* Tasks can be created statically or dynamically, so note this
+                     * task was created dynamically in case it is later deleted. */
+                    pxNewTCB->ucStaticallyAllocated = tskDYNAMICALLY_ALLOCATED_STACK_AND_TCB;
+                }
+                #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
+
+                prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, NULL, xCoreID );
+                prvAddNewTaskToReadyList( pxNewTCB );
+                xReturn = pdPASS;
+            }
+            else
+            {
+                xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY;
+            }
         }
-        #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */
-        return ret;
+        #endif /* CONFIG_FREERTOS_SMP */
+
+        return xReturn;
     }
 
-#endif /* CONFIG_FREERTOS_SMP */
+#endif /* ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) */
 /*----------------------------------------------------------*/
 
-#if ( CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
 
     TaskHandle_t xTaskCreateStaticPinnedToCore( TaskFunction_t pxTaskCode,
                                                 const char * const pcName,
@@ -85,95 +304,202 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt
                                                 StaticTask_t * const pxTaskBuffer,
                                                 const BaseType_t xCoreID )
     {
-        TaskHandle_t ret;
+        TaskHandle_t xReturn;
 
-        #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) )
+        #if CONFIG_FREERTOS_SMP
         {
-            /* Convert xCoreID into an affinity mask */
-            UBaseType_t uxCoreAffinityMask;
-
-            if( xCoreID == tskNO_AFFINITY )
+            /* If using Amazon SMP FreeRTOS. This function is just a wrapper around
+             * xTaskCreateStatic() or xTaskCreateStaticAffinitySet(). */
+            #if ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) )
             {
-                uxCoreAffinityMask = tskNO_AFFINITY;
+                /* Convert xCoreID into an affinity mask */
+                UBaseType_t uxCoreAffinityMask;
+
+                if( xCoreID == tskNO_AFFINITY )
+                {
+                    uxCoreAffinityMask = tskNO_AFFINITY;
+                }
+                else
+                {
+                    uxCoreAffinityMask = ( 1 << xCoreID );
+                }
+
+                xReturn = xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask );
             }
-            else
+            #else /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
             {
-                uxCoreAffinityMask = ( 1 << xCoreID );
+                xReturn = xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer );
             }
-
-            ret = xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask );
+            #endif /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */
         }
-        #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */
+        #else /* CONFIG_FREERTOS_SMP */
         {
-            ret = xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer );
+            TCB_t * pxNewTCB;
+
+            configASSERT( portVALID_STACK_MEM( puxStackBuffer ) );
+            configASSERT( portVALID_TCB_MEM( pxTaskBuffer ) );
+            configASSERT( ( ( xCoreID >= 0 ) && ( xCoreID < configNUM_CORES ) ) || ( xCoreID == tskNO_AFFINITY ) );
+
+            #if ( configASSERT_DEFINED == 1 )
+            {
+                /* Sanity check that the size of the structure used to declare a
+                 * variable of type StaticTask_t equals the size of the real task
+                 * structure. */
+                volatile size_t xSize = sizeof( StaticTask_t );
+                configASSERT( xSize == sizeof( TCB_t ) );
+                ( void ) xSize; /* Prevent lint warning when configASSERT() is not used. */
+            }
+            #endif /* configASSERT_DEFINED */
+
+            if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
+            {
+                /* The memory used for the task's TCB and stack are passed into this
+                 * function - use them. */
+                pxNewTCB = ( TCB_t * ) pxTaskBuffer; /*lint !e740 !e9087 Unusual cast is ok as the structures are designed to have the same alignment, and the size is checked by an assert. */
+                pxNewTCB->pxStack = ( StackType_t * ) puxStackBuffer;
+
+                #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) /*lint !e731 !e9029 Macro has been consolidated for readability reasons. */
+                {
+                    /* Tasks can be created statically or dynamically, so note this
+                     * task was created statically in case the task is later deleted. */
+                    pxNewTCB->ucStaticallyAllocated = tskSTATICALLY_ALLOCATED_STACK_AND_TCB;
+                }
+                #endif /* tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE */
+
+                prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, NULL, xCoreID );
+                prvAddNewTaskToReadyList( pxNewTCB );
+            }
+            else
+            {
+                xReturn = NULL;
+            }
         }
-        #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */
-        return ret;
+        #endif /* CONFIG_FREERTOS_SMP */
+
+        return xReturn;
     }
 
-#endif /* CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
+#endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
 /*----------------------------------------------------------*/
 
-/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
-
-#if CONFIG_FREERTOS_SMP
+#if ( configUSE_TIMERS == 1 )
 
-    TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID )
+/*
+ * In ESP-IDF, configUSE_TIMERS is always defined as 1 (i.e., not user configurable).
+ * However, tasks.c: vTaskStartScheduler() will always call xTimerCreateTimerTask()
+ * if ( configUSE_TIMERS == 1 ), thus causing the linker to link timers.c and
+ * wasting some memory (due to the timer task being created)/
+ *
+ * If we provide a weak version of xTimerCreateTimerTask(), this version will be
+ * compiled if the application does not call any other FreeRTOS timer functions.
+ * Thus we can save some text/RAM as timers.c will not be linked and the timer
+ * task never created.
+ */
+    BaseType_t __attribute__( ( weak ) ) xTimerCreateTimerTask( void )
     {
-        TaskHandle_t xTaskHandleTemp;
-
-        assert( xCoreID >= 0 && xCoreID < configNUM_CORES );
-        taskENTER_CRITICAL();
-        xTaskHandleTemp = ( TaskHandle_t ) pxCurrentTCBs[ xCoreID ];
-        taskEXIT_CRITICAL();
-        return xTaskHandleTemp;
+        return pdPASS;
     }
 
-#endif /* CONFIG_FREERTOS_SMP */
+#endif /* configUSE_TIMERS */
 /*----------------------------------------------------------*/
 
-#if CONFIG_FREERTOS_SMP
+/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
+
+#if ( INCLUDE_xTaskGetIdleTaskHandle == 1 )
 
     TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
     {
-        assert( xCoreID >= 0 && xCoreID < configNUM_CORES );
+        configASSERT( xCoreID >= 0 && xCoreID < configNUM_CORES );
+        configASSERT( ( xIdleTaskHandle[ xCoreID ] != NULL ) );
         return ( TaskHandle_t ) xIdleTaskHandle[ xCoreID ];
     }
 
-#endif /* CONFIG_FREERTOS_SMP */
+#endif /* INCLUDE_xTaskGetIdleTaskHandle */
 /*----------------------------------------------------------*/
 
-#if CONFIG_FREERTOS_SMP
+#if ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) )
 
-    BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
+    TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID )
     {
-        taskENTER_CRITICAL();
-        UBaseType_t uxCoreAffinityMask;
-        #if ( configUSE_CORE_AFFINITY == 1 && configNUM_CORES > 1 )
-            TCB_t * pxTCB = prvGetTCBFromHandle( xTask );
-            uxCoreAffinityMask = pxTCB->uxCoreAffinityMask;
-        #else
-            uxCoreAffinityMask = tskNO_AFFINITY;
-        #endif
-        taskEXIT_CRITICAL();
-        BaseType_t ret;
+        TaskHandle_t xReturn;
 
-        /* If the task is not pinned to a particular core, treat it as tskNO_AFFINITY */
-        if( uxCoreAffinityMask & ( uxCoreAffinityMask - 1 ) ) /* If more than one bit set */
+        #if CONFIG_FREERTOS_SMP
         {
-            ret = tskNO_AFFINITY;
+            xReturn = xTaskGetCurrentTaskHandleCPU( xCoreID );
         }
-        else
+        #else /* CONFIG_FREERTOS_SMP */
         {
-            int index_plus_one = __builtin_ffs( uxCoreAffinityMask );
-            assert( index_plus_one >= 1 );
-            ret = index_plus_one - 1;
+            if( xCoreID < configNUM_CORES )
+            {
+                xReturn = pxCurrentTCB[ xCoreID ];
+            }
+            else
+            {
+                xReturn = NULL;
+            }
         }
+        #endif /* CONFIG_FREERTOS_SMP */
 
-        return ret;
+        return xReturn;
     }
 
-#endif /* CONFIG_FREERTOS_SMP */
+#endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
+/*----------------------------------------------------------*/
+
+BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
+{
+    BaseType_t xReturn;
+
+    #if ( configNUM_CORES > 1 )
+    {
+        #if CONFIG_FREERTOS_SMP
+            UBaseType_t uxCoreAffinityMask;
+
+            /* Get the core affinity mask and covert it to an ID */
+            uxCoreAffinityMask = vTaskCoreAffinityGet( xTask );
+
+            /* If the task is not pinned to a particular core, treat it as tskNO_AFFINITY */
+            if( uxCoreAffinityMask & ( uxCoreAffinityMask - 1 ) ) /* If more than one bit set */
+            {
+                xReturn = tskNO_AFFINITY;
+            }
+            else
+            {
+                int iIndexPlusOne = __builtin_ffs( uxCoreAffinityMask );
+                assert( iIndexPlusOne >= 1 );
+                xReturn = iIndexPlusOne - 1;
+            }
+        #else /* CONFIG_FREERTOS_SMP */
+            TCB_t * pxTCB;
+
+            pxTCB = prvGetTCBFromHandle( xTask );
+            /* Simply read the xCoreID member of the TCB */
+            taskENTER_CRITICAL( &xKernelLock );
+            xReturn = pxTCB->xCoreID;
+            taskEXIT_CRITICAL_ISR( &xKernelLock );
+        #endif /* CONFIG_FREERTOS_SMP */
+    }
+    #else /* configNUM_CORES > 1 */
+    {
+        /* Single-core. Just return a core ID of 0 */
+        xReturn = 0;
+    }
+    #endif /* configNUM_CORES > 1 */
+
+    return xReturn;
+}
+/*----------------------------------------------------------*/
+
+uint8_t * pxTaskGetStackStart( TaskHandle_t xTask )
+{
+    TCB_t * pxTCB;
+    uint8_t * uxReturn;
+
+    pxTCB = prvGetTCBFromHandle( xTask );
+    uxReturn = ( uint8_t * ) pxTCB->pxStack;
+
+    return uxReturn;
+}
 /*----------------------------------------------------------*/
 
 #if ( INCLUDE_vTaskPrioritySet == 1 )
@@ -390,26 +716,61 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt
 
 /* --------------------------------------------- TLSP Deletion Callbacks -------------------------------------------- */
 
-#if ( CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
+#if CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
 
     void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet,
                                                           BaseType_t xIndex,
                                                           void * pvValue,
                                                           TlsDeleteCallbackFunction_t pvDelCallback )
     {
-        /* Verify that the offsets of pvThreadLocalStoragePointers and pvDummy15 match. */
-        /* pvDummy15 is part of the StaticTask_t struct and is used to access the TLSPs */
-        /* while deletion. */
-        _Static_assert( offsetof( StaticTask_t, pvDummy15 ) == offsetof( TCB_t, pvThreadLocalStoragePointers ), "Offset of pvDummy15 must match the offset of pvThreadLocalStoragePointers" );
+        /* If TLSP deletion callbacks are enabled, then configNUM_THREAD_LOCAL_STORAGE_POINTERS
+         * is doubled in size so that the latter half of the pvThreadLocalStoragePointers
+         * stores the deletion callbacks. */
+        if( xIndex < ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) )
+        {
+            TCB_t * pxTCB;
+
+            #if ( configNUM_CORES > 1 )
+            {
+                /* For SMP, we need a critical section as another core could also
+                 * update this task's TLSP at the same time. */
+                #if CONFIG_FREERTOS_SMP
+                {
+                    taskENTER_CRITICAL();
+                }
+                #else /* CONFIG_FREERTOS_SMP */
+                {
+                    taskENTER_CRITICAL( &xKernelLock );
+                }
+                #endif /* CONFIG_FREERTOS_SMP */
+            }
+            #endif /* configNUM_CORES > 1 */
+
+            pxTCB = prvGetTCBFromHandle( xTaskToSet );
+            /* Store the TLSP by indexing the first half of the array */
+            pxTCB->pvThreadLocalStoragePointers[ xIndex ] = pvValue;
 
-        /*Set the local storage pointer first */
-        vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue );
+            /* Store the TLSP deletion callback by indexing the second half
+             * of the array. */
+            pxTCB->pvThreadLocalStoragePointers[ ( xIndex + ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ) ] = ( void * ) pvDelCallback;
 
-        /*Set the deletion callback at an offset of configNUM_THREAD_LOCAL_STORAGE_POINTERS/2 */
-        vTaskSetThreadLocalStoragePointer( xTaskToSet, ( xIndex + ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ), pvDelCallback );
+            #if ( configNUM_CORES > 1 )
+            {
+                #if CONFIG_FREERTOS_SMP
+                {
+                    taskEXIT_CRITICAL();
+                }
+                #else /* CONFIG_FREERTOS_SMP */
+                {
+                    taskEXIT_CRITICAL( &xKernelLock );
+                }
+                #endif /* CONFIG_FREERTOS_SMP */
+            }
+            #endif /* configNUM_CORES > 1 */
+        }
     }
 
-#endif /* CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
+#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
 /*----------------------------------------------------------*/
 
 /* ----------------------------------------------------- Newlib ----------------------------------------------------- */

+ 105 - 0
components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h

@@ -20,6 +20,111 @@
 #endif
 /* *INDENT-ON* */
 
+/*------------------------------------------------------------------------------
+ * KERNEL CONTROL (PRIVATE)
+ *----------------------------------------------------------------------------*/
+
+/*
+ * The following macros are convenience macros used to account for different
+ * thread safety behavior between Vanilla FreeRTOS (i.e., single-core) and ESP-IDF
+ * FreeRTOS (i.e., multi-core SMP).
+ *
+ * For thread saftey...
+ *
+ * - Vanilla FreeRTOS will use the following for thread safety (depending on situation)
+ *      - `vTaskSuspendAll()`/`xTaskResumeAll()` for non-deterministic operations
+ *      - Critical sections or disabling interrupts for deterministic operations
+ * - ESP-IDF FreeRTOS will always use critical sections (determinism is not supported)
+ *
+ * [refactor-todo]: Define these locally in each kernel source file (IDF-8161)
+ */
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+    #define prvENTER_CRITICAL_OR_SUSPEND_ALL( x )    taskENTER_CRITICAL( ( x ) )
+    #define prvEXIT_CRITICAL_OR_RESUME_ALL( x )      ( { taskEXIT_CRITICAL( ( x ) ); pdFALSE; } )
+    #define prvENTER_CRITICAL_OR_MASK_ISR( pxLock, uxInterruptStatus ) \
+    {                                                                  \
+        taskENTER_CRITICAL_ISR( ( pxLock ) );                          \
+        ( void ) ( uxInterruptStatus );                                \
+    }
+    #define prvEXIT_CRITICAL_OR_UNMASK_ISR( pxLock, uxInterruptStatus ) \
+    {                                                                   \
+        taskEXIT_CRITICAL_ISR( ( pxLock ) );                            \
+        ( void ) ( uxInterruptStatus );                                 \
+    }
+
+#elif ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES == 1 ) )
+
+    #define prvENTER_CRITICAL_OR_SUSPEND_ALL( x )    ( { vTaskSuspendAll(); ( void ) ( x ); } )
+    #define prvEXIT_CRITICAL_OR_RESUME_ALL( x )      xTaskResumeAll()
+    #define prvENTER_CRITICAL_OR_MASK_ISR( pxLock, uxInterruptStatus )  \
+    {                                                                   \
+        ( uxInterruptStatus ) = portSET_INTERRUPT_MASK_FROM_ISR();      \
+        ( void ) ( pxLock );                                            \
+    }
+    #define prvEXIT_CRITICAL_OR_UNMASK_ISR( pxLock, uxInterruptStatus )  \
+    {                                                                    \
+        portCLEAR_INTERRUPT_MASK_FROM_ISR( ( uxInterruptStatus ) );      \
+        ( void ) ( pxLock );                                             \
+    }
+
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES == 1 ) ) */
+
+/*
+ * In ESP-IDF FreeRTOS (i.e., multi-core SMP) uses spinlocks to protect different
+ * groups of data. This function is a wrapper to take the "xKernelLock" spinlock
+ * of tasks.c.
+ *
+ * This lock is taken whenever any of the kernel's data structures are
+ * accessed/modified, such as when adding/removing tasks to/from the delayed
+ * task list or various event lists.
+ *
+ * In more cases, kernel data structures are not accessed by functions outside
+ * tasks.c. Thus, all accesses of the kernel data structures inside tasks.c will
+ * handle the taking/releasing of the "xKerneLock".
+ *
+ * This functions is meant to be called by xEventGroupSetBits() and
+ * vEventGroupDelete() as both those functions will directly access event lists
+ * (which are kernel data structures). Thus, a wrapper function must be provided
+ * to take/release the "xKernelLock" from outside tasks.c.
+ *
+ * [refactor-todo]: Extern this locally in event groups (IDF-8161)
+ */
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+    void prvTakeKernelLock( void );
+    void prvReleaseKernelLock( void );
+
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+
+#if ( CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+/**
+ * @brief Workaround for non-thread safe multi-core OS startup (see IDF-4524)
+ *
+ * This function must be called with interrupts disabled on all cores other than
+ * core 0 during startup.
+ */
+    void prvStartSchedulerOtherCores( void );
+
+#endif /* ( CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+
+/*
+ * In ESP-IDF FreeRTOS (i.e., multi-core SMP), core 0 manages the the FreeRTOS
+ * tick count. Thus only core 0 calls xTaskIncrementTick().
+ *
+ * However, all other cores also receive a periodic tick interrupt. Thus all
+ * other cores should call this function instead.
+ *
+ * This function will check if the current core requires time slicing, and also
+ * call the application tick hook. However, the tick count will remain unchanged.
+ */
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+
+    BaseType_t xTaskIncrementTickOtherCores( void );
+
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
+
 /*------------------------------------------------------------------------------
  * TASK UTILITIES (PRIVATE)
  *----------------------------------------------------------------------------*/

+ 63 - 61
components/freertos/esp_additions/include/freertos/idf_additions.h

@@ -31,26 +31,23 @@
 #endif
 /* *INDENT-ON* */
 
-/* -------------------------------------------------- Task Creation ---------------------------------------------------
-* Task Creation APIs added by ESP-IDF
-*
-* Todo: Move IDF FreeRTOS SMP related additions to this header as well (see IDF-7201)
-* Todo: Add these SMP related additions to docs once they are combined with IDF FreeRTOS.
-* ------------------------------------------------------------------------------------------------------------------ */
+/* -------------------------------------------------- Task Creation ------------------------------------------------- */
 
-#if ( CONFIG_FREERTOS_SMP && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) )
+#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 )
 
 /**
  * @brief Create a new task that is pinned to a particular core
  *
- * Helper function to create a task that is pinned to a particular core, or has
- * no affinity. In other words, the created task will have an affinity mask of:
- * - (1 << xCoreID) if it is pinned to a particular core
- * - Set to tskNO_AFFINITY if it has no affinity
+ * This function is similar to xTaskCreate(), but allows the creation of a pinned
+ * task. The task's pinned core is specified by the xCoreID argument. If xCoreID
+ * is set to tskNO_AFFINITY, then the task is unpinned and can run on any core.
+ *
+ * @note If ( configNUM_CORES == 1 ), xCoreID is ignored.
  *
  * @param pxTaskCode Pointer to the task entry function.
  * @param pcName A descriptive name for the task.
- * @param usStackDepth The size of the task stack.
+ * @param ulStackDepth The size of the task stack specified as the NUMBER OF
+ * BYTES. Note that this differs from vanilla FreeRTOS.
  * @param pvParameters Pointer that will be used as the parameter for the task
  * being created.
  * @param uxPriority The priority at which the task should run.
@@ -63,24 +60,30 @@
  */
     BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
                                         const char * const pcName,
-                                        const uint32_t usStackDepth,
+                                        const uint32_t ulStackDepth,
                                         void * const pvParameters,
                                         UBaseType_t uxPriority,
                                         TaskHandle_t * const pxCreatedTask,
                                         const BaseType_t xCoreID );
 
-#endif /* ( CONFIG_FREERTOS_SMP && ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) ) */
+#endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 
-#if ( CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) )
+#if ( configSUPPORT_STATIC_ALLOCATION == 1 )
 
 /**
  * @brief Create a new static task that is pinned to a particular core
  *
- * This funciton is the static equivalent of xTaskCreatePinnedToCore().
+ * This function is similar to xTaskCreateStatic(), but allows the creation of a
+ * pinned task. The task's pinned core is specified by the xCoreID argument. If
+ * xCoreID is set to tskNO_AFFINITY, then the task is unpinned and can run on any
+ * core.
+ *
+ * @note If ( configNUM_CORES == 1 ), xCoreID is ignored.
  *
  * @param pxTaskCode Pointer to the task entry function.
  * @param pcName A descriptive name for the task.
- * @param ulStackDepth The size of the task stack.
+ * @param ulStackDepth The size of the task stack specified as the NUMBER OF
+ * BYTES. Note that this differs from vanilla FreeRTOS.
  * @param pvParameters Pointer that will be used as the parameter for the task
  * being created.
  * @param uxPriority The priority at which the task should run.
@@ -101,47 +104,37 @@
                                                 StaticTask_t * const pxTaskBuffer,
                                                 const BaseType_t xCoreID );
 
-#endif /* ( CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */
-
-/* ------------------------------------------------- Task Utilities ----------------------------------------------------
- * Todo: Move IDF FreeRTOS SMP related additions to this header as well (see IDF-7201)
- * ------------------------------------------------------------------------------------------------------------------ */
+#endif /* configSUPPORT_STATIC_ALLOCATION */
 
-#if CONFIG_FREERTOS_SMP
+/* ------------------------------------------------- Task Utilities ------------------------------------------------- */
 
 /**
- * @brief Get the handle of the task running on a certain core
- *
- * Because of the nature of SMP processing, there is no guarantee that this
- * value will still be valid on return and should only be used for debugging
- * purposes.
+ * @brief Get the handle of idle task for the given core.
  *
- * [refactor-todo] Mark this function as deprecated, call
- * xTaskGetCurrentTaskHandleCPU() instead
+ * [refactor-todo] See if this needs to be deprecated (IDF-8145)
  *
+ * @note If CONFIG_FREERTOS_SMP is enabled, please call xTaskGetIdleTaskHandle()
+ * instead.
  * @param xCoreID The core to query
- * @return Handle of the current task running on the queried core
+ * @return Handle of the idle task for the queried core
  */
-    TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID );
-
-#endif /* CONFIG_FREERTOS_SMP */
-
-#if CONFIG_FREERTOS_SMP
+TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID );
 
 /**
- * @brief Get the handle of idle task for the given CPU.
+ * @brief Get the handle of the task currently running on a certain core
+ *
+ * Because of the nature of SMP processing, there is no guarantee that this
+ * value will still be valid on return and should only be used for debugging
+ * purposes.
  *
- * [refactor-todo] Mark this function as deprecated, call
- * xTaskGetIdleTaskHandle() instead
+ * [refactor-todo] See if this needs to be deprecated (IDF-8145)
  *
+ * @note If CONFIG_FREERTOS_SMP is enabled, please call xTaskGetCurrentTaskHandleCPU()
+ * instead.
  * @param xCoreID The core to query
- * @return Handle of the idle task for the queried core
+ * @return Handle of the current task running on the queried core
  */
-    TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID );
-
-#endif /* CONFIG_FREERTOS_SMP */
-
-#if CONFIG_FREERTOS_SMP
+TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID );
 
 /**
  * @brief Get the current core affinity of a particular task
@@ -150,35 +143,44 @@
  * pinned to a particular core, the core ID is returned. If the task is not
  * pinned to a particular core, tskNO_AFFINITY is returned.
  *
- * [refactor-todo] Mark this function as deprecated, call vTaskCoreAffinityGet()
- * instead
+ * If CONFIG_FREERTOS_UNICORE is enabled, this function simply returns 0.
+ *
+ * [refactor-todo] See if this needs to be deprecated (IDF-8145)(IDF-8164)
  *
+ * @note If CONFIG_FREERTOS_SMP is enabled, please call vTaskCoreAffinityGet()
+ * instead.
  * @param xTask The task to query
  * @return The tasks coreID or tskNO_AFFINITY
  */
-    BaseType_t xTaskGetAffinity( TaskHandle_t xTask );
+BaseType_t xTaskGetAffinity( TaskHandle_t xTask );
 
-#endif /* CONFIG_FREERTOS_SMP */
-
-/* --------------------------------------------- TLSP Deletion Callbacks -----------------------------------------------
- * TLSP Deletion Callback API Additions
+/**
+ * Returns the start of the stack associated with xTask.
  *
- * Todo: Move IDF FreeRTOS TLSP Deletion Callback related additions to this header as well (see IDF-7201)
- * Todo: Add these SMP related additions to docs once they are combined with IDF FreeRTOS.
- * ------------------------------------------------------------------------------------------------------------------ */
+ * Returns the lowest stack memory address, regardless of whether the stack
+ * grows up or down.
+ *
+ * [refactor-todo] Change return type to StackType_t (IDF-8158)
+ *
+ * @param xTask Handle of the task associated with the stack returned.
+ * Set xTask to NULL to return the stack of the calling task.
+ *
+ * @return A pointer to the start of the stack.
+ */
+uint8_t * pxTaskGetStackStart( TaskHandle_t xTask );
+
+/* --------------------------------------------- TLSP Deletion Callbacks -------------------------------------------- */
 
-#if ( CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
+#if CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
 
 /**
  * Prototype of local storage pointer deletion callback.
  */
     typedef void (* TlsDeleteCallbackFunction_t)( int,
                                                   void * );
+#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
 
-#endif /* ( CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS ) */
-
-
-#if ( CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
+#if CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
 
 /**
  * Set local storage pointer and deletion callback.
@@ -207,7 +209,7 @@
                                                           void * pvValue,
                                                           TlsDeleteCallbackFunction_t pvDelCallback );
 
-#endif /* ( CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS ) */
+#endif /* CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
 
 /* -------------------------------------------- Creation With Memory Caps ----------------------------------------------
  * Helper functions to create various FreeRTOS objects (e.g., queues, semaphores) with specific memory capabilities

+ 0 - 14
components/freertos/linker.lf

@@ -109,12 +109,9 @@ entries:
         #   - "xTaskGetSchedulerState"
         #   - "xTaskGetTickCount"
         # --------------------------------------------------------------------------------------------------------------
-        tasks:xTaskCreateStaticPinnedToCore (default)
-        tasks:xTaskCreatePinnedToCore (default)
         tasks:prvInitialiseNewTask (default)
         tasks:prvAddNewTaskToReadyList (default)
         tasks:vTaskDelete (default)
-        tasks:vTaskDelayUntil (default)
         tasks:xTaskDelayUntil (default)
         tasks:vTaskDelay (default)
         tasks:eTaskGetState (default)
@@ -133,7 +130,6 @@ entries:
         tasks:prvSearchForNameWithinSingleList (default)
         tasks:xTaskGetHandle (default)
         tasks:xTaskGetIdleTaskHandle (default)
-        tasks:xTaskGetIdleTaskHandleForCPU (default)
         tasks:xTaskAbortDelay (default)
         # IDF-6410 Application tags not supported yet
         #tasks:vTaskSetApplicationTaskTag (default)
@@ -142,30 +138,22 @@ entries:
         tasks:vTaskPlaceOnEventList (default)
         tasks:vTaskPlaceOnUnorderedEventList (default)
         tasks:vTaskPlaceOnEventListRestricted (default)
-        if FREERTOS_UNICORE = n:
-            tasks:vTaskTakeKernelLock (default)
-            tasks:vTaskReleaseKernelLock (default)
         tasks:vTaskRemoveFromUnorderedEventList (default)
         tasks:vTaskSetTimeOutState (default)
         tasks:vTaskInternalSetTimeOutState (default)
         tasks:xTaskCheckForTimeOut (default)
         tasks:vTaskMissedYield (default)
         tasks:prvIdleTask (default)
-        if FREERTOS_TLSP_DELETION_CALLBACKS = y:
-            tasks:vTaskSetThreadLocalStoragePointerAndDelCallback (default)
         if FREERTOS_THREAD_LOCAL_STORAGE_POINTERS != 0:
             tasks:vTaskSetThreadLocalStoragePointer (default)
             tasks:pvTaskGetThreadLocalStoragePointer (default)
         tasks:prvInitialiseTaskLists (default)
         tasks:prvCheckTasksWaitingTermination (default)
-        tasks:xTaskGetAffinity (default)
         tasks:prvTaskCheckFreeStackSpace (default)
         tasks:uxTaskGetStackHighWaterMark2 (default)
         tasks:uxTaskGetStackHighWaterMark (default)
-        tasks:pxTaskGetStackStart (default)
         tasks:prvDeleteTCB (default)
         tasks:xTaskGetCurrentTaskHandle (default)
-        tasks:xTaskGetCurrentTaskHandleForCPU (default)
         tasks:xTaskPriorityInherit (default)
         tasks:xTaskPriorityDisinherit (default)
         tasks:vTaskPriorityDisinheritAfterTimeout (default)
@@ -176,9 +164,7 @@ entries:
             tasks:vTaskGetRunTimeStats (default)
         tasks:uxTaskResetEventItemValue (default)
         tasks:pvTaskIncrementMutexHeldCount (default)
-        tasks:ulTaskNotifyTake (default)
         tasks:ulTaskGenericNotifyTake (default)
-        tasks:xTaskNotifyWait (default)
         tasks:xTaskGenericNotifyWait (default)
         tasks:xTaskGenericNotify (default)
         tasks:xTaskGenericNotifyStateClear (default)

+ 14 - 3
components/freertos/linker_common.lf

@@ -17,14 +17,19 @@ entries:
     #     to always keep it in IRAM
     # ------------------------------------------------------------------------------------------------------------------
     if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
+        # Kernel Control
+        if FREERTOS_SMP = n && FREERTOS_UNICORE = n:
+            tasks:prvTakeKernelLock (default)
+            tasks:prvReleaseKernelLock (default)
         # Task Creation
-        if FREERTOS_SMP = y:
-            tasks:xTaskCreatePinnedToCore (default)
-            tasks:xTaskCreateStaticPinnedToCore (default)
+        tasks:xTaskCreatePinnedToCore (default)
+        tasks:xTaskCreateStaticPinnedToCore (default)
         # Task Utilities
         tasks:xTaskGetCurrentTaskHandleForCPU (default)
         tasks:xTaskGetIdleTaskHandleForCPU (default)
+        tasks:xTaskGetCurrentTaskHandleForCPU (default)
         tasks:xTaskGetAffinity (default)
+        tasks:pxTaskGetStackStart (default)
         tasks:prvTaskPriorityRaise (default)
         tasks:prvTaskPriorityRestore (default)
         # TLSP Deletion Callbacks
@@ -36,6 +41,12 @@ entries:
         tasks:pxTaskGetNext (default)
         tasks:uxTaskGetSnapshotAll (default)
 
+    # ------------------------------------------------------------------------------------------------------------------
+    # freertos_compatibility.c
+    # Placement Rules: Functions always in flash as they are never called from an ISR
+    # ------------------------------------------------------------------------------------------------------------------
+    freertos_compatibility (default)
+
     # ------------------------------------------------------------------------------------------------------------------
     # idf_additions.c
     # Placement Rules: Functions always in flash as they are never called from an ISR

+ 4 - 0
components/freertos/port_systick.c

@@ -9,6 +9,10 @@
 #include <stdlib.h>
 #include "FreeRTOS.h"
 #include "task.h"
+#if ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) )
+    /* Required for xTaskIncrementTickOtherCores() */
+    #include "esp_private/freertos_idf_additions_priv.h"
+#endif /* ( !CONFIG_FREERTOS_SMP && ( configNUM_CORES > 1 ) ) */
 
 #if CONFIG_FREERTOS_SYSTICK_USES_CCOUNT
     #if CONFIG_FREERTOS_CORETIMER_0

+ 4 - 0
components/freertos/test_apps/freertos/port/test_fpu_in_isr.c

@@ -115,11 +115,13 @@ static void unpinned_task(void *arg)
     vTaskSuspendAll();
 #endif
     // Check that the task is unpinned
+#if !CONFIG_FREERTOS_UNICORE
 #if CONFIG_FREERTOS_SMP
     TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
 #else
     TEST_ASSERT_EQUAL(tskNO_AFFINITY, xTaskGetAffinity(NULL));
 #endif
+#endif // !CONFIG_FREERTOS_UNICORE
 
     // Allocate an ISR to use the FPU
     intr_handle_t isr_handle;
@@ -130,11 +132,13 @@ static void unpinned_task(void *arg)
     esp_intr_free(isr_handle);
 
     // Task should remain unpinned after the ISR uses the FPU
+#if !CONFIG_FREERTOS_UNICORE
 #if CONFIG_FREERTOS_SMP
     TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
 #else
     TEST_ASSERT_EQUAL(tskNO_AFFINITY, xTaskGetAffinity(NULL));
 #endif
+#endif // !CONFIG_FREERTOS_UNICORE
     // Reenable scheduling/preemption
 #if CONFIG_FREERTOS_SMP
     vTaskPreemptionEnable(NULL);

+ 4 - 0
components/freertos/test_apps/freertos/port/test_fpu_in_task.c

@@ -137,11 +137,13 @@ static void unpinned_task(void *arg)
 #endif
     BaseType_t cur_core_num = xPortGetCoreID();
     // Check that the task is unpinned
+#if !CONFIG_FREERTOS_UNICORE
 #if CONFIG_FREERTOS_SMP
     TEST_ASSERT_EQUAL(tskNO_AFFINITY, vTaskCoreAffinityGet(NULL));
 #else
     TEST_ASSERT_EQUAL(tskNO_AFFINITY, xTaskGetAffinity(NULL));
 #endif
+#endif // !CONFIG_FREERTOS_UNICORE
 
     /*
     Use the FPU
@@ -156,11 +158,13 @@ static void unpinned_task(void *arg)
     // We allow a 0.1% delta on the final result in case of any loss of precision from floating point calculations
     TEST_ASSERT_FLOAT_WITHIN(0.00256f, 2.56f, test_float);
 
+#if !CONFIG_FREERTOS_UNICORE
 #if CONFIG_FREERTOS_SMP
     TEST_ASSERT_EQUAL(1 << cur_core_num, vTaskCoreAffinityGet(NULL));
 #else
     TEST_ASSERT_EQUAL(cur_core_num, xTaskGetAffinity(NULL));
 #endif
+#endif // !CONFIG_FREERTOS_UNICORE
     // Reenable scheduling/preemption
 #if CONFIG_FREERTOS_SMP
     vTaskPreemptionEnable(NULL);

+ 3 - 0
tools/mocks/freertos/CMakeLists.txt

@@ -12,6 +12,8 @@ set(include_dirs
     "${original_freertos_dir}/config/include/freertos" # For "FreeRTOSConfig.h"
     "${original_freertos_dir}/config/linux/include" # For "freertos/FreeRTOSConfig_arch.h"
     "${original_freertos_dir}/esp_additions/include"
+    # Required because CMock tries to include "idf_additions.h" instead of "freertos/idf_additions.h"
+    "${original_freertos_dir}/esp_additions/include/freertos"
     "${kernel_dir}/portable/linux/include" # For "freertos/portmacro.h"
     "${kernel_dir}/include/freertos" # this is due to the way includes are generated in CMock (without freertos prefix)
 )
@@ -19,6 +21,7 @@ set(include_dirs
 idf_component_mock(INCLUDE_DIRS ${include_dirs}
     REQUIRES esp_common
     MOCK_HEADER_FILES
+    ${original_freertos_dir}/esp_additions/include/freertos/idf_additions.h
     ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/task.h
     ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/event_groups.h
     ${original_freertos_dir}/FreeRTOS-Kernel/include/freertos/queue.h)