Skip to content

Commit 06d8c08

Browse files
DvdGiessendpgeorge
authored andcommitted
esp32/modesp32: Implement esp32.idf_task_info().
This adds a new function, `esp32.idf_task_info()`, that can be used to retrieve task statistics which is useful for diagnosing issues where some tasks are using up a lot of CPU time. It's best used in conjunction with the `utop` module from micropython-lib. Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
1 parent 10f6c06 commit 06d8c08

File tree

2 files changed

+69
-0
lines changed

2 files changed

+69
-0
lines changed

docs/library/esp32.rst

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,29 @@ Functions
8080
The result of :func:`gc.mem_free()` is the total of the current "free"
8181
and "max new split" values printed by :func:`micropython.mem_info()`.
8282

83+
.. function:: idf_task_info()
84+
85+
Returns information about running ESP-IDF/FreeRTOS tasks, which include
86+
MicroPython threads. This data is useful to gain insight into how much time
87+
tasks spend running or if they are blocked for significant parts of time,
88+
and to determine if allocated stacks are fully utilized or might be reduced.
89+
90+
``CONFIG_FREERTOS_USE_TRACE_FACILITY=y`` must be set in the board
91+
configuration to make this method available. Additionally configuring
92+
``CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y`` and
93+
``CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y`` is recommended to be able to
94+
retrieve the total and per-task runtime and the core ID respectively.
95+
96+
The return value is a 2-tuple where the first value is the total runtime,
97+
and the second a list of tasks. Each task is a 7-tuple containing: the task
98+
ID, name, current state, priority, runtime, stack high water mark, and the
99+
ID of the core it is running on. Runtime and core ID will be None when the
100+
respective FreeRTOS configuration option is not enabled.
101+
102+
.. note:: For an easier to use output based on this function you can use the
103+
`utop library <https://github.com/micropython/micropython-lib/tree/master/micropython/utop>`_,
104+
which implements a live overview similar to the Unix ``top`` command.
105+
83106

84107
Flash partitions
85108
----------------

ports/esp32/modesp32.c

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,49 @@ static mp_obj_t esp32_idf_heap_info(const mp_obj_t cap_in) {
212212
}
213213
static MP_DEFINE_CONST_FUN_OBJ_1(esp32_idf_heap_info_obj, esp32_idf_heap_info);
214214

215+
#if CONFIG_FREERTOS_USE_TRACE_FACILITY
216+
static mp_obj_t esp32_idf_task_info(void) {
217+
const size_t task_count_max = uxTaskGetNumberOfTasks();
218+
TaskStatus_t *task_array = m_new(TaskStatus_t, task_count_max);
219+
uint32_t total_time;
220+
const size_t task_count = uxTaskGetSystemState(task_array, task_count_max, &total_time);
221+
222+
mp_obj_list_t *task_list = MP_OBJ_TO_PTR(mp_obj_new_list(task_count, NULL));
223+
for (size_t i = 0; i < task_count; i++) {
224+
mp_obj_t task_data[] = {
225+
mp_obj_new_int_from_uint((mp_uint_t)task_array[i].xHandle),
226+
mp_obj_new_str(task_array[i].pcTaskName, strlen(task_array[i].pcTaskName)),
227+
MP_OBJ_NEW_SMALL_INT(task_array[i].eCurrentState),
228+
MP_OBJ_NEW_SMALL_INT(task_array[i].uxCurrentPriority),
229+
#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
230+
mp_obj_new_int_from_uint(task_array[i].ulRunTimeCounter),
231+
#else
232+
mp_const_none,
233+
#endif
234+
mp_obj_new_int_from_uint(task_array[i].usStackHighWaterMark),
235+
#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
236+
MP_OBJ_NEW_SMALL_INT(task_array[i].xCoreID),
237+
#else
238+
mp_const_none,
239+
#endif
240+
};
241+
task_list->items[i] = mp_obj_new_tuple(7, task_data);
242+
}
243+
244+
m_del(TaskStatus_t, task_array, task_count_max);
245+
mp_obj_t task_stats[] = {
246+
#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
247+
MP_OBJ_NEW_SMALL_INT(total_time),
248+
#else
249+
mp_const_none,
250+
#endif
251+
task_list
252+
};
253+
return mp_obj_new_tuple(2, task_stats);
254+
}
255+
static MP_DEFINE_CONST_FUN_OBJ_0(esp32_idf_task_info_obj, esp32_idf_task_info);
256+
#endif
257+
215258
static const mp_rom_map_elem_t esp32_module_globals_table[] = {
216259
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32) },
217260

@@ -228,6 +271,9 @@ static const mp_rom_map_elem_t esp32_module_globals_table[] = {
228271
{ MP_ROM_QSTR(MP_QSTR_mcu_temperature), MP_ROM_PTR(&esp32_mcu_temperature_obj) },
229272
#endif
230273
{ MP_ROM_QSTR(MP_QSTR_idf_heap_info), MP_ROM_PTR(&esp32_idf_heap_info_obj) },
274+
#if CONFIG_FREERTOS_USE_TRACE_FACILITY
275+
{ MP_ROM_QSTR(MP_QSTR_idf_task_info), MP_ROM_PTR(&esp32_idf_task_info_obj) },
276+
#endif
231277

232278
{ MP_ROM_QSTR(MP_QSTR_NVS), MP_ROM_PTR(&esp32_nvs_type) },
233279
{ MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) },

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy