freertos: take tasks snapshot out of tasks.c source code

This commit is contained in:
Omar Chebib
2021-08-04 10:56:37 +08:00
parent 0f0bd29f8f
commit 83c9e1b223
15 changed files with 417 additions and 252 deletions

View File

@@ -25,6 +25,7 @@
#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS #ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task.h"
#include "freertos/task_snapshot.h"
#endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS #endif // CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
/* Internal error codes used by the routines that parse the incoming gdb packet */ /* Internal error codes used by the routines that parse the incoming gdb packet */

View File

@@ -16,7 +16,7 @@
#include "sdkconfig.h" #include "sdkconfig.h"
#include "soc/soc_memory_layout.h" #include "soc/soc_memory_layout.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task_snapshot.h"
#include "esp_rom_sys.h" #include "esp_rom_sys.h"
#include "esp_core_dump_port.h" #include "esp_core_dump_port.h"
#include "esp_core_dump_common.h" #include "esp_core_dump_common.h"

View File

@@ -34,8 +34,8 @@ const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port"
#define COREDUMP_EM_RISCV 0xF3 #define COREDUMP_EM_RISCV 0xF3
#define COREDUMP_INVALID_CAUSE_VALUE 0xFFFF #define COREDUMP_INVALID_CAUSE_VALUE 0xFFFF
#define COREDUMP_FAKE_STACK_START 0x20000000 #define COREDUMP_FAKE_STACK_START 0x20000000U
#define COREDUMP_FAKE_STACK_LIMIT 0x30000000 #define COREDUMP_FAKE_STACK_LIMIT 0x30000000U
#if CONFIG_ESP_COREDUMP_ENABLE #if CONFIG_ESP_COREDUMP_ENABLE
@@ -424,7 +424,7 @@ void esp_core_dump_summary_parse_backtrace_info(esp_core_dump_bt_info_t *bt_info
/* Check whether the stack is a fake stack created during coredump generation /* Check whether the stack is a fake stack created during coredump generation
* If its a fake stack, we don't have any actual stack dump * If its a fake stack, we don't have any actual stack dump
*/ */
if (vaddr >= COREDUMP_FAKE_STACK_START && vaddr < COREDUMP_FAKE_STACK_LIMIT) { if (vaddr >= (void*) COREDUMP_FAKE_STACK_START && vaddr < (void*) COREDUMP_FAKE_STACK_LIMIT) {
bt_info->dump_size = 0; bt_info->dump_size = 0;
return; return;
} }

View File

@@ -21,7 +21,6 @@ if(CONFIG_IDF_TARGET_ARCH_XTENSA)
port/xtensa/include) port/xtensa/include)
set(private_include_dirs set(private_include_dirs
include/freertos
port/xtensa/include/freertos port/xtensa/include/freertos
port/xtensa port/xtensa
port/priv_include port/priv_include
@@ -37,7 +36,6 @@ elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
port/riscv/include) port/riscv/include)
set(private_include_dirs set(private_include_dirs
include/freertos
port/riscv/include/freertos port/riscv/include/freertos
port/riscv port/riscv
port/priv_include port/priv_include
@@ -46,6 +44,7 @@ elseif(CONFIG_IDF_TARGET_ARCH_RISCV)
endif() endif()
list(APPEND srcs list(APPEND srcs
"esp_additions/task_snapshot.c"
"port/port_common.c" "port/port_common.c"
"port/port_systick.c" "port/port_systick.c"
"croutine.c" "croutine.c"
@@ -58,6 +57,12 @@ list(APPEND srcs
"FreeRTOS-openocd.c" "FreeRTOS-openocd.c"
"freertos_v8_compat.c") "freertos_v8_compat.c")
list(APPEND include_dirs
"include/esp_additions")
list(APPEND private_include_dirs
"include/freertos")
if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY) if(CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY)
list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S") list(APPEND srcs "port/xtensa/xtensa_loadstore_handler.S")
endif() endif()

View File

@@ -6,9 +6,9 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority
endif endif
COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include COMPONENT_ADD_INCLUDEDIRS := include port/xtensa/include include/esp_additions
COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa port/priv_include . COMPONENT_PRIV_INCLUDEDIRS := include/freertos port/xtensa/include/freertos port/xtensa port/priv_include .
COMPONENT_SRCDIRS += port port/xtensa COMPONENT_SRCDIRS += port port/xtensa esp_additions/
ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o

View File

@@ -0,0 +1,220 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "freertos/FreeRTOS.h"
#include "freertos/task_snapshot.h"
#ifndef DIM
#define DIM(t) (sizeof(t)/ sizeof(*(t)))
#endif
#if ( configENABLE_TASK_SNAPSHOT == 1 )
static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, void *pxTCB )
{
if (pxTCB == NULL) {
return;
}
pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB;
pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *) pxTCBGetTopOfStack(pxTCB);
#if( portSTACK_GROWTH < 0 )
{
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetEndOfStack(pxTCB);
}
#else
{
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCBGetStartOfStack(pxTCB);
}
#endif
(*uxTask)++;
}
static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList )
{
void *pxNextTCB = NULL;
void *pxFirstTCB = NULL;
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
{
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
do
{
if( *uxTask >= uxArraySize ) {
break;
}
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB );
} while( pxNextTCB != pxFirstTCB );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz )
{
UBaseType_t uxTask = 0;
UBaseType_t i = 0;
*pxTcbSz = pxTCBGetSize();
/* Fill in an TaskStatus_t structure with information on each
task in the Ready state. */
i = configMAX_PRIORITIES;
do
{
i--;
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyTask(i) );
} while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Fill in an TaskStatus_t structure with information on each
task in the Blocked state. */
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetDelayedTaskList() );
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetOverflowDelayedTaskList() );
for (i = 0; i < portNUM_PROCESSORS; i++) {
if( uxTask >= uxArraySize ) {
break;
}
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxListGetReadyPendingTask(i) );
}
#if( INCLUDE_vTaskDelete == 1 )
{
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetTasksWaitingTermination() );
}
#endif
#if ( INCLUDE_vTaskSuspend == 1 )
{
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, pxGetSuspendedTaskList() );
}
#endif
return uxTask;
}
static void *prvFirstTaskGet( List_t *pxList )
{
ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList );
if( pxListItem != listGET_END_MARKER( pxList ) ) {
return listGET_LIST_ITEM_OWNER( pxListItem );
}
return NULL;
}
static void *prvNextTaskGet( void *pxTCB )
{
List_t *pxList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTCB) );
ListItem_t *pxListItem = listGET_NEXT( pxTCBGetStateListItem(pxTCB) );
if( pxListItem != listGET_END_MARKER( pxList ) ) {
return listGET_LIST_ITEM_OWNER( pxListItem );
}
return NULL;
}
void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot )
{
configASSERT( portVALID_TCB_MEM(pxTask) );
configASSERT( pxTaskSnapshot != NULL );
pxTaskSnapshot->pxTCB = (void*) pxTask;
pxTaskSnapshot->pxTopOfStack = pxTCBGetTopOfStack((void*) pxTask);
pxTaskSnapshot->pxEndOfStack = pxTCBGetEndOfStack((void*) pxTask);
}
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask )
{
void *pxTCB = pxTask;
List_t *pxTaskList = NULL;
UBaseType_t i = configMAX_PRIORITIES;
UBaseType_t bCurTaskListFound = pdFALSE;
List_t *task_lists[] = {
pxGetDelayedTaskList(),
pxGetOverflowDelayedTaskList(),
#if( INCLUDE_vTaskDelete == 1 )
pxGetTasksWaitingTermination(),
#endif
#if( INCLUDE_vTaskSuspend == 1 )
pxGetSuspendedTaskList()
#endif
};
if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) {
return NULL;
}
if( pxTCB != NULL ) {
pxTCB = prvNextTaskGet( pxTCB );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
pxTaskList = listLIST_ITEM_CONTAINER( pxTCBGetStateListItem(pxTask) );
}
/* ready tasks lists */
do
{
i--;
List_t *pxList = pxListGetReadyTask(i);
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
/* need to find list the current task item from */
if( pxTaskList == pxList ) {
bCurTaskListFound = pdTRUE;
}
continue; /* go to the next 'ready list' */
}
pxTCB = prvFirstTaskGet( pxList );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
}
while( i > tskIDLE_PRIORITY );
/* pending ready tasks lists */
for (i = 0; i < portNUM_PROCESSORS; i++) {
List_t *pxList = pxListGetReadyPendingTask(i);
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
/* need to find list the current task item from */
if( pxTaskList == pxList ) {
bCurTaskListFound = pdTRUE;
}
continue; /* go to the next 'ready list' */
}
pxTCB = prvFirstTaskGet( pxList );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
}
/* other tasks lists */
for (i = 0; i < DIM(task_lists); i++) {
List_t *pxList = task_lists[ i ];
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
/* need to find list the current task item from */
if( pxTaskList == pxList ) {
bCurTaskListFound = pdTRUE;
}
continue; /* go to the next 'ready list' */
}
pxTCB = prvFirstTaskGet( pxList );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
}
return NULL;
}
#endif

View File

@@ -0,0 +1,90 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#if ( configENABLE_TASK_SNAPSHOT == 1 )
#ifdef __cplusplus
extern "C" {
#endif
/**
* Check `freertos_tasks_c_additions.h` file for more info
* about these functions declaration.
*/
UBaseType_t pxTCBGetSize ( void );
ListItem_t* pxTCBGetStateListItem ( void *pxTCB );
StackType_t* pxTCBGetStartOfStack ( void *pxTCB );
StackType_t* pxTCBGetTopOfStack ( void *pxTCB );
StackType_t* pxTCBGetEndOfStack ( void *pxTCB );
List_t* pxListGetReadyTask ( UBaseType_t idx );
List_t* pxListGetReadyPendingTask ( UBaseType_t idx );
List_t* pxGetDelayedTaskList ( void );
List_t* pxGetOverflowDelayedTaskList ( void );
List_t* pxGetTasksWaitingTermination ( void );
List_t* pxGetSuspendedTaskList ( void );
/**
* Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system.
* We need this struct because TCB_t is defined (hidden) in tasks.c.
*/
typedef struct xTASK_SNAPSHOT
{
void *pxTCB; /*!< Address of task control block. */
StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */
StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo
pxTopOfStack > pxEndOfStack, stack grows lo2hi*/
} TaskSnapshot_t;
/*
* This function fills array with TaskSnapshot_t structures for every task in the system.
* Used by panic handling code to get snapshots of all tasks in the system.
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
* @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data.
* @param uxArraySize Size of tasks snapshots array.
* @param pxTcbSz Pointer to store size of TCB.
* @return Number of elements stored in array.
*/
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz );
/*
* This function iterates over all tasks in the system.
* Used by panic handling code to iterate over tasks in the system.
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
* @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks).
* @param pxTask task handle.
* @return Handle for the next task. If pxTask is NULL, returns hadnle for the first task.
*/
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask );
/*
* This function fills TaskSnapshot_t structure for specified task.
* Used by panic handling code to get snapshot of a task.
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
* @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks).
* @param pxTask task handle.
* @param pxTaskSnapshot address of TaskSnapshot_t structure to fill.
*/
void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot );
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,80 @@
// Copyright 2015-2021 Espressif Systems (Shanghai) PTE LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#pragma once
/**
* This file will be included in `tasks.c` file, thus, it must NOT be included
* by any (other) file.
* The functions below only consist in getters for the static variables in
* `tasks.c` file.
* The only source files that should call these functions are the ones in
* `/additions` directory.
*/
#if ( configENABLE_TASK_SNAPSHOT == 1 )
UBaseType_t pxTCBGetSize ( void )
{
return sizeof(TCB_t);
}
ListItem_t* pxTCBGetStateListItem ( void *pxTCB )
{
return &(((TCB_t*)pxTCB)->xStateListItem);
}
StackType_t* pxTCBGetStartOfStack ( void *pxTCB )
{
return (StackType_t*) ((TCB_t*)pxTCB)->pxStack;
}
StackType_t* pxTCBGetTopOfStack ( void *pxTCB )
{
return (StackType_t*) ((TCB_t*)pxTCB)->pxTopOfStack;
}
StackType_t* pxTCBGetEndOfStack ( void *pxTCB )
{
return (StackType_t*) ((TCB_t*)pxTCB)->pxEndOfStack;
}
List_t* pxListGetReadyTask ( UBaseType_t idx )
{
return &( pxReadyTasksLists[idx] );
}
List_t* pxListGetReadyPendingTask ( UBaseType_t idx )
{
return &( xPendingReadyList[idx] );
}
List_t* pxGetDelayedTaskList ( void ) {
return pxDelayedTaskList;
}
List_t* pxGetOverflowDelayedTaskList ( void ) {
return pxOverflowDelayedTaskList;
}
List_t* pxGetTasksWaitingTermination ( void ) {
return &xTasksWaitingTermination;
}
List_t* pxGetSuspendedTaskList ( void ) {
return &xSuspendedTaskList;
}
#endif

View File

@@ -277,11 +277,11 @@ extern void vPortCleanUpTCB ( void *pxTCB );
#endif //configUSE_TICKLESS_IDLE #endif //configUSE_TICKLESS_IDLE
#if CONFIG_ESP_COREDUMP_ENABLE #if CONFIG_ESP_COREDUMP_ENABLE || CONFIG_ESP_GDBSTUB_SUPPORT_TASKS
#define configENABLE_TASK_SNAPSHOT 1 #define configENABLE_TASK_SNAPSHOT 1
#endif #endif
#ifndef configENABLE_TASK_SNAPSHOT #ifndef configENABLE_TASK_SNAPSHOT
#define configENABLE_TASK_SNAPSHOT 1 #define configENABLE_TASK_SNAPSHOT 0
#endif #endif
#if CONFIG_SYSVIEW_ENABLE #if CONFIG_SYSVIEW_ENABLE
@@ -297,4 +297,7 @@ extern void vPortCleanUpTCB ( void *pxTCB );
#define configCHECK_MUTEX_GIVEN_BY_OWNER 0 #define configCHECK_MUTEX_GIVEN_BY_OWNER 0
#endif #endif
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1
#endif /* FREERTOS_CONFIG_H */ #endif /* FREERTOS_CONFIG_H */

View File

@@ -152,18 +152,6 @@ typedef struct xTASK_STATUS
#endif #endif
} TaskStatus_t; } TaskStatus_t;
/**
* Used with the uxTaskGetSnapshotAll() function to save memory snapshot of each task in the system.
* We need this struct because TCB_t is defined (hidden) in tasks.c.
*/
typedef struct xTASK_SNAPSHOT
{
void *pxTCB; /*!< Address of task control block. */
StackType_t *pxTopOfStack; /*!< Points to the location of the last item placed on the tasks stack. */
StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo
pxTopOfStack > pxEndOfStack, stack grows lo2hi*/
} TaskSnapshot_t;
/** @endcond */ /** @endcond */
/** /**
@@ -2529,36 +2517,8 @@ TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION;
*/ */
void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION; void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
/* /* TODO: IDF-3683 */
* This function fills array with TaskSnapshot_t structures for every task in the system. #include "freertos/task_snapshot.h"
* Used by panic handling code to get snapshots of all tasks in the system.
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
* @param pxTaskSnapshotArray Pointer to array of TaskSnapshot_t structures to store tasks snapshot data.
* @param uxArraySize Size of tasks snapshots array.
* @param pxTcbSz Pointer to store size of TCB.
* @return Number of elements stored in array.
*/
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz );
/*
* This function iterates over all tasks in the system.
* Used by panic handling code to iterate over tasks in the system.
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
* @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks).
* @param pxTask task handle.
* @return Handle for the next task. If pxTask is NULL, returns hadnle for the first task.
*/
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask );
/*
* This function fills TaskSnapshot_t structure for specified task.
* Used by panic handling code to get snapshot of a task.
* Only available when configENABLE_TASK_SNAPSHOT is set to 1.
* @note This function should not be used while FreeRTOS is running (as it doesn't acquire any locks).
* @param pxTask task handle.
* @param pxTaskSnapshot address of TaskSnapshot_t structure to fill.
*/
void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot );
/** @endcond */ /** @endcond */
#ifdef __cplusplus #ifdef __cplusplus

View File

@@ -2,13 +2,11 @@
archive: libfreertos.a archive: libfreertos.a
entries: entries:
* (noflash_text) * (noflash_text)
if ESP_PANIC_HANDLER_IRAM != y:
task_snapshot (default)
if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y: if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
port: pxPortInitialiseStack (default) port: pxPortInitialiseStack (default)
port: xPortStartScheduler (default) port: xPortStartScheduler (default)
if ESP_PANIC_HANDLER_IRAM != y:
tasks: uxTaskGetSnapshotAll (default)
tasks: prvTaskGetSnapshot (default)
tasks: prvTaskGetSnapshotsFromList (default)
if IDF_TARGET_ESP32S2 = n && IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n : if IDF_TARGET_ESP32S2 = n && IDF_TARGET_ESP32C3 = n && IDF_TARGET_ESP32H2 = n :
port: vPortReleaseTaskMPUSettings (default) port: vPortReleaseTaskMPUSettings (default)
tasks: xTaskCreateRestricted (default) tasks: xTaskCreateRestricted (default)

View File

@@ -5811,201 +5811,6 @@ const TickType_t xConstTickCount = xTickCount;
#endif /* INCLUDE_vTaskSuspend */ #endif /* INCLUDE_vTaskSuspend */
} }
#if ( configENABLE_TASK_SNAPSHOT == 1 )
static void prvTaskGetSnapshot( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, TCB_t *pxTCB )
{
if (pxTCB == NULL) {
return;
}
pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB;
pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack;
#if( portSTACK_GROWTH < 0 )
{
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack;
}
#else
{
pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxStack;
}
#endif
(*uxTask)++;
}
static void prvTaskGetSnapshotsFromList( TaskSnapshot_t *pxTaskSnapshotArray, UBaseType_t *uxTask, const UBaseType_t uxArraySize, List_t *pxList )
{
TCB_t *pxNextTCB, *pxFirstTCB;
if( listCURRENT_LIST_LENGTH( pxList ) > ( UBaseType_t ) 0 )
{
listGET_OWNER_OF_NEXT_ENTRY( pxFirstTCB, pxList );
do
{
if( *uxTask >= uxArraySize )
break;
listGET_OWNER_OF_NEXT_ENTRY( pxNextTCB, pxList );
prvTaskGetSnapshot( pxTaskSnapshotArray, uxTask, pxNextTCB );
} while( pxNextTCB != pxFirstTCB );
}
else
{
mtCOVERAGE_TEST_MARKER();
}
}
UBaseType_t uxTaskGetSnapshotAll( TaskSnapshot_t * const pxTaskSnapshotArray, const UBaseType_t uxArraySize, UBaseType_t * const pxTcbSz )
{
UBaseType_t uxTask = 0, i = 0;
*pxTcbSz = sizeof(TCB_t);
/* Fill in an TaskStatus_t structure with information on each
task in the Ready state. */
i = configMAX_PRIORITIES;
do
{
i--;
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( pxReadyTasksLists[ i ] ) );
} while( i > ( UBaseType_t ) tskIDLE_PRIORITY ); /*lint !e961 MISRA exception as the casts are only redundant for some ports. */
/* Fill in an TaskStatus_t structure with information on each
task in the Blocked state. */
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxDelayedTaskList );
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, ( List_t * ) pxOverflowDelayedTaskList );
for (i = 0; i < portNUM_PROCESSORS; i++) {
if( uxTask >= uxArraySize )
break;
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &( xPendingReadyList[i]) );
}
#if( INCLUDE_vTaskDelete == 1 )
{
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xTasksWaitingTermination );
}
#endif
#if ( INCLUDE_vTaskSuspend == 1 )
{
prvTaskGetSnapshotsFromList( pxTaskSnapshotArray, &uxTask, uxArraySize, &xSuspendedTaskList );
}
#endif
return uxTask;
}
static TCB_t *prvFirstTaskGet( List_t *pxList )
{
ListItem_t *pxListItem = listGET_HEAD_ENTRY( pxList );
if( pxListItem != listGET_END_MARKER( pxList ) ) {
return listGET_LIST_ITEM_OWNER( pxListItem );
}
return NULL;
}
static TCB_t *prvNextTaskGet( TCB_t *pxTCB )
{
List_t *pxList = listLIST_ITEM_CONTAINER( &( pxTCB->xStateListItem ) );
ListItem_t *pxListItem = listGET_NEXT( &( pxTCB->xStateListItem ) );
if( pxListItem != listGET_END_MARKER( pxList ) ) {
return listGET_LIST_ITEM_OWNER( pxListItem );
}
return NULL;
}
inline void vTaskGetSnapshot( TaskHandle_t pxTask, TaskSnapshot_t *pxTaskSnapshot )
{
configASSERT( portVALID_TCB_MEM(pxTask) );
configASSERT( pxTaskSnapshot != NULL );
pxTaskSnapshot->pxTCB = (TCB_t *)pxTask;
pxTaskSnapshot->pxTopOfStack = (StackType_t *)((TCB_t *)pxTask)->pxTopOfStack;
pxTaskSnapshot->pxEndOfStack = ((TCB_t *)pxTask)->pxEndOfStack;
}
TaskHandle_t pxTaskGetNext( TaskHandle_t pxTask )
{
TCB_t *pxTCB = pxTask;
List_t *pxTaskList = NULL;
UBaseType_t i = configMAX_PRIORITIES;
UBaseType_t bCurTaskListFound = pdFALSE;
List_t *task_lists[] = {
pxDelayedTaskList,
pxOverflowDelayedTaskList,
#if( INCLUDE_vTaskDelete == 1 )
&xTasksWaitingTermination,
#endif
#if( INCLUDE_vTaskSuspend == 1 )
&xSuspendedTaskList
#endif
};
if( pxTask != NULL && !portVALID_TCB_MEM(pxTask) ) {
return NULL;
}
if( pxTCB != NULL ) {
pxTCB = prvNextTaskGet( pxTCB );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
pxTaskList = listLIST_ITEM_CONTAINER( &( ((TCB_t *)pxTask)->xStateListItem ) );
}
/* ready tasks lists */
do
{
i--;
List_t *pxList = &( pxReadyTasksLists[ i ] );
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
/* need to find list the current task item from */
if( pxTaskList == pxList ) {
bCurTaskListFound = pdTRUE;
}
continue; /* go to the next 'ready list' */
}
pxTCB = prvFirstTaskGet( pxList );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
}
while( i > tskIDLE_PRIORITY );
/* pending ready tasks lists */
for (i = 0; i < portNUM_PROCESSORS; i++) {
List_t *pxList = &( xPendingReadyList[ i ] );
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
/* need to find list the current task item from */
if( pxTaskList == pxList ) {
bCurTaskListFound = pdTRUE;
}
continue; /* go to the next 'ready list' */
}
pxTCB = prvFirstTaskGet( pxList );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
}
/* other tasks lists */
for (i = 0; i < sizeof(task_lists)/sizeof(task_lists[0]); i++) {
List_t *pxList = task_lists[ i ];
if( bCurTaskListFound == pdFALSE && pxTaskList != NULL ) {
/* need to find list the current task item from */
if( pxTaskList == pxList ) {
bCurTaskListFound = pdTRUE;
}
continue; /* go to the next 'ready list' */
}
pxTCB = prvFirstTaskGet( pxList );
if( pxTCB != NULL ) {
// take care not to return garbage
return portVALID_TCB_MEM(pxTCB) ? pxTCB : NULL;
}
}
return NULL;
}
#endif
/* Code below here allows additional code to be inserted into this source file, /* Code below here allows additional code to be inserted into this source file,
especially where access to file scope functions and data is needed (for example especially where access to file scope functions and data is needed (for example
when performing module tests). */ when performing module tests). */

View File

@@ -1,3 +1,5 @@
idf_component_register(SRC_DIRS . idf_component_register(SRC_DIRS .
PRIV_INCLUDE_DIRS . PRIV_INCLUDE_DIRS .
PRIV_REQUIRES cmock test_utils esp_ipc driver) PRIV_REQUIRES cmock test_utils esp_ipc driver)
# Enable task snapshots by setting configENABLE_TASK_SNAPSHOT macro
idf_build_set_property(COMPILE_OPTIONS "-DconfigENABLE_TASK_SNAPSHOT=1" APPEND)

View File

@@ -5,7 +5,7 @@
#include <stdio.h> #include <stdio.h>
#include "soc/cpu.h" #include "soc/cpu.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h" #include "freertos/task_snapshot.h"
#include "unity.h" #include "unity.h"
#include "sdkconfig.h" #include "sdkconfig.h"

View File

@@ -7,6 +7,7 @@ idf_component_get_property(original_freertos_dir freertos COMPONENT_OVERRIDEN_DI
set(include_dirs set(include_dirs
"${original_freertos_dir}/include" "${original_freertos_dir}/include"
"${original_freertos_dir}/include/freertos" # this is due to the way includes are generated in CMock "${original_freertos_dir}/include/freertos" # this is due to the way includes are generated in CMock
"${original_freertos_dir}/include/esp_additions"
"${original_freertos_dir}/port/linux/include") "${original_freertos_dir}/port/linux/include")
idf_component_mock(INCLUDE_DIRS ${include_dirs} idf_component_mock(INCLUDE_DIRS ${include_dirs}