Add memory diagnostics and optimize PSRAM usage

This commit is contained in:
2026-08-25 11:08:02 +02:00
parent f6a275c543
commit d779fb046e
7 changed files with 106 additions and 14 deletions
+7 -6
View File
@@ -74,13 +74,14 @@ ESP-IDF normally probes terminal cursor support once while constructing the UART
The project therefore preserves safe dumb mode until the first real UART byte arrives. Attach picoterm, picocom, minicom, PuTTY, or another ANSI-capable terminal and press Enter once. That empty line is consumed by the basic reader and promotes the next prompt to enhanced mode, enabling history, Delete, cursor keys, and completion without rebooting. This detects terminal activity rather than electrical USB attachment; a genuinely non-ANSI terminal is not automatically distinguishable on this hardware profile.
The root-level lifecycle command is:
The root-level system commands are:
```text
memory
reboot
```
It acknowledges the request, waits briefly for UART output to drain, and calls the ESP-IDF software restart. RAM-only serial or Wi-Fi changes are lost unless they were persisted first with `serial save` or `wifi save`.
`memory` reports current free space, a conservative aggregate of each matching region's lifetime minimum, and the largest contiguous block for internal 8-bit heap, the internal DMA-capable subset, and external PSRAM. It is intended for comparing idle state with concurrent USB, WebSocket, and SSH sessions. `reboot` acknowledges the request, waits briefly for UART output to drain, and calls the ESP-IDF software restart. RAM-only serial or Wi-Fi changes are lost unless they were persisted first with `serial save` or `wifi save`.
### Phase 1 serial service
@@ -136,7 +137,7 @@ broker read <client-id> [maximum-bytes]
broker events <client-id>
```
Each connection receives a generation-safe numeric ID. Stale IDs from disconnected clients cannot address a newly reused slot. Up to eight clients may connect, each with a bounded 4096-byte output queue and a 16-entry event queue.
Each connection receives a generation-safe numeric ID. Stale IDs from disconnected clients cannot address a newly reused slot. Up to eight clients may connect, each with a bounded 4096-byte output queue and a 16-entry event queue. The queue control structures remain in internal RAM, while their approximately 35 KiB of payload storage prefers PSRAM with internal fallback; queue semantics and bounds are unchanged.
UART RX is copied to every connected client. A full observer queue drops bytes only for that observer and records the loss; it never blocks UART reception or another client. With no clients, the broker still drains UART data and records it as unobserved.
@@ -416,7 +417,7 @@ ssh -o PreferredAuthentications=password -o PubkeyAuthentication=no admin@192.16
Compare OpenSSH's first-connection ECDSA fingerprint with `ssh host-key info` before accepting it. Once connected, all terminal bytes go directly to the physical RS-232 session. OpenSSH may print a one-time pre-authentication device banner; this is SSH protocol metadata and is not inserted into the serial stream.
The wolfSSH runtime has one owner task and two fixed session slots. A single owner serializes the managed component's `SINGLE_THREADED` build, avoids one large crypto stack per client, and services both nonblocking sessions fairly. The task has a 20 KiB internal stack; wolfSSL/wolfSSH dynamic allocations prefer external PSRAM and fall back to internal 8-bit memory. WolfCrypt's seed callback is installed after `wolfSSH_Init()` and routes all SSH RNG seeding through the project's serialized pre-radio CTR_DRBG instead of the registry component's default post-radio `esp_random()` path. HTTPS remains on ESP-IDF mbedTLS and is not switched to wolfSSL.
The wolfSSH runtime has one owner task and two fixed session slots. A single owner serializes the managed component's `SINGLE_THREADED` build, avoids one large crypto stack per client, and services both nonblocking sessions fairly. The task is pinned to CPU 1 so SSH key exchange and stream processing cannot monopolize the CPU 0 Wi-Fi/web path. It retains a 20 KiB internal stack because external task stacks are unsafe during flash/NVS cache-disable windows; `ssh status` reports its measured minimum-free stack space so this can be reduced later from hardware evidence rather than guesswork. wolfSSL/wolfSSH dynamic allocations prefer external PSRAM and fall back to internal 8-bit memory. Wi-Fi/lwIP payload allocations and broker observer/event payload queues also prefer PSRAM, preserving internal memory for DMA, task stacks, and control structures. WolfCrypt's seed callback is installed after `wolfSSH_Init()` and routes all SSH RNG seeding through the project's serialized pre-radio CTR_DRBG instead of the registry component's default post-radio `esp_random()` path. HTTPS remains on ESP-IDF mbedTLS and is not switched to wolfSSL.
The official Espressif registry baseline is pinned in `src/idf_component.yml` and `dependencies.lock`:
@@ -429,12 +430,12 @@ The build enables `CONFIG_ESP_ENABLE_WOLFSSH`, keeps `CONFIG_ESP_TLS_USING_MBEDT
#### SSH validation
1. Boot and confirm `ssh status` reports `running=yes`, TCP port 22, password authentication, and no sessions.
1. Boot and record `memory` plus `ssh status`; confirm SSH reports `running=yes`, TCP port 22, password authentication, no sessions, CPU 1 ownership, and a plausible nonzero stack minimum-free value.
2. Compare the first OpenSSH host-key prompt exactly with `ssh host-key info`; disconnect if it differs.
3. Verify a wrong password fails and the shared password from `web credentials show` succeeds.
4. Exercise text, NUL-containing/binary payloads, UTF-8, ANSI color, cursor-control sequences, and a full-screen terminal application through an RS-232 loopback or peer.
5. Confirm `ssh sessions`, `broker clients`, `ssh counters`, and serial counters reflect traffic and cleanup.
6. Connect a second SSH client. It should authenticate as an observer, receive identical UART output, and be unable to inject input while the first owns the writer lease.
6. Connect USB CDC as writer, then one WebSocket observer and one SSH observer. Re-run `memory` and `ssh status`; all transports should remain responsive, internal minimum-free/largest-block values should remain nonzero, and the SSH stack minimum-free value should show whether its 20 KiB allocation can later be reduced safely.
7. Test ownership against native USB and WebSocket clients, using UART0 `broker force-writer` for deterministic reassignment.
8. Run `ssh disconnect <session-id>` and verify the socket and broker client disappear without affecting another observer.
9. Leave an unauthenticated TCP/SSH client stalled and verify its slot closes after 15 seconds while an established session continues.