Explorar o código

Merge branch 'feature/freertos_snapshot_extraction' into 'master'

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

Closes IDF-3334

See merge request espressif/esp-idf!14675
Omar Chebib %!s(int64=4) %!d(string=hai) anos
pai
achega
32067f9b6b

+ 1 - 0
components/esp_gdbstub/private_include/esp_gdbstub_common.h

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

+ 1 - 1
components/espcoredump/src/core_dump_common.c

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

+ 3 - 3
components/espcoredump/src/port/riscv/core_dump_port.c

@@ -34,8 +34,8 @@ const static DRAM_ATTR char TAG[] __attribute__((unused)) = "esp_core_dump_port"
 #define COREDUMP_EM_RISCV                   0xF3
 
 #define COREDUMP_INVALID_CAUSE_VALUE        0xFFFF
-#define COREDUMP_FAKE_STACK_START           0x20000000
-#define COREDUMP_FAKE_STACK_LIMIT           0x30000000
+#define COREDUMP_FAKE_STACK_START           0x20000000U
+#define COREDUMP_FAKE_STACK_LIMIT           0x30000000U
 
 #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
      * 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;
         return;
     }

+ 7 - 2
components/freertos/CMakeLists.txt

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

+ 2 - 2
components/freertos/component.mk

@@ -6,9 +6,9 @@ ifdef CONFIG_FREERTOS_DEBUG_OCDAWARE
 	COMPONENT_ADD_LDFLAGS += -Wl,--undefined=uxTopUsedPriority
 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_SRCDIRS += port port/xtensa
+COMPONENT_SRCDIRS += port port/xtensa esp_additions/
 
 ifndef CONFIG_ESP32_IRAM_AS_8BIT_ACCESSIBLE_MEMORY
 	COMPONENT_OBJEXCLUDE := xtensa/xtensa_loadstore_handler.o

+ 220 - 0
components/freertos/esp_additions/task_snapshot.c

@@ -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

+ 90 - 0
components/freertos/include/esp_additions/freertos/task_snapshot.h

@@ -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

+ 80 - 0
components/freertos/include/esp_additions/freertos_tasks_c_additions.h

@@ -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

+ 5 - 2
components/freertos/include/freertos/FreeRTOSConfig.h

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

+ 2 - 42
components/freertos/include/freertos/task.h

@@ -152,18 +152,6 @@ typedef struct xTASK_STATUS
 #endif
 } 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 */
 
 /**
@@ -2529,36 +2517,8 @@ TaskHandle_t pvTaskIncrementMutexHeldCount( void ) PRIVILEGED_FUNCTION;
  */
 void vTaskInternalSetTimeOutState( TimeOut_t * const pxTimeOut ) PRIVILEGED_FUNCTION;
 
-/*
- * 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 );
+/* TODO: IDF-3683 */
+#include "freertos/task_snapshot.h"
 
 /** @endcond */
 #ifdef __cplusplus

+ 2 - 4
components/freertos/linker.lf

@@ -2,13 +2,11 @@
 archive: libfreertos.a
 entries:
     * (noflash_text)
+    if ESP_PANIC_HANDLER_IRAM != y:
+        task_snapshot (default)
     if FREERTOS_PLACE_FUNCTIONS_INTO_FLASH = y:
         port: pxPortInitialiseStack (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 :
             port: vPortReleaseTaskMPUSettings (default)
             tasks: xTaskCreateRestricted (default)

+ 0 - 195
components/freertos/tasks.c

@@ -5811,201 +5811,6 @@ const TickType_t xConstTickCount = xTickCount;
     #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,
 especially where access to file scope functions and data is needed (for example
 when performing module tests). */

+ 2 - 0
components/freertos/test/CMakeLists.txt

@@ -1,3 +1,5 @@
 idf_component_register(SRC_DIRS .
                        PRIV_INCLUDE_DIRS .
                        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)

+ 1 - 1
components/freertos/test/test_tasks_snapshot.c

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

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

@@ -7,6 +7,7 @@ idf_component_get_property(original_freertos_dir freertos COMPONENT_OVERRIDEN_DI
 set(include_dirs
     "${original_freertos_dir}/include"
     "${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")
 
 idf_component_mock(INCLUDE_DIRS ${include_dirs}