|
|
@@ -1,5 +1,5 @@
|
|
|
/*
|
|
|
- * SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
|
|
+ * SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
|
|
|
*
|
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
|
*/
|
|
|
@@ -8,6 +8,9 @@
|
|
|
|
|
|
#include "sdkconfig.h"
|
|
|
#include "freertos/idf_additions.h"
|
|
|
+#if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT
|
|
|
+ #include "freertos/task_snapshot.h"
|
|
|
+#endif /* CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT */
|
|
|
#include "esp_private/freertos_idf_additions_priv.h"
|
|
|
|
|
|
/**
|
|
|
@@ -18,23 +21,401 @@
|
|
|
* additional API.
|
|
|
*/
|
|
|
|
|
|
-/* ------------------------------------------------- Static asserts ----------------------------------------------------
|
|
|
- *
|
|
|
- * ------------------------------------------------------------------------------------------------------------------ */
|
|
|
+/* ------------------------------------------------- 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.
|
|
|
*/
|
|
|
+_Static_assert( offsetof( StaticTask_t, pxDummy6 ) == offsetof( TCB_t, pxStack ) );
|
|
|
+_Static_assert( offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfStack ) );
|
|
|
+#if CONFIG_FREERTOS_SMP
|
|
|
+ _Static_assert( tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "CONFIG_FREERTOS_NO_AFFINITY must be the same as tskNO_AFFINITY" );
|
|
|
+#endif /* CONFIG_FREERTOS_SMP */
|
|
|
|
|
|
-_Static_assert(offsetof( StaticTask_t, pxDummy6 ) == offsetof( TCB_t, pxStack ));
|
|
|
-_Static_assert(offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfStack ));
|
|
|
+/* -------------------------------------------------- Task Creation ------------------------------------------------- */
|
|
|
|
|
|
-/* ----------------------------------------------------- Newlib --------------------------------------------------------
|
|
|
- *
|
|
|
- * ------------------------------------------------------------------------------------------------------------------ */
|
|
|
+#if CONFIG_FREERTOS_SMP
|
|
|
+
|
|
|
+ BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
|
|
|
+ const char * const pcName,
|
|
|
+ const uint32_t usStackDepth,
|
|
|
+ void * const pvParameters,
|
|
|
+ UBaseType_t uxPriority,
|
|
|
+ TaskHandle_t * const pxCreatedTask,
|
|
|
+ const BaseType_t xCoreID )
|
|
|
+ {
|
|
|
+ BaseType_t ret;
|
|
|
+
|
|
|
+ #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) )
|
|
|
+ {
|
|
|
+ /* Convert xCoreID into an affinity mask */
|
|
|
+ UBaseType_t uxCoreAffinityMask;
|
|
|
+
|
|
|
+ if( xCoreID == tskNO_AFFINITY )
|
|
|
+ {
|
|
|
+ uxCoreAffinityMask = tskNO_AFFINITY;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ uxCoreAffinityMask = ( 1 << xCoreID );
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* CONFIG_FREERTOS_SMP */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+#if ( CONFIG_FREERTOS_SMP && ( 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 )
|
|
|
+ {
|
|
|
+ TaskHandle_t ret;
|
|
|
+
|
|
|
+ #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) )
|
|
|
+ {
|
|
|
+ /* Convert xCoreID into an affinity mask */
|
|
|
+ UBaseType_t uxCoreAffinityMask;
|
|
|
+
|
|
|
+ if( xCoreID == tskNO_AFFINITY )
|
|
|
+ {
|
|
|
+ uxCoreAffinityMask = tskNO_AFFINITY;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ uxCoreAffinityMask = ( 1 << xCoreID );
|
|
|
+ }
|
|
|
+
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* CONFIG_FREERTOS_SMP && ( configSUPPORT_STATIC_ALLOCATION == 1 ) */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+/* ------------------------------------------------- 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
|
|
|
+
|
|
|
+ TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
|
|
|
+ {
|
|
|
+ assert( xCoreID >= 0 && xCoreID < configNUM_CORES );
|
|
|
+ return ( TaskHandle_t ) xIdleTaskHandle[ xCoreID ];
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* CONFIG_FREERTOS_SMP */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+#if CONFIG_FREERTOS_SMP
|
|
|
+
|
|
|
+ BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
|
|
|
+ {
|
|
|
+ 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;
|
|
|
+
|
|
|
+ /* 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 */
|
|
|
+ {
|
|
|
+ ret = tskNO_AFFINITY;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int index_plus_one = __builtin_ffs( uxCoreAffinityMask );
|
|
|
+ assert( index_plus_one >= 1 );
|
|
|
+ ret = index_plus_one - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* CONFIG_FREERTOS_SMP */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+#if ( INCLUDE_vTaskPrioritySet == 1 )
|
|
|
+
|
|
|
+ void prvTaskPriorityRaise( prvTaskSavedPriority_t * pxSavedPriority,
|
|
|
+ UBaseType_t uxNewPriority )
|
|
|
+ {
|
|
|
+ TCB_t * pxTCB;
|
|
|
+ UBaseType_t uxPriorityUsedOnEntry;
|
|
|
+
|
|
|
+ configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
|
|
|
+
|
|
|
+ /* Ensure the new priority is valid. */
|
|
|
+ if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
|
|
|
+ {
|
|
|
+ uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
|
|
|
+ }
|
|
|
+
|
|
|
+ #if CONFIG_FREERTOS_SMP
|
|
|
+ taskENTER_CRITICAL();
|
|
|
+ #else
|
|
|
+ taskENTER_CRITICAL( &xKernelLock );
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ pxTCB = prvGetTCBFromHandle( NULL );
|
|
|
+
|
|
|
+ #if ( configUSE_MUTEXES == 1 )
|
|
|
+ {
|
|
|
+ pxSavedPriority->uxPriority = pxTCB->uxPriority;
|
|
|
+ pxSavedPriority->uxBasePriority = pxTCB->uxBasePriority;
|
|
|
+
|
|
|
+ /* If uxNewPriority < uxBasePriority, then there is nothing else to
|
|
|
+ * do, as uxBasePriority is always <= uxPriority. */
|
|
|
+ if( uxNewPriority > pxTCB->uxBasePriority )
|
|
|
+ {
|
|
|
+ pxTCB->uxBasePriority = uxNewPriority;
|
|
|
+
|
|
|
+ /* Remember the task's current priority before attempting to
|
|
|
+ * change it. If the task's current priority is changed, it must
|
|
|
+ * be done so before moving the task between task lists) in order
|
|
|
+ * for the taskRESET_READY_PRIORITY() macro to function correctly. */
|
|
|
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
|
|
+
|
|
|
+ if( uxNewPriority > pxTCB->uxPriority )
|
|
|
+ {
|
|
|
+ pxTCB->uxPriority = uxNewPriority;
|
|
|
+
|
|
|
+ /* Only reset the event list item value if the value is not
|
|
|
+ * being used for anything else. */
|
|
|
+ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
|
+ {
|
|
|
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If the task is in the blocked or suspended list we need do
|
|
|
+ * nothing more than change its priority variable. However, if
|
|
|
+ * the task is in a ready list it needs to be removed and placed
|
|
|
+ * in the list appropriate to its new priority. */
|
|
|
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
|
+ {
|
|
|
+ /* The task is currently in its ready list - remove before
|
|
|
+ * adding it to its new ready list. As we are in a critical
|
|
|
+ * section we can do this even if the scheduler is suspended. */
|
|
|
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
|
+ {
|
|
|
+ /* It is known that the task is in its ready list so
|
|
|
+ * there is no need to check again and the port level
|
|
|
+ * reset macro can be called directly. */
|
|
|
+ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
|
|
|
+ }
|
|
|
+
|
|
|
+ prvAddTaskToReadyList( pxTCB );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #else /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
+ {
|
|
|
+ pxSavedPriority->uxPriority = pxTCB->uxPriority;
|
|
|
+
|
|
|
+ if( uxNewPriority > pxTCB->uxPriority )
|
|
|
+ {
|
|
|
+ vTaskPrioritySet( NULL, uxNewPriority );
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #endif /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
+ }
|
|
|
+ #if CONFIG_FREERTOS_SMP
|
|
|
+ taskEXIT_CRITICAL();
|
|
|
+ #else
|
|
|
+ taskEXIT_CRITICAL( &xKernelLock );
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* INCLUDE_vTaskPrioritySet == 1 */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+#if ( INCLUDE_vTaskPrioritySet == 1 )
|
|
|
+
|
|
|
+ void prvTaskPriorityRestore( prvTaskSavedPriority_t * pxSavedPriority )
|
|
|
+ {
|
|
|
+ TCB_t * pxTCB;
|
|
|
+ UBaseType_t uxNewPriority;
|
|
|
+ UBaseType_t uxPriorityUsedOnEntry;
|
|
|
+ UBaseType_t uxBasePriorityUsedOnEntry;
|
|
|
+ BaseType_t xYieldRequired = pdFALSE;
|
|
|
+
|
|
|
+ #if CONFIG_FREERTOS_SMP
|
|
|
+ taskENTER_CRITICAL();
|
|
|
+ #else
|
|
|
+ taskENTER_CRITICAL( &xKernelLock );
|
|
|
+ #endif
|
|
|
+ {
|
|
|
+ pxTCB = prvGetTCBFromHandle( NULL );
|
|
|
+
|
|
|
+ #if ( configUSE_MUTEXES == 1 )
|
|
|
+ {
|
|
|
+ /* If the saved uxBasePriority == the task's uxBasePriority, it means
|
|
|
+ * that prvTaskPriorityRaise() never raised the task's uxBasePriority.
|
|
|
+ * In that case, there is nothing else to do. */
|
|
|
+ if( pxSavedPriority->uxBasePriority != pxTCB->uxBasePriority )
|
|
|
+ {
|
|
|
+ uxBasePriorityUsedOnEntry = pxTCB->uxBasePriority;
|
|
|
+ pxTCB->uxBasePriority = pxSavedPriority->uxBasePriority;
|
|
|
+
|
|
|
+ /* Remember the task's current priority before attempting to
|
|
|
+ * change it. If the task's current priority is changed, it must
|
|
|
+ * be done so before moving the task between task lists in order
|
|
|
+ * for the taskRESET_READY_PRIORITY() macro to function correctly. */
|
|
|
+ uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
|
|
+
|
|
|
+ /* Check if the task inherited a priority after prvTaskPriorityRaise().
|
|
|
+ * If this is the case, there is nothing else to do. The priority
|
|
|
+ * will be restored when the task disinherits its priority. */
|
|
|
+ if( pxTCB->uxPriority == uxBasePriorityUsedOnEntry )
|
|
|
+ {
|
|
|
+ if( pxTCB->uxMutexesHeld == 0 )
|
|
|
+ {
|
|
|
+ /* The task may have inherited a priority before prvTaskPriorityRaise()
|
|
|
+ * then disinherited a priority after prvTaskPriorityRaise().
|
|
|
+ * Thus we need set the uxPriority to the saved base priority
|
|
|
+ * so that the task's priority gets restored to the priority
|
|
|
+ * before any inheritance or raising. */
|
|
|
+ pxTCB->uxPriority = pxSavedPriority->uxBasePriority;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* The task may have inherited a priority before prvTaskPriorityRaise()
|
|
|
+ * was called. Thus, we need to restore uxPriority to the
|
|
|
+ * "saved uxPriority" so that the task still retains that
|
|
|
+ * inherited priority. */
|
|
|
+ pxTCB->uxPriority = pxSavedPriority->uxPriority;
|
|
|
+ }
|
|
|
+
|
|
|
+ uxNewPriority = pxTCB->uxPriority;
|
|
|
+
|
|
|
+ if( uxNewPriority < uxPriorityUsedOnEntry )
|
|
|
+ {
|
|
|
+ /* Setting the priority of the running task down means
|
|
|
+ * there may now be another task of higher priority that
|
|
|
+ * is ready to execute. */
|
|
|
+ xYieldRequired = pdTRUE;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Only reset the event list item value if the value is not
|
|
|
+ * being used for anything else. */
|
|
|
+ if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
|
+ {
|
|
|
+ listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
+ }
|
|
|
+
|
|
|
+ /* If the task is in the blocked or suspended list we need do
|
|
|
+ * nothing more than change its priority variable. However, if
|
|
|
+ * the task is in a ready list it needs to be removed and placed
|
|
|
+ * in the list appropriate to its new priority. */
|
|
|
+ if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
|
+ {
|
|
|
+ /* The task is currently in its ready list - remove before
|
|
|
+ * adding it to its new ready list. As we are in a critical
|
|
|
+ * section we can do this even if the scheduler is suspended. */
|
|
|
+ if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
|
+ {
|
|
|
+ /* It is known that the task is in its ready list so
|
|
|
+ * there is no need to check again and the port level
|
|
|
+ * reset macro can be called directly. */
|
|
|
+ portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
|
|
|
+ }
|
|
|
+
|
|
|
+ prvAddTaskToReadyList( pxTCB );
|
|
|
+ }
|
|
|
+
|
|
|
+ if( xYieldRequired != pdFALSE )
|
|
|
+ {
|
|
|
+ taskYIELD_IF_USING_PREEMPTION();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ #else /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
+ {
|
|
|
+ vTaskPrioritySet( NULL, pxSavedPriority->uxPriority );
|
|
|
+ }
|
|
|
+ #endif /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
+ }
|
|
|
+ #if CONFIG_FREERTOS_SMP
|
|
|
+ taskEXIT_CRITICAL();
|
|
|
+ #else
|
|
|
+ taskEXIT_CRITICAL( &xKernelLock );
|
|
|
+ #endif
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* ( INCLUDE_vTaskPrioritySet == 1 ) */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+/* --------------------------------------------- TLSP Deletion Callbacks -------------------------------------------- */
|
|
|
+
|
|
|
+#if ( CONFIG_FREERTOS_SMP && 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" );
|
|
|
+
|
|
|
+ /*Set the local storage pointer first */
|
|
|
+ vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue );
|
|
|
+
|
|
|
+ /*Set the deletion callback at an offset of configNUM_THREAD_LOCAL_STORAGE_POINTERS/2 */
|
|
|
+ vTaskSetThreadLocalStoragePointer( xTaskToSet, ( xIndex + ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ), pvDelCallback );
|
|
|
+ }
|
|
|
+
|
|
|
+#endif /* CONFIG_FREERTOS_SMP && CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS */
|
|
|
+/*----------------------------------------------------------*/
|
|
|
+
|
|
|
+/* ----------------------------------------------------- Newlib ----------------------------------------------------- */
|
|
|
|
|
|
#if ( configUSE_NEWLIB_REENTRANT == 1 )
|
|
|
+
|
|
|
/**
|
|
|
* @brief Get reentrancy structure of the current task
|
|
|
*
|
|
|
@@ -44,51 +425,54 @@ _Static_assert(offsetof( StaticTask_t, pxDummy8 ) == offsetof( TCB_t, pxEndOfSta
|
|
|
*
|
|
|
* @return Pointer to a the (current taks's)/(globa) reent struct
|
|
|
*/
|
|
|
-struct _reent *__getreent(void)
|
|
|
-{
|
|
|
- // No lock needed because if this changes, we won't be running anymore.
|
|
|
- TCB_t *pxCurTask = xTaskGetCurrentTaskHandle();
|
|
|
- struct _reent *ret;
|
|
|
- if (pxCurTask == NULL) {
|
|
|
- // No task running. Return global struct.
|
|
|
- ret = _GLOBAL_REENT;
|
|
|
- } else {
|
|
|
- // We have a task; return its reentrant struct.
|
|
|
- ret = &pxCurTask->xNewLib_reent;
|
|
|
+ struct _reent * __getreent( void )
|
|
|
+ {
|
|
|
+ /* No lock needed because if this changes, we won't be running anymore. */
|
|
|
+ TCB_t * pxCurTask = xTaskGetCurrentTaskHandle();
|
|
|
+ struct _reent * ret;
|
|
|
+
|
|
|
+ if( pxCurTask == NULL )
|
|
|
+ {
|
|
|
+ /* No task running. Return global struct. */
|
|
|
+ ret = _GLOBAL_REENT;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* We have a task; return its reentrant struct. */
|
|
|
+ ret = &pxCurTask->xNewLib_reent;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
}
|
|
|
- return ret;
|
|
|
-}
|
|
|
-#endif // configUSE_NEWLIB_REENTRANT == 1
|
|
|
|
|
|
-/* -------------------------------------------------- Task Snapshot ----------------------------------------------------
|
|
|
- *
|
|
|
- * ------------------------------------------------------------------------------------------------------------------ */
|
|
|
+#endif /* configUSE_NEWLIB_REENTRANT == 1 */
|
|
|
|
|
|
-#include "freertos/task_snapshot.h"
|
|
|
+/* -------------------------------------------------- Task Snapshot ------------------------------------------------- */
|
|
|
|
|
|
/**
|
|
|
* @brief List of all task lists in FreeRTOS
|
|
|
*
|
|
|
* @note There are currently differing number of task list between SMP FreeRTOS and ESP-IDF FreeRTOS
|
|
|
*/
|
|
|
-static List_t *non_ready_task_lists[] = {
|
|
|
+static List_t * non_ready_task_lists[] = {
|
|
|
#ifdef CONFIG_FREERTOS_SMP
|
|
|
&xPendingReadyList,
|
|
|
- #else
|
|
|
- &xPendingReadyList[0],
|
|
|
+ #else /* CONFIG_FREERTOS_SMP */
|
|
|
+ &xPendingReadyList[ 0 ],
|
|
|
#ifndef CONFIG_FREERTOS_UNICORE
|
|
|
- &xPendingReadyList[1],
|
|
|
- #endif // CONFIG_FREERTOS_UNICORE
|
|
|
- #endif //CONFIG_FREERTOS_SMP
|
|
|
+ &xPendingReadyList[ 1 ],
|
|
|
+ #endif /* CONFIG_FREERTOS_UNICORE */
|
|
|
+ #endif /* CONFIG_FREERTOS_SMP */
|
|
|
&xDelayedTaskList1,
|
|
|
&xDelayedTaskList2,
|
|
|
- #if( INCLUDE_vTaskDelete == 1 )
|
|
|
+ #if ( INCLUDE_vTaskDelete == 1 )
|
|
|
&xTasksWaitingTermination,
|
|
|
#endif
|
|
|
- #if( INCLUDE_vTaskSuspend == 1 )
|
|
|
+ #if ( INCLUDE_vTaskSuspend == 1 )
|
|
|
&xSuspendedTaskList,
|
|
|
#endif
|
|
|
};
|
|
|
+/*----------------------------------------------------------*/
|
|
|
|
|
|
/**
|
|
|
* @brief Get the next task list to traverse
|
|
|
@@ -105,49 +489,57 @@ static List_t *non_ready_task_lists[] = {
|
|
|
* @param pxCurTaskList Previously traversed task list (or NULL if obtaining the first task list)
|
|
|
* @return List_t* The next task list to traverse (or NULL of all task lists have been traversed)
|
|
|
*/
|
|
|
-static List_t *pxGetNextTaskList(List_t *pxCurTaskList)
|
|
|
+static List_t * pxGetNextTaskList( List_t * pxCurTaskList )
|
|
|
{
|
|
|
- List_t *pxNextTaskList = NULL;
|
|
|
+ List_t * pxNextTaskList = NULL;
|
|
|
|
|
|
- // No Current List. Start from the highest priority ready task list
|
|
|
- if (pxCurTaskList == NULL)
|
|
|
+ /* No Current List. Start from the highest priority ready task list */
|
|
|
+ if( pxCurTaskList == NULL )
|
|
|
{
|
|
|
- pxNextTaskList = &pxReadyTasksLists[configMAX_PRIORITIES - 1];
|
|
|
+ pxNextTaskList = &pxReadyTasksLists[ configMAX_PRIORITIES - 1 ];
|
|
|
}
|
|
|
- // Current list is one of the ready task lists. Find the current priority, and return the next lower priority ready task list
|
|
|
- else if (pxCurTaskList >= &pxReadyTasksLists[0] && pxCurTaskList <= &pxReadyTasksLists[configMAX_PRIORITIES - 1] )
|
|
|
+ /* Current list is one of the ready task lists. Find the current priority, and return the next lower priority ready task list */
|
|
|
+ else if( ( pxCurTaskList >= &pxReadyTasksLists[ 0 ] ) && ( pxCurTaskList <= &pxReadyTasksLists[ configMAX_PRIORITIES - 1 ] ) )
|
|
|
{
|
|
|
- // Find the current priority
|
|
|
+ /* Find the current priority */
|
|
|
int cur_priority;
|
|
|
- for (cur_priority = configMAX_PRIORITIES - 1; cur_priority >= 0; cur_priority--) {
|
|
|
- if (pxCurTaskList == &pxReadyTasksLists[cur_priority]) {
|
|
|
+
|
|
|
+ for( cur_priority = configMAX_PRIORITIES - 1; cur_priority >= 0; cur_priority-- )
|
|
|
+ {
|
|
|
+ if( pxCurTaskList == &pxReadyTasksLists[ cur_priority ] )
|
|
|
+ {
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
- // Return the ready task list at (cur_priority - 1), or the pending ready task list
|
|
|
- if (cur_priority > 0)
|
|
|
+
|
|
|
+ /* Return the ready task list at (cur_priority - 1), or the pending ready task list */
|
|
|
+ if( cur_priority > 0 )
|
|
|
{
|
|
|
- pxNextTaskList = &pxReadyTasksLists[cur_priority - 1];
|
|
|
+ pxNextTaskList = &pxReadyTasksLists[ cur_priority - 1 ];
|
|
|
}
|
|
|
- // We've reached the end of the Ready Task Lists. We get the next list from the non-ready task lists
|
|
|
- else if (cur_priority == 0)
|
|
|
+ /* We've reached the end of the Ready Task Lists. We get the next list from the non-ready task lists */
|
|
|
+ else if( cur_priority == 0 )
|
|
|
{
|
|
|
- pxNextTaskList = non_ready_task_lists[0];
|
|
|
+ pxNextTaskList = non_ready_task_lists[ 0 ];
|
|
|
}
|
|
|
else
|
|
|
{
|
|
|
- abort(); // This should never occur
|
|
|
+ abort(); /* This should never occur */
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- // Current list is one of the non-ready task lists. Fetch the next non-ready task list
|
|
|
- if (pxNextTaskList == NULL) {
|
|
|
+ /* Current list is one of the non-ready task lists. Fetch the next non-ready task list */
|
|
|
+ if( pxNextTaskList == NULL )
|
|
|
+ {
|
|
|
int cur_list_idx;
|
|
|
- const int num_non_ready_task_lists = (sizeof(non_ready_task_lists) / sizeof(List_t *));
|
|
|
- // Note: - 1 so that if the current list is the last on non_ready_task_lists[], the next list will return NULL
|
|
|
- for (cur_list_idx = 0; cur_list_idx < num_non_ready_task_lists - 1; cur_list_idx++) {
|
|
|
- if (pxCurTaskList == non_ready_task_lists[cur_list_idx]) {
|
|
|
- pxNextTaskList = non_ready_task_lists[cur_list_idx + 1];
|
|
|
+ const int num_non_ready_task_lists = ( sizeof( non_ready_task_lists ) / sizeof( List_t * ) );
|
|
|
+
|
|
|
+ /* Note: - 1 so that if the current list is the last on non_ready_task_lists[], the next list will return NULL */
|
|
|
+ for( cur_list_idx = 0; cur_list_idx < num_non_ready_task_lists - 1; cur_list_idx++ )
|
|
|
+ {
|
|
|
+ if( pxCurTaskList == non_ready_task_lists[ cur_list_idx ] )
|
|
|
+ {
|
|
|
+ pxNextTaskList = non_ready_task_lists[ cur_list_idx + 1 ];
|
|
|
break;
|
|
|
}
|
|
|
}
|
|
|
@@ -155,99 +547,132 @@ static List_t *pxGetNextTaskList(List_t *pxCurTaskList)
|
|
|
|
|
|
return pxNextTaskList;
|
|
|
}
|
|
|
+/*----------------------------------------------------------*/
|
|
|
|
|
|
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask )
|
|
|
{
|
|
|
- TCB_t *pxTCB = (TCB_t *)pxTask;
|
|
|
- // Check current task is valid
|
|
|
- if (pxTCB != NULL && !portVALID_TCB_MEM(pxTCB)) {
|
|
|
+ TCB_t * pxTCB = ( TCB_t * ) pxTask;
|
|
|
+
|
|
|
+ /* Check current task is valid */
|
|
|
+ if( ( pxTCB != NULL ) && !portVALID_TCB_MEM( pxTCB ) )
|
|
|
+ {
|
|
|
return NULL;
|
|
|
}
|
|
|
|
|
|
- List_t *pxCurTaskList;
|
|
|
- const ListItem_t *pxCurListItem;
|
|
|
- if (pxTCB == NULL) {
|
|
|
- // Starting traversal for the first time
|
|
|
- pxCurTaskList = pxGetNextTaskList(NULL);
|
|
|
- pxCurListItem = listGET_END_MARKER(pxCurTaskList);
|
|
|
- } else {
|
|
|
- // Continuing traversal
|
|
|
- pxCurTaskList = listLIST_ITEM_CONTAINER(&pxTCB->xStateListItem);
|
|
|
+ List_t * pxCurTaskList;
|
|
|
+ const ListItem_t * pxCurListItem;
|
|
|
+
|
|
|
+ if( pxTCB == NULL )
|
|
|
+ {
|
|
|
+ /* Starting traversal for the first time */
|
|
|
+ pxCurTaskList = pxGetNextTaskList( NULL );
|
|
|
+ pxCurListItem = listGET_END_MARKER( pxCurTaskList );
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /* Continuing traversal */
|
|
|
+ pxCurTaskList = listLIST_ITEM_CONTAINER( &pxTCB->xStateListItem );
|
|
|
pxCurListItem = &pxTCB->xStateListItem;
|
|
|
}
|
|
|
|
|
|
- ListItem_t *pxNextListItem = NULL;
|
|
|
- if (pxCurListItem->pxNext == listGET_END_MARKER(pxCurTaskList)) {
|
|
|
- List_t *pxNextTaskList = pxGetNextTaskList(pxCurTaskList);
|
|
|
- while (pxNextTaskList != NULL) {
|
|
|
- if (!listLIST_IS_EMPTY(pxNextTaskList)) {
|
|
|
- // Get the first item in the next task list
|
|
|
- pxNextListItem = listGET_HEAD_ENTRY(pxNextTaskList);
|
|
|
+ ListItem_t * pxNextListItem = NULL;
|
|
|
+
|
|
|
+ if( pxCurListItem->pxNext == listGET_END_MARKER( pxCurTaskList ) )
|
|
|
+ {
|
|
|
+ List_t * pxNextTaskList = pxGetNextTaskList( pxCurTaskList );
|
|
|
+
|
|
|
+ while( pxNextTaskList != NULL )
|
|
|
+ {
|
|
|
+ if( !listLIST_IS_EMPTY( pxNextTaskList ) )
|
|
|
+ {
|
|
|
+ /* Get the first item in the next task list */
|
|
|
+ pxNextListItem = listGET_HEAD_ENTRY( pxNextTaskList );
|
|
|
break;
|
|
|
}
|
|
|
- // Task list is empty. Get the next task list
|
|
|
- pxNextTaskList = pxGetNextTaskList(pxNextTaskList);
|
|
|
+
|
|
|
+ /* Task list is empty. Get the next task list */
|
|
|
+ pxNextTaskList = pxGetNextTaskList( pxNextTaskList );
|
|
|
}
|
|
|
- } else {
|
|
|
- //There are still more items in the current task list. Get the next item
|
|
|
- pxNextListItem = listGET_NEXT(pxCurListItem);
|
|
|
}
|
|
|
+ else
|
|
|
+ {
|
|
|
+ /*There are still more items in the current task list. Get the next item */
|
|
|
+ pxNextListItem = listGET_NEXT( pxCurListItem );
|
|
|
+ }
|
|
|
+
|
|
|
+ TCB_t * pxNextTCB;
|
|
|
|
|
|
- TCB_t *pxNextTCB;
|
|
|
- if (pxNextListItem == NULL) {
|
|
|
+ if( pxNextListItem == NULL )
|
|
|
+ {
|
|
|
pxNextTCB = NULL;
|
|
|
- } else {
|
|
|
- pxNextTCB = (TCB_t *)listGET_LIST_ITEM_OWNER(pxNextListItem);
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ pxNextTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxNextListItem );
|
|
|
}
|
|
|
|
|
|
return pxNextTCB;
|
|
|
}
|
|
|
+/*----------------------------------------------------------*/
|
|
|
|
|
|
-BaseType_t vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot )
|
|
|
+BaseType_t vTaskGetSnapshot( TaskHandle_t pxTask,
|
|
|
+ TaskSnapshot_t * pxTaskSnapshot )
|
|
|
{
|
|
|
- if (portVALID_TCB_MEM(pxTask) == false || pxTaskSnapshot == NULL) {
|
|
|
+ if( ( portVALID_TCB_MEM( pxTask ) == false ) || ( pxTaskSnapshot == NULL ) )
|
|
|
+ {
|
|
|
return pdFALSE;
|
|
|
}
|
|
|
|
|
|
- TCB_t *pxTCB = (TCB_t *)pxTask;
|
|
|
+ TCB_t * pxTCB = ( TCB_t * ) pxTask;
|
|
|
pxTaskSnapshot->pxTCB = pxTCB;
|
|
|
- pxTaskSnapshot->pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack;
|
|
|
- pxTaskSnapshot->pxEndOfStack = (StackType_t *)pxTCB->pxEndOfStack;
|
|
|
+ pxTaskSnapshot->pxTopOfStack = ( StackType_t * ) pxTCB->pxTopOfStack;
|
|
|
+ pxTaskSnapshot->pxEndOfStack = ( StackType_t * ) pxTCB->pxEndOfStack;
|
|
|
return pdTRUE;
|
|
|
}
|
|
|
+/*----------------------------------------------------------*/
|
|
|
|
|
|
-UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArrayLength, UBaseType_t * const pxTCBSize )
|
|
|
+UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray,
|
|
|
+ const UBaseType_t uxArrayLength,
|
|
|
+ UBaseType_t * const pxTCBSize )
|
|
|
{
|
|
|
UBaseType_t uxArrayNumFilled = 0;
|
|
|
|
|
|
- //Traverse all of the tasks lists
|
|
|
- List_t *pxCurTaskList = pxGetNextTaskList(NULL); //Get the first task list
|
|
|
- while (pxCurTaskList != NULL && uxArrayNumFilled < uxArrayLength) {
|
|
|
- if (!listLIST_IS_EMPTY(pxCurTaskList)) {
|
|
|
- const ListItem_t *pxCurListItem;
|
|
|
- //Walk each task on the current task list
|
|
|
- pxCurListItem = listGET_HEAD_ENTRY(pxCurTaskList);
|
|
|
- while (pxCurListItem != listGET_END_MARKER(pxCurTaskList)) {
|
|
|
- TCB_t *pxTCB = (TCB_t *)listGET_LIST_ITEM_OWNER(pxCurListItem);
|
|
|
- vTaskGetSnapshot((TaskHandle_t)pxTCB, &pxTaskSnapshotArray[uxArrayNumFilled]);
|
|
|
+ /*Traverse all of the tasks lists */
|
|
|
+ List_t * pxCurTaskList = pxGetNextTaskList( NULL ); /*Get the first task list */
|
|
|
+
|
|
|
+ while( pxCurTaskList != NULL && uxArrayNumFilled < uxArrayLength )
|
|
|
+ {
|
|
|
+ if( !listLIST_IS_EMPTY( pxCurTaskList ) )
|
|
|
+ {
|
|
|
+ const ListItem_t * pxCurListItem;
|
|
|
+ /*Walk each task on the current task list */
|
|
|
+ pxCurListItem = listGET_HEAD_ENTRY( pxCurTaskList );
|
|
|
+
|
|
|
+ while( pxCurListItem != listGET_END_MARKER( pxCurTaskList ) )
|
|
|
+ {
|
|
|
+ TCB_t * pxTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER( pxCurListItem );
|
|
|
+ vTaskGetSnapshot( ( TaskHandle_t ) pxTCB, &pxTaskSnapshotArray[ uxArrayNumFilled ] );
|
|
|
uxArrayNumFilled++;
|
|
|
- if (!(uxArrayNumFilled < uxArrayLength)) {
|
|
|
+
|
|
|
+ if( !( uxArrayNumFilled < uxArrayLength ) )
|
|
|
+ {
|
|
|
break;
|
|
|
}
|
|
|
- pxCurListItem = listGET_NEXT(pxCurListItem);
|
|
|
+
|
|
|
+ pxCurListItem = listGET_NEXT( pxCurListItem );
|
|
|
}
|
|
|
}
|
|
|
- //Get the next task list
|
|
|
- pxCurTaskList = pxGetNextTaskList(pxCurTaskList);
|
|
|
+
|
|
|
+ /*Get the next task list */
|
|
|
+ pxCurTaskList = pxGetNextTaskList( pxCurTaskList );
|
|
|
}
|
|
|
|
|
|
- *pxTCBSize = sizeof(TCB_t);
|
|
|
+ *pxTCBSize = sizeof( TCB_t );
|
|
|
return uxArrayNumFilled;
|
|
|
}
|
|
|
+/*----------------------------------------------------------*/
|
|
|
|
|
|
-/* ----------------------------------------------------- OpenOCD -------------------------------------------------------
|
|
|
- *
|
|
|
- * ------------------------------------------------------------------------------------------------------------------ */
|
|
|
+/* ----------------------------------------------------- OpenOCD ---------------------------------------------------- */
|
|
|
|
|
|
#if CONFIG_FREERTOS_DEBUG_OCDAWARE
|
|
|
|
|
|
@@ -255,352 +680,30 @@ UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, co
|
|
|
* Debug param indexes. DO NOT change the order. OpenOCD uses the same indexes
|
|
|
* Entries in FreeRTOS_openocd_params must match the order of these indexes
|
|
|
*/
|
|
|
-enum {
|
|
|
- ESP_FREERTOS_DEBUG_TABLE_SIZE = 0,
|
|
|
- ESP_FREERTOS_DEBUG_TABLE_VERSION,
|
|
|
- ESP_FREERTOS_DEBUG_KERNEL_VER_MAJOR,
|
|
|
- ESP_FREERTOS_DEBUG_KERNEL_VER_MINOR,
|
|
|
- ESP_FREERTOS_DEBUG_KERNEL_VER_BUILD,
|
|
|
- ESP_FREERTOS_DEBUG_UX_TOP_USED_PIORITY,
|
|
|
- ESP_FREERTOS_DEBUG_PX_TOP_OF_STACK,
|
|
|
- ESP_FREERTOS_DEBUG_PC_TASK_NAME,
|
|
|
- /* New entries must be inserted here */
|
|
|
- ESP_FREERTOS_DEBUG_TABLE_END,
|
|
|
-};
|
|
|
-
|
|
|
-const DRAM_ATTR uint8_t FreeRTOS_openocd_params[ESP_FREERTOS_DEBUG_TABLE_END] = {
|
|
|
- ESP_FREERTOS_DEBUG_TABLE_END, /* table size */
|
|
|
- 1, /* table version */
|
|
|
- tskKERNEL_VERSION_MAJOR,
|
|
|
- tskKERNEL_VERSION_MINOR,
|
|
|
- tskKERNEL_VERSION_BUILD,
|
|
|
- configMAX_PRIORITIES - 1, /* uxTopUsedPriority */
|
|
|
- offsetof(TCB_t, pxTopOfStack), /* thread_stack_offset; */
|
|
|
- offsetof(TCB_t, pcTaskName), /* thread_name_offset; */
|
|
|
-};
|
|
|
-
|
|
|
-#endif // CONFIG_FREERTOS_DEBUG_OCDAWARE
|
|
|
-
|
|
|
-/* -------------------------------------------- FreeRTOS IDF API Additions ---------------------------------------------
|
|
|
- * FreeRTOS related API that were added by IDF
|
|
|
- * ------------------------------------------------------------------------------------------------------------------ */
|
|
|
-
|
|
|
-#if CONFIG_FREERTOS_SMP
|
|
|
-_Static_assert(tskNO_AFFINITY == CONFIG_FREERTOS_NO_AFFINITY, "CONFIG_FREERTOS_NO_AFFINITY must be the same as tskNO_AFFINITY");
|
|
|
-
|
|
|
-BaseType_t xTaskCreatePinnedToCore( TaskFunction_t pxTaskCode,
|
|
|
- const char * const pcName,
|
|
|
- const uint32_t usStackDepth,
|
|
|
- void * const pvParameters,
|
|
|
- UBaseType_t uxPriority,
|
|
|
- TaskHandle_t * const pxCreatedTask,
|
|
|
- const BaseType_t xCoreID)
|
|
|
-{
|
|
|
- BaseType_t ret;
|
|
|
- #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) )
|
|
|
- {
|
|
|
- // Convert xCoreID into an affinity mask
|
|
|
- UBaseType_t uxCoreAffinityMask;
|
|
|
- if (xCoreID == tskNO_AFFINITY) {
|
|
|
- uxCoreAffinityMask = tskNO_AFFINITY;
|
|
|
- } else {
|
|
|
- uxCoreAffinityMask = (1 << xCoreID);
|
|
|
- }
|
|
|
- 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;
|
|
|
-}
|
|
|
-
|
|
|
-#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)
|
|
|
-{
|
|
|
- TaskHandle_t ret;
|
|
|
- #if ( ( configUSE_CORE_AFFINITY == 1 ) && ( configNUM_CORES > 1 ) )
|
|
|
- {
|
|
|
- // Convert xCoreID into an affinity mask
|
|
|
- UBaseType_t uxCoreAffinityMask;
|
|
|
- if (xCoreID == tskNO_AFFINITY) {
|
|
|
- uxCoreAffinityMask = tskNO_AFFINITY;
|
|
|
- } else {
|
|
|
- uxCoreAffinityMask = (1 << xCoreID);
|
|
|
- }
|
|
|
- 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;
|
|
|
-}
|
|
|
-#endif /* configSUPPORT_STATIC_ALLOCATION */
|
|
|
-
|
|
|
-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;
|
|
|
-}
|
|
|
-
|
|
|
-TaskHandle_t xTaskGetIdleTaskHandleForCPU( BaseType_t xCoreID )
|
|
|
-{
|
|
|
- assert(xCoreID >= 0 && xCoreID < configNUM_CORES);
|
|
|
- return (TaskHandle_t) xIdleTaskHandle[xCoreID];
|
|
|
-}
|
|
|
-
|
|
|
-BaseType_t xTaskGetAffinity( TaskHandle_t xTask )
|
|
|
-{
|
|
|
- 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;
|
|
|
- // 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
|
|
|
- ret = tskNO_AFFINITY;
|
|
|
- } else {
|
|
|
- int index_plus_one = __builtin_ffs(uxCoreAffinityMask);
|
|
|
- assert(index_plus_one >= 1);
|
|
|
- ret = index_plus_one - 1;
|
|
|
- }
|
|
|
- return ret;
|
|
|
-}
|
|
|
-
|
|
|
-#if ( CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS )
|
|
|
-void vTaskSetThreadLocalStoragePointerAndDelCallback( TaskHandle_t xTaskToSet, BaseType_t xIndex, void *pvValue, TlsDeleteCallbackFunction_t pvDelCallback)
|
|
|
+ enum
|
|
|
{
|
|
|
- // 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");
|
|
|
-
|
|
|
- //Set the local storage pointer first
|
|
|
- vTaskSetThreadLocalStoragePointer( xTaskToSet, xIndex, pvValue );
|
|
|
-
|
|
|
- //Set the deletion callback at an offset of configNUM_THREAD_LOCAL_STORAGE_POINTERS/2
|
|
|
- vTaskSetThreadLocalStoragePointer( xTaskToSet, ( xIndex + ( configNUM_THREAD_LOCAL_STORAGE_POINTERS / 2 ) ), pvDelCallback );
|
|
|
- }
|
|
|
-#endif // CONFIG_FREERTOS_TLSP_DELETION_CALLBACKS
|
|
|
-
|
|
|
-#endif // CONFIG_FREERTOS_SMP
|
|
|
-
|
|
|
-#if ( INCLUDE_vTaskPrioritySet == 1 )
|
|
|
-
|
|
|
-void prvTaskPriorityRaise( prvTaskSavedPriority_t * pxSavedPriority, UBaseType_t uxNewPriority )
|
|
|
-{
|
|
|
- TCB_t * pxTCB;
|
|
|
- UBaseType_t uxPriorityUsedOnEntry;
|
|
|
-
|
|
|
- configASSERT( ( uxNewPriority < configMAX_PRIORITIES ) );
|
|
|
-
|
|
|
- /* Ensure the new priority is valid. */
|
|
|
- if( uxNewPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
|
|
|
- {
|
|
|
- uxNewPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
|
|
|
- }
|
|
|
-
|
|
|
-#if CONFIG_FREERTOS_SMP
|
|
|
- taskENTER_CRITICAL();
|
|
|
-#else
|
|
|
- taskENTER_CRITICAL( &xKernelLock );
|
|
|
-#endif
|
|
|
- {
|
|
|
- pxTCB = prvGetTCBFromHandle( NULL );
|
|
|
-
|
|
|
- #if ( configUSE_MUTEXES == 1 )
|
|
|
- {
|
|
|
- pxSavedPriority->uxPriority = pxTCB->uxPriority;
|
|
|
- pxSavedPriority->uxBasePriority = pxTCB->uxBasePriority;
|
|
|
-
|
|
|
- /* If uxNewPriority < uxBasePriority, then there is nothing else to
|
|
|
- * do, as uxBasePriority is always <= uxPriority. */
|
|
|
- if( uxNewPriority > pxTCB->uxBasePriority )
|
|
|
- {
|
|
|
- pxTCB->uxBasePriority = uxNewPriority;
|
|
|
-
|
|
|
- /* Remember the task's current priority before attempting to
|
|
|
- * change it. If the task's current priority is changed, it must
|
|
|
- * be done so before moving the task between task lists) in order
|
|
|
- * for the taskRESET_READY_PRIORITY() macro to function correctly. */
|
|
|
- uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
|
|
-
|
|
|
- if( uxNewPriority > pxTCB->uxPriority )
|
|
|
- {
|
|
|
- pxTCB->uxPriority = uxNewPriority;
|
|
|
-
|
|
|
- /* Only reset the event list item value if the value is not
|
|
|
- * being used for anything else. */
|
|
|
- if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
|
- {
|
|
|
- listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
- }
|
|
|
-
|
|
|
- /* If the task is in the blocked or suspended list we need do
|
|
|
- * nothing more than change its priority variable. However, if
|
|
|
- * the task is in a ready list it needs to be removed and placed
|
|
|
- * in the list appropriate to its new priority. */
|
|
|
- if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
|
- {
|
|
|
- /* The task is currently in its ready list - remove before
|
|
|
- * adding it to its new ready list. As we are in a critical
|
|
|
- * section we can do this even if the scheduler is suspended. */
|
|
|
- if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
|
- {
|
|
|
- /* It is known that the task is in its ready list so
|
|
|
- * there is no need to check again and the port level
|
|
|
- * reset macro can be called directly. */
|
|
|
- portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
|
|
|
- }
|
|
|
- prvAddTaskToReadyList( pxTCB );
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- #else /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
- {
|
|
|
- pxSavedPriority->uxPriority = pxTCB->uxPriority;
|
|
|
- if ( uxNewPriority > pxTCB->uxPriority)
|
|
|
- {
|
|
|
- vTaskPrioritySet( NULL, uxNewPriority );
|
|
|
- }
|
|
|
- }
|
|
|
- #endif
|
|
|
- }
|
|
|
-#if CONFIG_FREERTOS_SMP
|
|
|
- taskEXIT_CRITICAL();
|
|
|
-#else
|
|
|
- taskEXIT_CRITICAL( &xKernelLock );
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-void prvTaskPriorityRestore( prvTaskSavedPriority_t * pxSavedPriority )
|
|
|
-{
|
|
|
- TCB_t * pxTCB;
|
|
|
- UBaseType_t uxNewPriority;
|
|
|
- UBaseType_t uxPriorityUsedOnEntry;
|
|
|
- UBaseType_t uxBasePriorityUsedOnEntry;
|
|
|
- BaseType_t xYieldRequired = pdFALSE;
|
|
|
-
|
|
|
-#if CONFIG_FREERTOS_SMP
|
|
|
- taskENTER_CRITICAL();
|
|
|
-#else
|
|
|
- taskENTER_CRITICAL( &xKernelLock );
|
|
|
-#endif
|
|
|
- {
|
|
|
- pxTCB = prvGetTCBFromHandle( NULL );
|
|
|
-
|
|
|
- #if ( configUSE_MUTEXES == 1 )
|
|
|
- {
|
|
|
- /* If the saved uxBasePriority == the task's uxBasePriority, it means
|
|
|
- * that prvTaskPriorityRaise() never raised the task's uxBasePriority.
|
|
|
- * In that case, there is nothing else to do. */
|
|
|
- if( pxSavedPriority->uxBasePriority != pxTCB->uxBasePriority )
|
|
|
- {
|
|
|
- uxBasePriorityUsedOnEntry = pxTCB->uxBasePriority;
|
|
|
- pxTCB->uxBasePriority = pxSavedPriority->uxBasePriority;
|
|
|
-
|
|
|
- /* Remember the task's current priority before attempting to
|
|
|
- * change it. If the task's current priority is changed, it must
|
|
|
- * be done so before moving the task between task lists in order
|
|
|
- * for the taskRESET_READY_PRIORITY() macro to function correctly. */
|
|
|
- uxPriorityUsedOnEntry = pxTCB->uxPriority;
|
|
|
-
|
|
|
- /* Check if the task inherited a priority after prvTaskPriorityRaise().
|
|
|
- * If this is the case, there is nothing else to do. The priority
|
|
|
- * will be restored when the task disinherits its priority. */
|
|
|
- if( pxTCB->uxPriority == uxBasePriorityUsedOnEntry )
|
|
|
- {
|
|
|
- if( pxTCB->uxMutexesHeld == 0 )
|
|
|
- {
|
|
|
- /* The task may have inherited a priority before prvTaskPriorityRaise()
|
|
|
- * then disinherited a priority after prvTaskPriorityRaise().
|
|
|
- * Thus we need set the uxPriority to the saved base priority
|
|
|
- * so that the task's priority gets restored to the priority
|
|
|
- * before any inheritance or raising. */
|
|
|
- pxTCB->uxPriority = pxSavedPriority->uxBasePriority;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- /* The task may have inherited a priority before prvTaskPriorityRaise()
|
|
|
- * was called. Thus, we need to restore uxPriority to the
|
|
|
- * "saved uxPriority" so that the task still retains that
|
|
|
- * inherited priority. */
|
|
|
- pxTCB->uxPriority = pxSavedPriority->uxPriority;
|
|
|
- }
|
|
|
- uxNewPriority = pxTCB->uxPriority;
|
|
|
-
|
|
|
- if( uxNewPriority < uxPriorityUsedOnEntry )
|
|
|
- {
|
|
|
- /* Setting the priority of the running task down means
|
|
|
- * there may now be another task of higher priority that
|
|
|
- * is ready to execute. */
|
|
|
- xYieldRequired = pdTRUE;
|
|
|
- }
|
|
|
-
|
|
|
- /* Only reset the event list item value if the value is not
|
|
|
- * being used for anything else. */
|
|
|
- if( ( listGET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ) ) & taskEVENT_LIST_ITEM_VALUE_IN_USE ) == 0UL )
|
|
|
- {
|
|
|
- listSET_LIST_ITEM_VALUE( &( pxTCB->xEventListItem ), ( ( TickType_t ) configMAX_PRIORITIES - ( TickType_t ) uxNewPriority ) ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
|
|
|
- }
|
|
|
-
|
|
|
- /* If the task is in the blocked or suspended list we need do
|
|
|
- * nothing more than change its priority variable. However, if
|
|
|
- * the task is in a ready list it needs to be removed and placed
|
|
|
- * in the list appropriate to its new priority. */
|
|
|
- if( listIS_CONTAINED_WITHIN( &( pxReadyTasksLists[ uxPriorityUsedOnEntry ] ), &( pxTCB->xStateListItem ) ) != pdFALSE )
|
|
|
- {
|
|
|
- /* The task is currently in its ready list - remove before
|
|
|
- * adding it to its new ready list. As we are in a critical
|
|
|
- * section we can do this even if the scheduler is suspended. */
|
|
|
- if( uxListRemove( &( pxTCB->xStateListItem ) ) == ( UBaseType_t ) 0 )
|
|
|
- {
|
|
|
- /* It is known that the task is in its ready list so
|
|
|
- * there is no need to check again and the port level
|
|
|
- * reset macro can be called directly. */
|
|
|
- portRESET_READY_PRIORITY( uxPriorityUsedOnEntry, uxTopReadyPriority );
|
|
|
- }
|
|
|
- prvAddTaskToReadyList( pxTCB );
|
|
|
- }
|
|
|
-
|
|
|
- if( xYieldRequired != pdFALSE )
|
|
|
- {
|
|
|
- taskYIELD_IF_USING_PREEMPTION();
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- #else /* if ( configUSE_MUTEXES == 1 ) */
|
|
|
- {
|
|
|
- vTaskPrioritySet( NULL, pxSavedPriority->uxPriority );
|
|
|
- }
|
|
|
- #endif
|
|
|
- }
|
|
|
-#if CONFIG_FREERTOS_SMP
|
|
|
- taskEXIT_CRITICAL();
|
|
|
-#else
|
|
|
- taskEXIT_CRITICAL( &xKernelLock );
|
|
|
-#endif
|
|
|
-}
|
|
|
-
|
|
|
-#endif // ( INCLUDE_vTaskPrioritySet == 1 )
|
|
|
+ ESP_FREERTOS_DEBUG_TABLE_SIZE = 0,
|
|
|
+ ESP_FREERTOS_DEBUG_TABLE_VERSION,
|
|
|
+ ESP_FREERTOS_DEBUG_KERNEL_VER_MAJOR,
|
|
|
+ ESP_FREERTOS_DEBUG_KERNEL_VER_MINOR,
|
|
|
+ ESP_FREERTOS_DEBUG_KERNEL_VER_BUILD,
|
|
|
+ ESP_FREERTOS_DEBUG_UX_TOP_USED_PIORITY,
|
|
|
+ ESP_FREERTOS_DEBUG_PX_TOP_OF_STACK,
|
|
|
+ ESP_FREERTOS_DEBUG_PC_TASK_NAME,
|
|
|
+ /* New entries must be inserted here */
|
|
|
+ ESP_FREERTOS_DEBUG_TABLE_END,
|
|
|
+ };
|
|
|
+
|
|
|
+ const DRAM_ATTR uint8_t FreeRTOS_openocd_params[ ESP_FREERTOS_DEBUG_TABLE_END ] = {
|
|
|
+ ESP_FREERTOS_DEBUG_TABLE_END, /* table size */
|
|
|
+ 1, /* table version */
|
|
|
+ tskKERNEL_VERSION_MAJOR,
|
|
|
+ tskKERNEL_VERSION_MINOR,
|
|
|
+ tskKERNEL_VERSION_BUILD,
|
|
|
+ configMAX_PRIORITIES - 1, /* uxTopUsedPriority */
|
|
|
+ offsetof( TCB_t, pxTopOfStack ), /* thread_stack_offset; */
|
|
|
+ offsetof( TCB_t, pcTaskName ), /* thread_name_offset; */
|
|
|
+ };
|
|
|
+
|
|
|
+#endif /* CONFIG_FREERTOS_DEBUG_OCDAWARE */
|
|
|
+/*----------------------------------------------------------*/
|