From 5227616e570dc815e7015fe305ac0db15f11c56d Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 16:48:30 +0800 Subject: [PATCH 01/10] refactor(freertos/idf): Implicitly include idf_additions.h from FreeRTOS.h This commit adds an implicit inclusion of `idf_additions.h` to `FreeRTOS.h` in preparation for moving some IDf specific API to `idf_additions.h`. This implict inclusion allows existing code to be continue using these relocated APIs without any changes in header inclusions. Also removed "#pragma once" directive from "freertos_tasks_c_additions.h" since that header is included as a source file. --- .../include/freertos/FreeRTOS.h | 30 +++++++++++++++---- .../include/freertos/task.h | 2 -- .../include/freertos/FreeRTOS.h | 27 ++++++++++++++++- .../freertos_tasks_c_additions.h | 2 -- 4 files changed, 50 insertions(+), 11 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h index deef64198a..24dbd653df 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/FreeRTOS.h +++ b/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 */ diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h index 41d44b5107..4d3158e535 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h @@ -3321,8 +3321,6 @@ core 0 during startup. void vTaskStartSchedulerOtherCores( void ); #endif // configNUM_CORES > 1 -#include "freertos/idf_additions.h" - #endif //ESP_PLATFORM /* *INDENT-OFF* */ diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/FreeRTOS.h b/components/freertos/FreeRTOS-Kernel/include/freertos/FreeRTOS.h index e6b6916ab9..5ddfdafdb7 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/FreeRTOS.h +++ b/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 */ diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index 6dbff63ead..560c57898a 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -4,8 +4,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -#pragma once - #include "sdkconfig.h" #include "freertos/idf_additions.h" #if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT From 6c66018d5bff5853746568d1fb7a4bfdc4ebb439 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 16:52:25 +0800 Subject: [PATCH 02/10] refactor(freertos/smp): Move vTaskStartSchedulerOtherCores() to API additions to headers - Move vTaskStartSchedulerOtherCores() - implementation to freertos_tasks_c_additions.h - declaration to freertos_idf_additions_priv.h as API is private - Rename vTaskStartSchedulerOtherCores() -> prvStartSchedulerOtherCores() to indicate that the function is private. --- .../FreeRTOS-Kernel-SMP/include/freertos/task.h | 17 ----------------- .../FreeRTOS-Kernel-SMP/portable/xtensa/port.c | 3 ++- components/freertos/FreeRTOS-Kernel-SMP/tasks.c | 11 ----------- .../esp_additions/freertos_tasks_c_additions.h | 16 ++++++++++++++++ .../esp_private/freertos_idf_additions_priv.h | 16 ++++++++++++++++ 5 files changed, 34 insertions(+), 29 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h index 4d3158e535..7f436bcb0d 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel-SMP/include/freertos/task.h @@ -3306,23 +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 - -#endif //ESP_PLATFORM - /* *INDENT-OFF* */ #ifdef __cplusplus } diff --git a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c b/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c index ad5fa3dbd9..cb84e80931 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/portable/xtensa/port.c +++ b/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 diff --git a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c b/components/freertos/FreeRTOS-Kernel-SMP/tasks.c index b7a8f03253..254fc0a830 100644 --- a/components/freertos/FreeRTOS-Kernel-SMP/tasks.c +++ b/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 diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index 560c57898a..9a3beeb6b7 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -31,6 +31,22 @@ _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 ) ) + +/* + * 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 ) ) */ +/*----------------------------------------------------------*/ + /* -------------------------------------------------- Task Creation ------------------------------------------------- */ #if CONFIG_FREERTOS_SMP diff --git a/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h b/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h index 2670a46ad2..0318f166d1 100644 --- a/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h +++ b/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h @@ -20,6 +20,22 @@ #endif /* *INDENT-ON* */ +/*------------------------------------------------------------------------------ + * KERNEL CONTROL (PRIVATE) + *----------------------------------------------------------------------------*/ + +#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 ) ) */ + /*------------------------------------------------------------------------------ * TASK UTILITIES (PRIVATE) *----------------------------------------------------------------------------*/ From 8825c8dda90f4f2dcc2bdb670c58b80eded54800 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 02:04:51 +0800 Subject: [PATCH 03/10] refactor(freertos/idf): Move critical section API to IDF addition headers - The following IDF API additions are moved to freertos_tasks_c_additions.h (implementation) and freertos_idf_additions_priv.h (declaration) as APIs are private. This reduces the source code difference from upstream. - prvENTER_CRITICAL_OR_SUSPEND_ALL() - prvEXIT_CRITICAL_OR_RESUME_ALL() - prvENTER_CRITICAL_OR_MASK_ISR() - prvEXIT_CRITICAL_OR_UNMASK_ISR() - vTaskTakeKernelLock() - vTaskReleaseKernelLock() - Rename vTask[Take/Release]KernelLock() to prv[Take/Release]KernelLock() to indicate that the this API is private. --- .../freertos/FreeRTOS-Kernel/event_groups.c | 16 ++-- .../FreeRTOS-Kernel/include/freertos/task.h | 48 +----------- components/freertos/FreeRTOS-Kernel/queue.c | 2 + .../freertos/FreeRTOS-Kernel/stream_buffer.c | 2 + components/freertos/FreeRTOS-Kernel/tasks.c | 18 +---- components/freertos/FreeRTOS-Kernel/timers.c | 2 + .../freertos_tasks_c_additions.h | 28 +++++++ .../esp_private/freertos_idf_additions_priv.h | 73 +++++++++++++++++++ components/freertos/linker.lf | 3 - components/freertos/linker_common.lf | 4 + 10 files changed, 124 insertions(+), 72 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/event_groups.c b/components/freertos/FreeRTOS-Kernel/event_groups.c index 8b1b184b17..019b85e3b2 100644 --- a/components/freertos/FreeRTOS-Kernel/event_groups.c +++ b/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 ) ); diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h index a50fb78d07..c316608ee8 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h +++ b/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 */ /* @@ -3439,32 +3439,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 @@ -3577,26 +3551,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. diff --git a/components/freertos/FreeRTOS-Kernel/queue.c b/components/freertos/FreeRTOS-Kernel/queue.c index 69da28f732..1be5631a0b 100644 --- a/components/freertos/FreeRTOS-Kernel/queue.c +++ b/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" diff --git a/components/freertos/FreeRTOS-Kernel/stream_buffer.c b/components/freertos/FreeRTOS-Kernel/stream_buffer.c index d67f091cba..0973bdbbf1 100644 --- a/components/freertos/FreeRTOS-Kernel/stream_buffer.c +++ b/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 diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 9487213e2a..51fc9b47b6 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/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 @@ -4008,20 +4010,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 +4020,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 diff --git a/components/freertos/FreeRTOS-Kernel/timers.c b/components/freertos/FreeRTOS-Kernel/timers.c index d68ab1e371..7e9db6968d 100644 --- a/components/freertos/FreeRTOS-Kernel/timers.c +++ b/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. diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index 9a3beeb6b7..02aeb66949 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -33,6 +33,34 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt /* ------------------------------------------------- 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 ) ) /* diff --git a/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h b/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h index 0318f166d1..7791d81996 100644 --- a/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h +++ b/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h @@ -24,6 +24,79 @@ * 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 ) ) /** diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index f23fac8bfe..23ff389917 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -142,9 +142,6 @@ 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) diff --git a/components/freertos/linker_common.lf b/components/freertos/linker_common.lf index 0756332bbb..ee61f1d03c 100644 --- a/components/freertos/linker_common.lf +++ b/components/freertos/linker_common.lf @@ -17,6 +17,10 @@ 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) From db9d9658f9d4ca770d62c9f498e68190680d8cd0 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Mon, 28 Aug 2023 21:55:27 +0800 Subject: [PATCH 04/10] refactor(freertos/idf): Move xTaskIncrementTickOtherCores() to IDF additition headers This commit moves xTaskIncrementTickOtherCores() to freertos_tasks_c_additions.h and freertos_idf_additions_priv.h (as API is private). This reduces the code differences cmpared to upstream FreeRTOS. --- .../FreeRTOS-Kernel/include/freertos/task.h | 14 --- components/freertos/FreeRTOS-Kernel/tasks.c | 84 ------------------ .../freertos_tasks_c_additions.h | 86 +++++++++++++++++++ .../esp_private/freertos_idf_additions_priv.h | 16 ++++ components/freertos/port_systick.c | 4 + 5 files changed, 106 insertions(+), 98 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h index c316608ee8..7e898b2d32 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h @@ -3485,20 +3485,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. diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 51fc9b47b6..c55fa6a927 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -3369,90 +3369,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 ) diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index 02aeb66949..7f45a52219 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -75,6 +75,92 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt #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 diff --git a/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h b/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h index 7791d81996..4f38f5ec99 100644 --- a/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h +++ b/components/freertos/esp_additions/include/esp_private/freertos_idf_additions_priv.h @@ -109,6 +109,22 @@ #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) *----------------------------------------------------------------------------*/ diff --git a/components/freertos/port_systick.c b/components/freertos/port_systick.c index eedafc750b..73bd161108 100644 --- a/components/freertos/port_systick.c +++ b/components/freertos/port_systick.c @@ -9,6 +9,10 @@ #include #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 From 0db40f9e6cbb4cdf632728f491205be311a63c0b Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 02:07:52 +0800 Subject: [PATCH 05/10] refactor(freertos/idf): Move IDF task utility functions to API addition headers This commit combines various task utility API additions in IDF FreeRTOS and with their Amazon SMP FreeRTOS addition counterparts. The folloiwng functions have been moved to freertos_tasks_c_additions.h and idf_additions.h as these API are considered public: - xTaskGetCurrentTaskHandleForCPU() - xTaskGetIdleTaskHandleForCPU() - xTaskGetAffinity() - pxTaskGetStackStart() Also fixed in missing #if macros when vTaskCoreAffinityGet() is called in Amazon SMP FreerTOS tests. --- .../FreeRTOS-Kernel/include/freertos/task.h | 41 ------ components/freertos/FreeRTOS-Kernel/tasks.c | 45 +------ .../config/include/freertos/FreeRTOSConfig.h | 2 - .../freertos_tasks_c_additions.h | 117 ++++++++++++------ .../include/freertos/idf_additions.h | 70 ++++++----- components/freertos/linker.lf | 4 - components/freertos/linker_common.lf | 2 + .../test_apps/freertos/port/test_fpu_in_isr.c | 4 + .../freertos/port/test_fpu_in_task.c | 4 + 9 files changed, 126 insertions(+), 163 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h index 7e898b2d32..0cffaf5e5c 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h @@ -1950,21 +1950,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 @@ -3439,32 +3424,6 @@ BaseType_t xTaskCatchUpTicks( TickType_t xTicksToCatchUp ) PRIVILEGED_FUNCTION; *----------------------------------------------------------*/ /** @cond !DOC_EXCLUDE_HEADER_SECTION */ -/* - * 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 diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index c55fa6a927..98de5987ff 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -3016,12 +3016,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 */ /*----------------------------------------------------------*/ @@ -4677,16 +4671,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, @@ -4809,20 +4793,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 ) @@ -4910,7 +4880,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 ) { @@ -4924,19 +4894,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 ) ) */ /*-----------------------------------------------------------*/ diff --git a/components/freertos/config/include/freertos/FreeRTOSConfig.h b/components/freertos/config/include/freertos/FreeRTOSConfig.h index 6a7ccf6d19..35faea2145 100644 --- a/components/freertos/config/include/freertos/FreeRTOSConfig.h +++ b/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 ----------------------- */ diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index 7f45a52219..b37933d79d 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -244,64 +244,101 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt /* ------------------------------------------------- Task Utilities ------------------------------------------------- */ -#if CONFIG_FREERTOS_SMP - - TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID ) - { - TaskHandle_t xTaskHandleTemp; - - assert( xCoreID >= 0 && xCoreID < configNUM_CORES ); - taskENTER_CRITICAL(); - xTaskHandleTemp = ( TaskHandle_t ) pxCurrentTCBs[ xCoreID ]; - taskEXIT_CRITICAL(); - return xTaskHandleTemp; - } - -#endif /* CONFIG_FREERTOS_SMP */ -/*----------------------------------------------------------*/ - -#if CONFIG_FREERTOS_SMP +#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 ) diff --git a/components/freertos/esp_additions/include/freertos/idf_additions.h b/components/freertos/esp_additions/include/freertos/idf_additions.h index 41ca5ee14a..3d9574973b 100644 --- a/components/freertos/esp_additions/include/freertos/idf_additions.h +++ b/components/freertos/esp_additions/include/freertos/idf_additions.h @@ -103,45 +103,35 @@ #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) - * ------------------------------------------------------------------------------------------------------------------ */ - -#if CONFIG_FREERTOS_SMP +/* ------------------------------------------------- Task Utilities ------------------------------------------------- */ /** - * @brief Get the handle of the task running on a certain core + * @brief Get the handle of idle task for the given core. + * + * [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 idle task for the queried core + */ +TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID ); + +/** + * @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 - * xTaskGetCurrentTaskHandleCPU() 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 current task running on the queried core */ - TaskHandle_t xTaskGetCurrentTaskHandleForCPU( BaseType_t xCoreID ); - -#endif /* CONFIG_FREERTOS_SMP */ - -#if CONFIG_FREERTOS_SMP - -/** - * @brief Get the handle of idle task for the given CPU. - * - * [refactor-todo] Mark this function as deprecated, call - * xTaskGetIdleTaskHandle() instead - * - * @param xCoreID The core to query - * @return Handle of the idle task for 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,15 +140,31 @@ * 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 */ +/** + * Returns the start of the stack associated with xTask. + * + * 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 ----------------------------------------------- * TLSP Deletion Callback API Additions diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 23ff389917..5b2c149d18 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -133,7 +133,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) @@ -155,14 +154,11 @@ entries: 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) diff --git a/components/freertos/linker_common.lf b/components/freertos/linker_common.lf index ee61f1d03c..4a19d9764d 100644 --- a/components/freertos/linker_common.lf +++ b/components/freertos/linker_common.lf @@ -28,7 +28,9 @@ entries: # 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 diff --git a/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c b/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c index 2917f3c0b7..3ca6e90046 100644 --- a/components/freertos/test_apps/freertos/port/test_fpu_in_isr.c +++ b/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); diff --git a/components/freertos/test_apps/freertos/port/test_fpu_in_task.c b/components/freertos/test_apps/freertos/port/test_fpu_in_task.c index a829ed9adf..6bde01e388 100644 --- a/components/freertos/test_apps/freertos/port/test_fpu_in_task.c +++ b/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); From 5de6a9aff6a6028adfdaa6472e34b9d551610fe6 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Mon, 28 Aug 2023 23:45:46 +0800 Subject: [PATCH 06/10] refactor(freertos/idf): Move compatibility functions This function moves ulTaskNotifyTake()/xTaskNotifyWait() from IDF FreeRTOS `tasks.c` to `freertos_compatibility.c`. These functions were kept for pre-compiled library compatibilty. Move them reduces the kernel source code difference when compared to upstream FreeRTOS. --- components/freertos/CMakeLists.txt | 6 +-- components/freertos/FreeRTOS-Kernel/tasks.c | 31 -------------- .../esp_additions/freertos_compatibility.c | 42 +++++++++++++++++++ components/freertos/linker.lf | 3 -- components/freertos/linker_common.lf | 6 +++ 5 files changed, 49 insertions(+), 39 deletions(-) diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 17e6749d1e..9ac34ce96a 100644 --- a/components/freertos/CMakeLists.txt +++ b/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 diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 98de5987ff..26e27dcb28 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -1530,15 +1530,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 ) @@ -5633,16 +5624,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 ) @@ -5715,18 +5696,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, diff --git a/components/freertos/esp_additions/freertos_compatibility.c b/components/freertos/esp_additions/freertos_compatibility.c index 66211af185..d56ae4e2d5 100644 --- a/components/freertos/esp_additions/freertos_compatibility.c +++ b/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 ); +} diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index 5b2c149d18..d36885354e 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -114,7 +114,6 @@ entries: tasks:prvInitialiseNewTask (default) tasks:prvAddNewTaskToReadyList (default) tasks:vTaskDelete (default) - tasks:vTaskDelayUntil (default) tasks:xTaskDelayUntil (default) tasks:vTaskDelay (default) tasks:eTaskGetState (default) @@ -169,9 +168,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) diff --git a/components/freertos/linker_common.lf b/components/freertos/linker_common.lf index 4a19d9764d..eedac43a07 100644 --- a/components/freertos/linker_common.lf +++ b/components/freertos/linker_common.lf @@ -42,6 +42,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 From 7b4dba4ffdd6cf0b6ba5bd78aa6d36ae0f68f9d9 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 00:36:03 +0800 Subject: [PATCH 07/10] refactor(freertos/idf): Move vTaskSetThreadLocalStoragePointerAndDelCallback() This commit moves vTaskSetThreadLocalStoragePointerAndDelCallback() from `tasks.c`/`task.h` to `freertos_tasks_c_additions.h`/`idf_additions.h`. --- .../FreeRTOS-Kernel/include/freertos/task.h | 34 -------- components/freertos/FreeRTOS-Kernel/tasks.c | 85 ++++++------------- .../freertos_tasks_c_additions.h | 57 ++++++++++--- .../include/freertos/idf_additions.h | 17 ++-- components/freertos/linker.lf | 2 - 5 files changed, 75 insertions(+), 120 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h index 0cffaf5e5c..05603c02e9 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h @@ -2024,7 +2024,6 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL BaseType_t xIndex, void * pvValue ) PRIVILEGED_FUNCTION; - /** * Get local storage pointer specific to the given task. * @@ -2041,39 +2040,6 @@ configSTACK_DEPTH_TYPE uxTaskGetStackHighWaterMark2( TaskHandle_t xTask ) PRIVIL 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 ) diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 26e27dcb28..a5d4eb7cd0 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -4331,79 +4331,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 ) + { + /* TLSP Deletion Callbacks are enabled. Call the TLSPDC funciton + * instead with a NULL callback. */ + vTaskSetThreadLocalStoragePointerAndDelCallback( xTaskToSet, xIndex, pvValue, NULL ); + } + #else /* 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 ) + #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 */ - } - } - - void vTaskSetThreadLocalStoragePointer( TaskHandle_t xTaskToSet, - BaseType_t xIndex, - void * pvValue ) - { - vTaskSetThreadLocalStoragePointerAndDelCallback( xTaskToSet, xIndex, pvValue, ( TlsDeleteCallbackFunction_t ) NULL ); - } - - - #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 */ /*-----------------------------------------------------------*/ diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index b37933d79d..b88947abf0 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -21,7 +21,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. */ @@ -555,26 +555,61 @@ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ) /* --------------------------------------------- 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; - /*Set the local storage pointer first */ - vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue ); + #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 */ - /*Set the deletion callback at an offset of configNUM_THREAD_LOCAL_STORAGE_POINTERS/2 */ - vTaskSetThreadLocalStoragePointer( xTaskToSet, ( xIndex + ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ), pvDelCallback ); + 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 * ) 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 ----------------------------------------------------- */ diff --git a/components/freertos/esp_additions/include/freertos/idf_additions.h b/components/freertos/esp_additions/include/freertos/idf_additions.h index 3d9574973b..94fc012a15 100644 --- a/components/freertos/esp_additions/include/freertos/idf_additions.h +++ b/components/freertos/esp_additions/include/freertos/idf_additions.h @@ -166,25 +166,18 @@ BaseType_t xTaskGetAffinity( TaskHandle_t xTask ); */ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ); -/* --------------------------------------------- TLSP Deletion Callbacks ----------------------------------------------- - * TLSP Deletion Callback API Additions - * - * 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. - * ------------------------------------------------------------------------------------------------------------------ */ +/* --------------------------------------------- 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. @@ -213,7 +206,7 @@ uint8_t * pxTaskGetStackStart( TaskHandle_t xTask ); 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 diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index d36885354e..c0a663b0c5 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -146,8 +146,6 @@ entries: 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) From a5f9a2505e1b424adc158cc17e8b2ffe252a0082 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 00:42:37 +0800 Subject: [PATCH 08/10] refactor(freertos/idf): Remove application hook prototypes The following application hook protoypes are defined in task.h from FreeRTOS V10.4.0 onwwards and no longer need to be declared in tasks.c, thus have been removed: - vApplicationStackOverflowHook() - vApplicationTickHook() - vApplicationGetIdleTaskMemory() --- components/freertos/FreeRTOS-Kernel/tasks.c | 22 --------------------- 1 file changed, 22 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index a5d4eb7cd0..da7bdab9de 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -504,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. --------------------------------*/ /** From e612db7d327853630f5ff083a78f6402483d55f4 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Tue, 29 Aug 2023 00:59:20 +0800 Subject: [PATCH 09/10] refactor(freertos/idf): Move weak xTimerCreateTimerTask() to IDF additions header A weak xTimerCreateTimerTask() was added to tasks.c as a workaround in ESP-IDF in order to prevent timers.c from being linked when unused. This commit moves that workaround to `freertos_tasks_c_additions.h` --- components/freertos/FreeRTOS-Kernel/tasks.c | 6 ------ .../freertos_tasks_c_additions.h | 21 +++++++++++++++++++ 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index da7bdab9de..592af7071e 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -6304,9 +6304,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; -} diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index b88947abf0..c9c64b1964 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -242,6 +242,27 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt #endif /* CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ +#if ( configUSE_TIMERS == 1 ) + +/* + * 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 ) + { + return pdPASS; + } + +#endif /* configUSE_TIMERS */ +/*----------------------------------------------------------*/ + /* ------------------------------------------------- Task Utilities ------------------------------------------------- */ #if ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) From 035423eb371f3cdd2c9894611777ca573a704e02 Mon Sep 17 00:00:00 2001 From: Darian Leung Date: Thu, 31 Aug 2023 22:24:06 +0800 Subject: [PATCH 10/10] refactor(freertos/idf): Move task creation "PinnedToCore" API to addition headers This commit moves/merges the IDF FreeRTOS "PinnedToCore" task creation functions from tasks.c/task.h to idf_additions.h/freertos_task_c_additions.h. Also updated FreeRTOS Mock component to provide mocks for "idf_additions.h" headers for our mock tests. --- .../FreeRTOS-Kernel/include/freertos/task.h | 260 ++++-------------- components/freertos/FreeRTOS-Kernel/tasks.c | 152 ---------- .../freertos_tasks_c_additions.h | 212 +++++++++++--- .../include/freertos/idf_additions.h | 39 +-- components/freertos/linker.lf | 2 - components/freertos/linker_common.lf | 5 +- tools/mocks/freertos/CMakeLists.txt | 3 + 7 files changed, 257 insertions(+), 416 deletions(-) diff --git a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h index 05603c02e9..22992e565b 100644 --- a/components/freertos/FreeRTOS-Kernel/include/freertos/task.h +++ b/components/freertos/FreeRTOS-Kernel/include/freertos/task.h @@ -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 */ /** diff --git a/components/freertos/FreeRTOS-Kernel/tasks.c b/components/freertos/FreeRTOS-Kernel/tasks.c index 592af7071e..3459a572a7 100644 --- a/components/freertos/FreeRTOS-Kernel/tasks.c +++ b/components/freertos/FreeRTOS-Kernel/tasks.c @@ -708,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, @@ -865,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, diff --git a/components/freertos/esp_additions/freertos_tasks_c_additions.h b/components/freertos/esp_additions/freertos_tasks_c_additions.h index c9c64b1964..f93d36e04a 100644 --- a/components/freertos/esp_additions/freertos_tasks_c_additions.h +++ b/components/freertos/esp_additions/freertos_tasks_c_additions.h @@ -5,6 +5,7 @@ */ #include "sdkconfig.h" +#include "esp_assert.h" #include "freertos/idf_additions.h" #if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT #include "freertos/task_snapshot.h" @@ -163,7 +164,7 @@ _Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSt /* -------------------------------------------------- Task Creation ------------------------------------------------- */ -#if CONFIG_FREERTOS_SMP +#if ( configSUPPORT_DYNAMIC_ALLOCATION == 1 ) BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode, const char * const pcName, @@ -173,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 /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + { + xReturn = xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ); + } + #endif /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + } + #else /* CONFIG_FREERTOS_SMP */ + { + 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 { - uxCoreAffinityMask = ( 1 << xCoreID ); + xReturn = errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY; } + } + #endif /* CONFIG_FREERTOS_SMP */ - ret = xTaskCreateAffinitySet( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, uxCoreAffinityMask, pxCreatedTask ); - } - #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */ - { - ret = xTaskCreate( pxTaskCode, pcName, usStackDepth, pvParameters, uxPriority, pxCreatedTask ); - } - #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */ - return ret; + 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, @@ -213,33 +304,82 @@ _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 /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + { + xReturn = xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer ); + } + #endif /* ( ( configNUM_CORES > 1 ) && ( configUSE_CORE_AFFINITY == 1 ) ) */ + } + #else /* CONFIG_FREERTOS_SMP */ + { + 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 { - uxCoreAffinityMask = ( 1 << xCoreID ); + xReturn = NULL; } + } + #endif /* CONFIG_FREERTOS_SMP */ - ret = xTaskCreateStaticAffinitySet( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer, uxCoreAffinityMask ); - } - #else /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */ - { - ret = xTaskCreateStatic( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, puxStackBuffer, pxTaskBuffer ); - } - #endif /* ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) ) */ - return ret; + return xReturn; } -#endif /* CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ +#endif /* ( configSUPPORT_STATIC_ALLOCATION == 1 ) */ /*----------------------------------------------------------*/ #if ( configUSE_TIMERS == 1 ) diff --git a/components/freertos/esp_additions/include/freertos/idf_additions.h b/components/freertos/esp_additions/include/freertos/idf_additions.h index 94fc012a15..5f2e431bcf 100644 --- a/components/freertos/esp_additions/include/freertos/idf_additions.h +++ b/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,7 +104,7 @@ StaticTask_t * const pxTaskBuffer, const BaseType_t xCoreID ); -#endif /* ( CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) ) */ +#endif /* configSUPPORT_STATIC_ALLOCATION */ /* ------------------------------------------------- Task Utilities ------------------------------------------------- */ diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index c0a663b0c5..31a1b39cfb 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -109,8 +109,6 @@ entries: # - "xTaskGetSchedulerState" # - "xTaskGetTickCount" # -------------------------------------------------------------------------------------------------------------- - tasks:xTaskCreateStaticPinnedToCore (default) - tasks:xTaskCreatePinnedToCore (default) tasks:prvInitialiseNewTask (default) tasks:prvAddNewTaskToReadyList (default) tasks:vTaskDelete (default) diff --git a/components/freertos/linker_common.lf b/components/freertos/linker_common.lf index eedac43a07..d836cf4902 100644 --- a/components/freertos/linker_common.lf +++ b/components/freertos/linker_common.lf @@ -22,9 +22,8 @@ entries: 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) diff --git a/tools/mocks/freertos/CMakeLists.txt b/tools/mocks/freertos/CMakeLists.txt index 3e1e9bb68e..ac4c116a44 100644 --- a/tools/mocks/freertos/CMakeLists.txt +++ b/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)