Skip to content

Commit 0d60de6

Browse files
committed
utop: Add initial implementation for ESP32.
Signed-off-by: Daniël van de Giessen <daniel@dvdgiessen.nl>
1 parent 68e0dfc commit 0d60de6

File tree

3 files changed

+103
-0
lines changed

3 files changed

+103
-0
lines changed

micropython/utop/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# utop
2+
3+
Provides a top-like live overview of the running system.
4+
5+
On the `esp32` port this depends on the `esp32.idf_task_info()` function, which
6+
can be enabled by adding the following lines to the board `sdkconfig`:
7+
8+
```ini
9+
CONFIG_FREERTOS_USE_TRACE_FACILITY=y
10+
CONFIG_FREERTOS_VTASKLIST_INCLUDE_COREID=y
11+
CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS=y
12+
```

micropython/utop/manifest.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
metadata(
2+
version="0.1.0",
3+
description="Provides a top-like live overview of the running system.",
4+
)
5+
6+
module("utop.py")

micropython/utop/utop.py

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
import time
2+
3+
try:
4+
import esp32
5+
import _thread
6+
except ImportError:
7+
esp32 = None
8+
9+
10+
def top(update_interval_ms=1000, timeout_ms=None, thread_names={}):
11+
time_start = time.ticks_ms()
12+
previous_total_runtime = None
13+
previous_task_runtimes = {}
14+
previous_line_count = 0
15+
esp32_task_state_names = dict(
16+
enumerate(("running", "ready", "blocked", "suspended", "deleted", "invalid"))
17+
)
18+
19+
while timeout_ms is None or abs(time.ticks_diff(time.ticks_ms(), time_start)) < timeout_ms:
20+
if previous_line_count > 0:
21+
print("\x1b[{}A".format(previous_line_count), end="")
22+
line_count = 0
23+
24+
if esp32 is not None:
25+
if not hasattr(esp32, "idf_task_info"):
26+
print(
27+
"INFO: esp32.idf_task_info() is not available, cannot list active tasks.\x1b[K"
28+
)
29+
line_count += 1
30+
else:
31+
print(" CPU% CORE PRIORITY STATE STACKWATERMARK NAME\x1b[K")
32+
line_count += 1
33+
34+
total_runtime, tasks = esp32.idf_task_info()
35+
current_thread_id = _thread.get_ident()
36+
tasks.sort(key=lambda t: t[0])
37+
for (
38+
task_id,
39+
task_name,
40+
task_state,
41+
task_priority,
42+
task_runtime,
43+
task_stackhighwatermark,
44+
task_coreid,
45+
) in tasks:
46+
task_runtime_percentage = "-"
47+
if (
48+
total_runtime != previous_total_runtime
49+
and task_id in previous_task_runtimes
50+
):
51+
task_runtime_percentage = "{:.2f}%".format(
52+
100
53+
* ((task_runtime - previous_task_runtimes[task_id]) & (2**32 - 1))
54+
/ ((total_runtime - previous_total_runtime) & (2**32 - 1))
55+
)
56+
print(
57+
"{:>7} {:>4} {:>8d} {:<9} {:<14d} {}{}\x1b[K".format(
58+
task_runtime_percentage,
59+
"-" if task_coreid is None else task_coreid,
60+
task_priority,
61+
esp32_task_state_names.get(task_state, "unknown"),
62+
task_stackhighwatermark,
63+
thread_names.get(task_id, task_name),
64+
" (*)" if task_id == current_thread_id else "",
65+
)
66+
)
67+
line_count += 1
68+
69+
previous_task_runtimes[task_id] = task_runtime
70+
previous_total_runtime = total_runtime
71+
else:
72+
print("INFO: Platform does not support listing active tasks.\x1b[K")
73+
line_count += 1
74+
75+
if previous_line_count > line_count:
76+
for _ in range(previous_line_count - line_count):
77+
print("\x1b[K")
78+
print("\x1b[{}A".format(previous_line_count - line_count), end="")
79+
80+
previous_line_count = line_count
81+
82+
try:
83+
time.sleep_ms(update_interval_ms)
84+
except KeyboardInterrupt:
85+
break

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