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>
This commit is contained in:
Daniël van de Giessen
2022-03-01 22:29:58 +01:00
committed by Damien George
parent 10f6c0699e
commit 06d8c084b9
2 changed files with 69 additions and 0 deletions

View File

@@ -80,6 +80,29 @@ Functions
The result of :func:`gc.mem_free()` is the total of the current "free"
and "max new split" values printed by :func:`micropython.mem_info()`.
.. function:: idf_task_info()
Returns information about running ESP-IDF/FreeRTOS tasks, which include
MicroPython threads. This data is useful to gain insight into how much time
tasks spend running or if they are blocked for significant parts of time,
and to determine if allocated stacks are fully utilized or might be reduced.
``CONFIG_FREERTOS_USE_TRACE_FACILITY=y`` must be set in the board
configuration to make this method available. Additionally configuring
``CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y`` and
``CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y`` is recommended to be able to
retrieve the total and per-task runtime and the core ID respectively.
The return value is a 2-tuple where the first value is the total runtime,
and the second a list of tasks. Each task is a 7-tuple containing: the task
ID, name, current state, priority, runtime, stack high water mark, and the
ID of the core it is running on. Runtime and core ID will be None when the
respective FreeRTOS configuration option is not enabled.
.. note:: For an easier to use output based on this function you can use the
`utop library <https://github.com/micropython/micropython-lib/tree/master/micropython/utop>`_,
which implements a live overview similar to the Unix ``top`` command.
Flash partitions
----------------

View File

@@ -212,6 +212,49 @@ static mp_obj_t esp32_idf_heap_info(const mp_obj_t cap_in) {
}
static MP_DEFINE_CONST_FUN_OBJ_1(esp32_idf_heap_info_obj, esp32_idf_heap_info);
#if CONFIG_FREERTOS_USE_TRACE_FACILITY
static mp_obj_t esp32_idf_task_info(void) {
const size_t task_count_max = uxTaskGetNumberOfTasks();
TaskStatus_t *task_array = m_new(TaskStatus_t, task_count_max);
uint32_t total_time;
const size_t task_count = uxTaskGetSystemState(task_array, task_count_max, &total_time);
mp_obj_list_t *task_list = MP_OBJ_TO_PTR(mp_obj_new_list(task_count, NULL));
for (size_t i = 0; i < task_count; i++) {
mp_obj_t task_data[] = {
mp_obj_new_int_from_uint((mp_uint_t)task_array[i].xHandle),
mp_obj_new_str(task_array[i].pcTaskName, strlen(task_array[i].pcTaskName)),
MP_OBJ_NEW_SMALL_INT(task_array[i].eCurrentState),
MP_OBJ_NEW_SMALL_INT(task_array[i].uxCurrentPriority),
#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
mp_obj_new_int_from_uint(task_array[i].ulRunTimeCounter),
#else
mp_const_none,
#endif
mp_obj_new_int_from_uint(task_array[i].usStackHighWaterMark),
#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
MP_OBJ_NEW_SMALL_INT(task_array[i].xCoreID),
#else
mp_const_none,
#endif
};
task_list->items[i] = mp_obj_new_tuple(7, task_data);
}
m_del(TaskStatus_t, task_array, task_count_max);
mp_obj_t task_stats[] = {
#if CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
MP_OBJ_NEW_SMALL_INT(total_time),
#else
mp_const_none,
#endif
task_list
};
return mp_obj_new_tuple(2, task_stats);
}
static MP_DEFINE_CONST_FUN_OBJ_0(esp32_idf_task_info_obj, esp32_idf_task_info);
#endif
static const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32) },
@@ -228,6 +271,9 @@ static const mp_rom_map_elem_t esp32_module_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR_mcu_temperature), MP_ROM_PTR(&esp32_mcu_temperature_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_idf_heap_info), MP_ROM_PTR(&esp32_idf_heap_info_obj) },
#if CONFIG_FREERTOS_USE_TRACE_FACILITY
{ MP_ROM_QSTR(MP_QSTR_idf_task_info), MP_ROM_PTR(&esp32_idf_task_info_obj) },
#endif
{ MP_ROM_QSTR(MP_QSTR_NVS), MP_ROM_PTR(&esp32_nvs_type) },
{ MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) },