S1 #11: the System App: tasks, memory, network and system, live

Five views, Tab between them: Overview (each core's load, memory,
traffic, battery, two minutes of load), Tasks (share of a core over the
last second, lowest free stack, flagged under 512 bytes; `s` sorts),
Memory (free heap against the floors of Q86), Network (bytes per
service, and what's moving now), System (what `info` prints, plus
battery, card, radio, GNSS). It samples once a second and keeps history
only while open.

The arithmetic is host-tested, including the trap found on the device: a
task's run-time counter only moves when it's switched out, so the task
that samples (the main loop, alone on its core) gets what's left of its
core. `tasks` now samples across a second of normal running instead of
inside its own wait. The main loop uses 100 % of core 1 at rest (#40).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EhqxQ49eCju4CzKYNjZzwT
This commit is contained in:
2026-10-06 01:28:26 +02:00
co-authored by Claude Opus 5.5
parent 70bb2a4137
commit e36aa50922
10 changed files with 812 additions and 12 deletions
+12 -1
View File
@@ -1,6 +1,6 @@
# S1 — System basics
**Status:** in progress. The SD driver fix shipped in v0.6.1 (issue #21, ADR 0007), and fixed IPv4 settings in v0.7.0 (issue #7). The System Monitor (#11) hasn't started; issue #39 follows the SD driver upstream.
**Status:** in progress (branch `s1`). The SD driver fix shipped in v0.6.1 (issue #21, ADR 0007), and fixed IPv4 settings in v0.7.0 (issue #7). The System Monitor (#11) is built and checked on the device. Issue #39 follows the SD driver upstream, and #40 the main loop's CPU use.
**Goal:** the device works on any network, the card can be trusted, and you can see what the system is doing. A side milestone, like G1.
@@ -79,3 +79,14 @@ Every milestone so far was driven by measurements, heap floors, stack sizes, TLS
| Q125 | `info` and `tasks` are split into a **snapshot** that the console and the App share; the arithmetic (shares from two samples, sorting, the stack warning) is host-tested. |
| Q126 | Left out: acting on tasks, an event log, exporting snapshots to the card. |
| Q127 | The main loop uses about 81 % of a core. The App shows it; fixing it is issue #40, not part of #11. |
The App has five views, not four: Q121's network view is one of its own (Overview, Tasks, Memory, Network, System).
### Measured (2026-10-06)
- **Traffic counters are exact.** A Gemini fetch of a 164,970-byte page counts 164,986 bytes in (the page and its 16-byte header line) and 42 out (the 40-character URL and CRLF). A 1,797,760-byte upload counts 1,798,123 in for the Debug Console, commands included.
- **The Memory view shows a TLS dip as it happens.** Starting IRC and a 165 KB Gemini fetch together: free heap falls from about 100 KB through the three floors to a low of 12.1 KB, then settles near 50 KB. That's the dip accepted in G1 (Q86).
- **A run-time counter only moves when its task is switched out.** FreeRTOS adds to a task's run time at the context switch. The main loop takes the samples, and with core 1 to itself it's never switched out: its counter said 2 % while the core's idle task had 0 %. So the task that samples gets what's left of its core. With that: **the main loop uses 100 % of core 1 at rest** (issue #40 said 81 %, an average since boot).
- **`tasks` on the console** sampled twice inside one command at first, a quarter second apart, and showed the loop at 1 %: it was asleep in the command's own wait. It now samples, lets the loop run for a second, and prints.
- **Low stack, flagged:** `IDLE0` (232 bytes left), `IDLE1` (328 to 352) and `spk_task` (256 to 264), all the framework's own tasks.
- **Cost:** 15.6 KB of flash for the App and the counters (1,742,723 bytes, release). Nothing while it's closed; about 2 KB of history and samples while it's open.