From 140c5e06773c22e444da0d108c23984a93f74e17 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 15 Apr 2020 13:17:33 -0300 Subject: [PATCH 1/5] freertos: added task state field inside of TaskSnapshot_t to capture it. --- components/freertos/include/freertos/task.h | 1 + components/freertos/tasks.c | 1 + components/freertos/test/test_tasks_snapshot.c | 3 +++ 3 files changed, 5 insertions(+) diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index cfea1f0a77..982c6bfe69 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -199,6 +199,7 @@ typedef struct xTASK_SNAPSHOT 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*/ + eTaskState eState; /*!< Current state of the task. Can be running or suspended */ } TaskSnapshot_t; /** diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 5290168542..d09e36e56e 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -5057,6 +5057,7 @@ TickType_t uxReturn; } pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack; + pxTaskSnapshotArray[ *uxTask ].eState = eTaskGetState(pxTCB); #if( portSTACK_GROWTH < 0 ) { pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack; diff --git a/components/freertos/test/test_tasks_snapshot.c b/components/freertos/test/test_tasks_snapshot.c index bc42e1a90c..f02c04332e 100644 --- a/components/freertos/test/test_tasks_snapshot.c +++ b/components/freertos/test/test_tasks_snapshot.c @@ -27,6 +27,9 @@ TEST_CASE("Tasks snapshot", "[freertos]") esp_cpu_stall(other_core_id); #endif UBaseType_t task_num = uxTaskGetSnapshotAll(tasks, TEST_MAX_TASKS_NUM, &tcb_sz); + for (uint32_t i = 0; i < task_num; i++) { + TEST_ASSERT_EQUAL(tasks[i].eState, eTaskGetState(tasks[i].pxTCB)); + } #ifndef CONFIG_FREERTOS_UNICORE esp_cpu_unstall(other_core_id); #endif From 9a54a0af138fd01b80435d7f5e32e3a4c8014465 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 15 Apr 2020 13:57:01 -0300 Subject: [PATCH 2/5] gdbstub: added task state information on qThreadExtraInfo command --- components/esp_gdbstub/src/gdbstub.c | 45 +++++++++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c index f15be617f2..b67ae273aa 100644 --- a/components/esp_gdbstub/src/gdbstub.c +++ b/components/esp_gdbstub/src/gdbstub.c @@ -177,6 +177,15 @@ static bool get_task_handle(size_t index, TaskHandle_t *handle) return true; } +static eTaskState get_task_state(size_t index) +{ + if (index >= s_scratch.task_count) { + return eInvalid; + } + + return s_scratch.tasks[index].eState; +} + /** Get the index of the task running on the current CPU, and save the result */ static void find_paniced_task_index(void) { @@ -280,6 +289,13 @@ static void handle_qsThreadInfo_command(const unsigned char* cmd, int len) /** qThreadExtraInfo requests the thread name */ static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) { + uint8_t task_state_string_index = 0; + const char task_state_string[][] = "Running", + "Ready", + "Blocked", + "Suspended", + "Invalid"; + cmd += sizeof("qThreadExtraInfo,") - 1; int task_index = esp_gdbstub_gethex(&cmd, -1); TaskHandle_t handle; @@ -293,7 +309,34 @@ static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) esp_gdbstub_send_hex(*task_name, 8); task_name++; } - /** TODO: add "Running" or "Suspended" and "CPU0" or "CPU1" */ + + esp_gdbstub_send_hex(' ', 8); + + eTaskState state = get_task_state(task_index); + switch (state) { + case eRunning: + task_state_string_index = 0; + break; + case eReady: + task_state_string_index = 1; + break; + case eBlocked: + task_state_string_index = 2; + break; + case eSuspended: + task_state_string_index = 3; + break; + default: + task_state_string_index = 4; + break; + } + + const char* buffer = &task_state_string[task_state_string_index][0]; + while (*buffer) { + esp_gdbstub_send_hex(*buffer, 8); + buffer++; + } + esp_gdbstub_send_end(); } From 5279e6814699a439e9f67a33d99285b4ef7b5f28 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Wed, 15 Apr 2020 17:24:12 -0300 Subject: [PATCH 3/5] gdbstub: improve format of info thread command output gdbstub: simplify the state handling on extra thread info --- components/esp_gdbstub/src/gdbstub.c | 50 ++++++++------------- components/freertos/include/freertos/task.h | 2 +- 2 files changed, 20 insertions(+), 32 deletions(-) diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c index b67ae273aa..67386c566b 100644 --- a/components/esp_gdbstub/src/gdbstub.c +++ b/components/esp_gdbstub/src/gdbstub.c @@ -76,7 +76,6 @@ void esp_gdbstub_panic_handler(esp_gdbstub_frame_t *frame) } } - static void send_reason(void) { esp_gdbstub_send_start(); @@ -90,6 +89,13 @@ static uint32_t gdbstub_hton(uint32_t i) return __builtin_bswap32(i); } +static void esp_gdbstub_send_str_as_hex(const char *str) +{ + while (*str) { + esp_gdbstub_send_hex(*str, 8); + str++; + } +} /** Send all registers to gdb */ static void handle_g_command(const unsigned char* cmd, int len) { @@ -179,10 +185,6 @@ static bool get_task_handle(size_t index, TaskHandle_t *handle) static eTaskState get_task_state(size_t index) { - if (index >= s_scratch.task_count) { - return eInvalid; - } - return s_scratch.tasks[index].eState; } @@ -288,14 +290,7 @@ static void handle_qsThreadInfo_command(const unsigned char* cmd, int len) /** qThreadExtraInfo requests the thread name */ static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) -{ - uint8_t task_state_string_index = 0; - const char task_state_string[][] = "Running", - "Ready", - "Blocked", - "Suspended", - "Invalid"; - +{ cmd += sizeof("qThreadExtraInfo,") - 1; int task_index = esp_gdbstub_gethex(&cmd, -1); TaskHandle_t handle; @@ -304,38 +299,31 @@ static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) return; } esp_gdbstub_send_start(); - const char* task_name = pcTaskGetTaskName(handle); - while (*task_name) { - esp_gdbstub_send_hex(*task_name, 8); - task_name++; - } - + esp_gdbstub_send_str_as_hex("Name: "); + esp_gdbstub_send_str_as_hex(pcTaskGetTaskName(handle)); esp_gdbstub_send_hex(' ', 8); - + eTaskState state = get_task_state(task_index); switch (state) { case eRunning: - task_state_string_index = 0; + esp_gdbstub_send_str_as_hex("State: Running"); break; case eReady: - task_state_string_index = 1; + esp_gdbstub_send_str_as_hex("State: Ready"); break; case eBlocked: - task_state_string_index = 2; + esp_gdbstub_send_str_as_hex("State: Blocked"); break; case eSuspended: - task_state_string_index = 3; + esp_gdbstub_send_str_as_hex("State: Suspended"); + break; + case eDeleted: + esp_gdbstub_send_str_as_hex("State: Deleted"); break; default: - task_state_string_index = 4; + esp_gdbstub_send_str_as_hex("State: Invalid"); break; } - - const char* buffer = &task_state_string[task_state_string_index][0]; - while (*buffer) { - esp_gdbstub_send_hex(*buffer, 8); - buffer++; - } esp_gdbstub_send_end(); } diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 982c6bfe69..7957d3b034 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -199,7 +199,7 @@ typedef struct xTASK_SNAPSHOT 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*/ - eTaskState eState; /*!< Current state of the task. Can be running or suspended */ + eTaskState eState; /*!< Current state of the task. Can be running or suspended */ } TaskSnapshot_t; /** From c296d01737fbce62423c507b00a3c4133b245a2e Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Thu, 16 Apr 2020 17:48:01 -0300 Subject: [PATCH 4/5] gdbstub: added cpu id of running tasks to the output --- components/esp_gdbstub/src/gdbstub.c | 13 ++++++++++++- components/freertos/include/freertos/task.h | 1 + components/freertos/tasks.c | 19 +++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c index 67386c566b..d4e8c9380c 100644 --- a/components/esp_gdbstub/src/gdbstub.c +++ b/components/esp_gdbstub/src/gdbstub.c @@ -22,6 +22,7 @@ static void init_task_info(void); static void find_paniced_task_index(void); static int handle_task_commands(unsigned char *cmd, int len); +static void esp_gdbstub_send_str_as_hex(const char *str); #endif static void send_reason(void); @@ -89,6 +90,7 @@ static uint32_t gdbstub_hton(uint32_t i) return __builtin_bswap32(i); } +#ifdef CONFIG_ESP_GDBSTUB_SUPPORT_TASKS static void esp_gdbstub_send_str_as_hex(const char *str) { while (*str) { @@ -96,6 +98,8 @@ static void esp_gdbstub_send_str_as_hex(const char *str) str++; } } +#endif + /** Send all registers to gdb */ static void handle_g_command(const unsigned char* cmd, int len) { @@ -188,6 +192,11 @@ static eTaskState get_task_state(size_t index) return s_scratch.tasks[index].eState; } +static int get_task_cpu_id(size_t index) +{ + return s_scratch.tasks[index].xCpuId; +} + /** Get the index of the task running on the current CPU, and save the result */ static void find_paniced_task_index(void) { @@ -306,7 +315,9 @@ static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) eTaskState state = get_task_state(task_index); switch (state) { case eRunning: - esp_gdbstub_send_str_as_hex("State: Running"); + esp_gdbstub_send_str_as_hex("State: Running "); + esp_gdbstub_send_str_as_hex("@CPU"); + esp_gdbstub_send_hex(get_task_cpu_id(task_index) + '0', 8); break; case eReady: esp_gdbstub_send_str_as_hex("State: Ready"); diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 7957d3b034..46863304a8 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -200,6 +200,7 @@ typedef struct xTASK_SNAPSHOT StackType_t *pxEndOfStack; /*!< Points to the end of the stack. pxTopOfStack < pxEndOfStack, stack grows hi2lo pxTopOfStack > pxEndOfStack, stack grows lo2hi*/ eTaskState eState; /*!< Current state of the task. Can be running or suspended */ + BaseType_t xCpuId; /*!< CPU where this task was running */ } TaskSnapshot_t; /** diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index d09e36e56e..210b6595a8 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -5058,6 +5058,25 @@ TickType_t uxReturn; pxTaskSnapshotArray[ *uxTask ].pxTCB = pxTCB; pxTaskSnapshotArray[ *uxTask ].pxTopOfStack = (StackType_t *)pxTCB->pxTopOfStack; pxTaskSnapshotArray[ *uxTask ].eState = eTaskGetState(pxTCB); + + if(pxTaskSnapshotArray[ *uxTask ].eState == eRunning) + { + BaseType_t xCoreId = xPortGetCoreID(); + /* task is running, let's find in which core it is located */ + if(pxTCB == pxCurrentTCB[xCoreId]) + { + pxTaskSnapshotArray[ *uxTask ].xCpuId = xCoreId; + } + else + { + pxTaskSnapshotArray[ *uxTask ].xCpuId = !xCoreId; + } + } + else + { + pxTaskSnapshotArray[ *uxTask ].xCpuId = -1; + } + #if( portSTACK_GROWTH < 0 ) { pxTaskSnapshotArray[ *uxTask ].pxEndOfStack = pxTCB->pxEndOfStack; From c78ddb770aedb48c17093b4d3f9741dc998fa1c6 Mon Sep 17 00:00:00 2001 From: Felipe Neves Date: Mon, 20 Apr 2020 14:10:23 -0300 Subject: [PATCH 5/5] docs: added information of task states on fatal errors documentation. --- components/esp_gdbstub/src/gdbstub.c | 2 +- docs/en/api-guides/fatal-errors.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/components/esp_gdbstub/src/gdbstub.c b/components/esp_gdbstub/src/gdbstub.c index d4e8c9380c..74b2c2d9d3 100644 --- a/components/esp_gdbstub/src/gdbstub.c +++ b/components/esp_gdbstub/src/gdbstub.c @@ -299,7 +299,7 @@ static void handle_qsThreadInfo_command(const unsigned char* cmd, int len) /** qThreadExtraInfo requests the thread name */ static void handle_qThreadExtraInfo_command(const unsigned char* cmd, int len) -{ +{ cmd += sizeof("qThreadExtraInfo,") - 1; int task_index = esp_gdbstub_gethex(&cmd, -1); TaskHandle_t handle; diff --git a/docs/en/api-guides/fatal-errors.rst b/docs/en/api-guides/fatal-errors.rst index 31657eac7e..579cc947ff 100644 --- a/docs/en/api-guides/fatal-errors.rst +++ b/docs/en/api-guides/fatal-errors.rst @@ -186,7 +186,7 @@ If :doc:`IDF Monitor ` is used, GDB is started automatically 36 *((int*) 0) = 0; (gdb) -GDB prompt can be used to inspect CPU registers, local and static variables, and arbitrary locations in memory. It is not possible to set breakpoints, change PC, or continue execution. To reset the program, exit GDB and perform external reset: Ctrl-T Ctrl-R in IDF Monitor, or using external reset button on the development board. +GDB prompt can be used to inspect CPU registers, local and static variables, state of created tasks by issuing "info thread" command on the GDB prompt, and arbitrary locations in memory. It is not possible to set breakpoints, change PC, or continue execution. To reset the program, exit GDB and perform external reset: Ctrl-T Ctrl-R in IDF Monitor, or using external reset button on the development board. Guru Meditation Errors ----------------------