8000 esp32/modesp32: Implement idf_task_stats(). · micropython/micropython@fa7c95b · GitHub
[go: up one dir, main page]

Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit fa7c95b

Browse files
committed
esp32/modesp32: Implement idf_task_stats().
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
1 parent f498a16 commit fa7c95b

File tree

2 files changed

+95
-0
lines changed

2 files changed

+95
-0
lines changed

docs/library/esp32.rst

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,28 @@ 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_stats()
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 setting
92+
``CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y`` and
93+
``CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y`` is recommended to be able to
94+
retrieve the core id and runtime 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.
100+
101+
.. note:: For an easier to use output based on this function you can use the
102+
`utop library <https://github.com/micropython/micropython-lib/tree/master/micropython/utop>`,
103+
which implements a live overview similar to the Unix ``top`` command.
104+
83105

84106
Flash partitions
85107
----------------
@@ -93,6 +115,43 @@ methods to enable over-the-air (OTA) updates.
93115
of the partition to retrieve, or one of the constants: ``BOOT`` or ``RUNNING``.
94116
*block_size* specifies the byte size of an individual block.
95117

118+
119+
/**
120+
* @brief Register a partition on an external flash chip
121+
*
122+
* This API allows designating certain areas of external flash chips (identified by the esp_flash_t structure)
123+
* as partitions. This allows using them with components which access SPI flash through the esp_partition API.
124+
*
125+
* @param flash_chip Pointer to the structure identifying the flash chip
126+
* @param offset Address in bytes, where the partition starts
127+
* @param size Size of the partition in bytes
128+
* @param label Partition name
129+
* @param type One of the partition types (ESP_PARTITION_TYPE_*), or an integer. Note that applications can not be booted from external flash
130+
* chips, so using ESP_PARTITION_TYPE_APP is not supported.
131+
* @param subtype One of the partition subtypes (ESP_PARTITION_SUBTYPE_*), or an integer.
132+
* @param[out] out_partition Output, if non-NULL, receives the pointer to the resulting esp_partition_t structure
133+
* @return
134+
* - ESP_OK on success
135+
* - ESP_ERR_NO_MEM if memory allocation has failed
136+
* - ESP_ERR_INVALID_ARG if the new partition overlaps another partition on the same flash chip
137+
* - ESP_ERR_INVALID_SIZE if the partition doesn't fit into the flash chip size
138+
*/
139+
// esp_err_t esp_partition_register_external(esp_flash_t* flash_chip, size_t offset, size_t size,
140+
// const char* label, esp_partition_type_t type, esp_partition_subtype_t subtype,
141+
// const esp_partition_t** out_partition);
142+
143+
.. classmethod:: Partition.register(offset, size, label=None, type=TYPE_DATA, subtype=0x06, block_size=4096)
144+
145+
Register a new partition that isn't specified in the partition table. Useful for
146+
accessing data outside of the defined partitions. Returns a Partition object.
147+
148+
*block_size* specifies the byte size of an individual block used by the returned
149+
object.
150+
151+
.. method:: Partition.deregister()
152+
153+
Deregisters a previously registered partition.
154+
96155
.. classmethod:: Partition.find(type=TYPE_APP, subtype=0xff, label=None, block_size=4096)
97156

98157
Find a partition specified by *type*, *subtype* and *label*. Returns a

ports/esp32/modesp32.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,39 @@ 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_stats(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_t task_list = mp_obj_new_list(0, 0);
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+
mp_obj_new_int_from_uint(task_array[i].ulRunTimeCounter),
230+
mp_obj_new_int_from_uint(task_array[i].usStackHighWaterMark),
231+
#if CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID
232+
MP_OBJ_NEW_SMALL_INT(task_array[i].xCoreID),
233+
#else
234+
mp_const_none,
235+
#endif
236+
};
237+
mp_obj_t task = mp_obj_new_tuple(7, task_data);
238+
mp_obj_list_append(task_list, task);
239+
}
240+
241+
m_del(TaskStatus_t, task_array, task_count_max);
242+
mp_obj_t task_stats[] = { MP_OBJ_NEW_SMALL_INT(total_time), task_list };
243+
return mp_obj_new_tuple(2, task_stats);
244+
}
245+
static MP_DEFINE_CONST_FUN_OBJ_0(esp32_idf_task_stats_obj, esp32_idf_task_stats);
246+
#endif
247+
215248
static const mp_rom_map_elem_t esp32_module_globals_table[] = {
216249
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_esp32) },
217250

@@ -228,6 +261,9 @@ static const mp_rom_map_elem_t esp32_module_globals_table[] = {
228261
{ MP_ROM_QSTR(MP_QSTR_mcu_temperature), MP_ROM_PTR(&esp32_mcu_temperature_obj) },
229262
#endif
230263
{ MP_ROM_QSTR(MP_QSTR_idf_heap_info), MP_ROM_PTR(&esp32_idf_heap_info_obj) },
264+
#if CONFIG_FREERTOS_USE_TRACE_FACILITY
265+
{ MP_ROM_QSTR(MP_QSTR_idf_task_stats), MP_ROM_PTR(&esp32_idf_task_stats_obj) },
266+
#endif
231267

232268
{ MP_ROM_QSTR(MP_QSTR_NVS), MP_ROM_PTR(&esp32_nvs_type) },
233269
{ MP_ROM_QSTR(MP_QSTR_Partition), MP_ROM_PTR(&esp32_partition_type) },

0 commit comments

Comments
 (0)
0