2022-03-24 01:45:19 -04:00
/*
2023-08-29 02:27:09 -04:00
* SPDX - FileCopyrightText : 2015 - 2023 Espressif Systems ( Shanghai ) CO LTD
2022-03-24 01:45:19 -04:00
*
* SPDX - License - Identifier : Apache - 2.0
*/
# include "sdkconfig.h"
2023-05-08 04:37:59 -04:00
# include "freertos/idf_additions.h"
2023-08-29 02:27:09 -04:00
# if CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT
# include "freertos/task_snapshot.h"
# endif /* CONFIG_FREERTOS_ENABLE_TASK_SNAPSHOT */
2023-04-06 09:26:17 -04:00
# include "esp_private/freertos_idf_additions_priv.h"
2022-03-24 01:45:19 -04:00
/**
2023-04-06 08:56:50 -04:00
* This file will be included in ` tasks . c ` file , thus , it is treated as a source
* file instead of a header file , and must NOT be included by any ( other ) file .
* This file is used to add additional functions to ` tasks . c ` . See the
* ` esp_additions / include ` directory of the headers that expose these ` tasks . c `
* additional API .
2022-03-24 01:45:19 -04:00
*/
2023-08-29 02:27:09 -04:00
/* ------------------------------------------------- Static Asserts ------------------------------------------------- */
2023-05-04 11:31:31 -04:00
/**
* Both StaticTask_t and TCB_t structures are provided by FreeRTOS sources .
* This is just an additional check of the consistency of these structures .
*/
2023-08-29 02:27:09 -04:00
_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 */
2023-05-04 11:31:31 -04:00
2023-08-29 04:52:25 -04:00
/* ------------------------------------------------- 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 ) ) */
/*----------------------------------------------------------*/
2023-08-29 02:27:09 -04:00
/* -------------------------------------------------- Task Creation ------------------------------------------------- */
2023-05-04 11:31:31 -04:00
2023-08-29 02:27:09 -04:00
# 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 ----------------------------------------------------- */
2022-06-01 11:16:11 -04:00
# if ( configUSE_NEWLIB_REENTRANT == 1 )
2023-08-29 02:27:09 -04:00
2022-06-01 11:16:11 -04:00
/**
* @ brief Get reentrancy structure of the current task
*
* - This funciton is required by newlib ( when __DYNAMIC_REENT__ is enabled )
* - It will return a pointer to the current task ' s reent struct
* - If FreeRTOS is not running , it will return the global reent struct
*
* @ return Pointer to a the ( current taks ' s ) / ( globa ) reent struct
*/
2023-08-29 02:27:09 -04:00
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 ;
2022-06-01 11:16:11 -04:00
}
2023-08-29 02:27:09 -04:00
# endif /* configUSE_NEWLIB_REENTRANT == 1 */
2022-03-24 01:45:19 -04:00
2023-08-29 02:27:09 -04:00
/* -------------------------------------------------- Task Snapshot ------------------------------------------------- */
2022-03-24 01:45:19 -04:00
/**
* @ brief List of all task lists in FreeRTOS
*
* @ note There are currently differing number of task list between SMP FreeRTOS and ESP - IDF FreeRTOS
*/
2023-08-29 02:27:09 -04:00
static List_t * non_ready_task_lists [ ] = {
2022-03-24 01:45:19 -04:00
# ifdef CONFIG_FREERTOS_SMP
& xPendingReadyList ,
2023-08-29 02:27:09 -04:00
# else /* CONFIG_FREERTOS_SMP */
& xPendingReadyList [ 0 ] ,
2022-03-24 01:45:19 -04:00
# ifndef CONFIG_FREERTOS_UNICORE
2023-08-29 02:27:09 -04:00
& xPendingReadyList [ 1 ] ,
# endif /* CONFIG_FREERTOS_UNICORE */
# endif /* CONFIG_FREERTOS_SMP */
2022-03-24 01:45:19 -04:00
& xDelayedTaskList1 ,
& xDelayedTaskList2 ,
2023-08-29 02:27:09 -04:00
# if ( INCLUDE_vTaskDelete == 1 )
2022-03-24 01:45:19 -04:00
& xTasksWaitingTermination ,
# endif
2023-08-29 02:27:09 -04:00
# if ( INCLUDE_vTaskSuspend == 1 )
2022-03-24 01:45:19 -04:00
& xSuspendedTaskList ,
# endif
} ;
2023-08-29 02:27:09 -04:00
/*----------------------------------------------------------*/
2022-03-24 01:45:19 -04:00
/**
* @ brief Get the next task list to traverse
*
* - Given a particular task list , this function returns the next task to traverse .
* - The task lists are returned in the following precedence
* - Ready lists ( highest to lowers priority )
* - Pending ready list ( s )
* - Delayed list 1
* - Delayed list 2
* - Waiting termination list
* - Suspended list
*
* @ 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 )
*/
2023-08-29 02:27:09 -04:00
static List_t * pxGetNextTaskList ( List_t * pxCurTaskList )
2022-03-24 01:45:19 -04:00
{
2023-08-29 02:27:09 -04:00
List_t * pxNextTaskList = NULL ;
2022-03-24 01:45:19 -04:00
2023-08-29 02:27:09 -04:00
/* No Current List. Start from the highest priority ready task list */
if ( pxCurTaskList = = NULL )
2022-03-24 01:45:19 -04:00
{
2023-08-29 02:27:09 -04:00
pxNextTaskList = & pxReadyTasksLists [ configMAX_PRIORITIES - 1 ] ;
2022-03-24 01:45:19 -04:00
}
2023-08-29 02:27:09 -04:00
/* 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 ] ) )
2022-03-24 01:45:19 -04:00
{
2023-08-29 02:27:09 -04:00
/* Find the current priority */
2022-03-24 01:45:19 -04:00
int cur_priority ;
2023-08-29 02:27:09 -04:00
for ( cur_priority = configMAX_PRIORITIES - 1 ; cur_priority > = 0 ; cur_priority - - )
{
if ( pxCurTaskList = = & pxReadyTasksLists [ cur_priority ] )
{
2022-03-24 01:45:19 -04:00
break ;
}
}
2023-08-29 02:27:09 -04:00
/* Return the ready task list at (cur_priority - 1), or the pending ready task list */
if ( cur_priority > 0 )
2022-03-24 01:45:19 -04:00
{
2023-08-29 02:27:09 -04:00
pxNextTaskList = & pxReadyTasksLists [ cur_priority - 1 ] ;
2022-03-24 01:45:19 -04:00
}
2023-08-29 02:27:09 -04:00
/* 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 )
2022-03-24 01:45:19 -04:00
{
2023-08-29 02:27:09 -04:00
pxNextTaskList = non_ready_task_lists [ 0 ] ;
2022-03-24 01:45:19 -04:00
}
else
{
2023-08-29 02:27:09 -04:00
abort ( ) ; /* This should never occur */
2022-03-24 01:45:19 -04:00
}
}
2023-08-29 02:27:09 -04:00
/* Current list is one of the non-ready task lists. Fetch the next non-ready task list */
if ( pxNextTaskList = = NULL )
{
2022-03-24 01:45:19 -04:00
int cur_list_idx ;
2023-08-29 02:27:09 -04:00
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 ] ;
2022-03-24 01:45:19 -04:00
break ;
}
}
}
return pxNextTaskList ;
}
2023-08-29 02:27:09 -04:00
/*----------------------------------------------------------*/
2022-03-24 01:45:19 -04:00
TaskHandle_t pxTaskGetNext ( TaskHandle_t pxTask )
{
2023-08-29 02:27:09 -04:00
TCB_t * pxTCB = ( TCB_t * ) pxTask ;
/* Check current task is valid */
if ( ( pxTCB ! = NULL ) & & ! portVALID_TCB_MEM ( pxTCB ) )
{
2022-03-24 01:45:19 -04:00
return NULL ;
}
2023-08-29 02:27:09 -04:00
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 ) ;
2022-03-24 01:45:19 -04:00
pxCurListItem = & pxTCB - > xStateListItem ;
}
2023-08-29 02:27:09 -04:00
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 ) ;
2022-03-24 01:45:19 -04:00
break ;
}
2023-08-29 02:27:09 -04:00
/* Task list is empty. Get the next task list */
pxNextTaskList = pxGetNextTaskList ( pxNextTaskList ) ;
2022-03-24 01:45:19 -04:00
}
}
2023-08-29 02:27:09 -04:00
else
{
/*There are still more items in the current task list. Get the next item */
pxNextListItem = listGET_NEXT ( pxCurListItem ) ;
}
TCB_t * pxNextTCB ;
2022-03-24 01:45:19 -04:00
2023-08-29 02:27:09 -04:00
if ( pxNextListItem = = NULL )
{
2022-03-24 01:45:19 -04:00
pxNextTCB = NULL ;
2023-08-29 02:27:09 -04:00
}
else
{
pxNextTCB = ( TCB_t * ) listGET_LIST_ITEM_OWNER ( pxNextListItem ) ;
2022-03-24 01:45:19 -04:00
}
return pxNextTCB ;
}
2023-08-29 02:27:09 -04:00
/*----------------------------------------------------------*/
2022-03-24 01:45:19 -04:00
2023-08-29 02:27:09 -04:00
BaseType_t vTaskGetSnapshot ( TaskHandle_t pxTask ,
TaskSnapshot_t * pxTaskSnapshot )
2022-03-24 01:45:19 -04:00
{
2023-08-29 02:27:09 -04:00
if ( ( portVALID_TCB_MEM ( pxTask ) = = false ) | | ( pxTaskSnapshot = = NULL ) )
{
2022-05-09 06:17:13 -04:00
return pdFALSE ;
}
2023-08-29 02:27:09 -04:00
TCB_t * pxTCB = ( TCB_t * ) pxTask ;
2022-03-24 01:45:19 -04:00
pxTaskSnapshot - > pxTCB = pxTCB ;
2023-08-29 02:27:09 -04:00
pxTaskSnapshot - > pxTopOfStack = ( StackType_t * ) pxTCB - > pxTopOfStack ;
pxTaskSnapshot - > pxEndOfStack = ( StackType_t * ) pxTCB - > pxEndOfStack ;
2022-05-09 06:17:13 -04:00
return pdTRUE ;
2022-03-24 01:45:19 -04:00
}
2023-08-29 02:27:09 -04:00
/*----------------------------------------------------------*/
2022-03-24 01:45:19 -04:00
2023-08-29 02:27:09 -04:00
UBaseType_t uxTaskGetSnapshotAll ( TaskSnapshot_t * const pxTaskSnapshotArray ,
const UBaseType_t uxArrayLength ,
UBaseType_t * const pxTCBSize )
2022-03-24 01:45:19 -04:00
{
UBaseType_t uxArrayNumFilled = 0 ;
2023-08-29 02:27:09 -04:00
/*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 ] ) ;
2022-03-24 01:45:19 -04:00
uxArrayNumFilled + + ;
2023-08-29 02:27:09 -04:00
if ( ! ( uxArrayNumFilled < uxArrayLength ) )
{
2022-03-24 01:45:19 -04:00
break ;
}
2023-08-29 02:27:09 -04:00
pxCurListItem = listGET_NEXT ( pxCurListItem ) ;
2022-03-24 01:45:19 -04:00
}
}
2023-08-29 02:27:09 -04:00
/*Get the next task list */
pxCurTaskList = pxGetNextTaskList ( pxCurTaskList ) ;
2022-03-24 01:45:19 -04:00
}
2023-08-29 02:27:09 -04:00
* pxTCBSize = sizeof ( TCB_t ) ;
2022-03-24 01:45:19 -04:00
return uxArrayNumFilled ;
}
2023-08-29 02:27:09 -04:00
/*----------------------------------------------------------*/
2022-03-24 01:45:19 -04:00
2023-08-29 02:27:09 -04:00
/* ----------------------------------------------------- OpenOCD ---------------------------------------------------- */
2022-03-24 01:45:19 -04:00
2023-05-08 04:37:59 -04:00
# if CONFIG_FREERTOS_DEBUG_OCDAWARE
2022-03-24 01:45:19 -04:00
/**
* 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
*/
2023-08-29 02:27:09 -04:00
enum
2022-05-02 01:29:54 -04:00
{
2023-08-29 02:27:09 -04:00
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 */
/*----------------------------------------------------------*/