Skip to content

Add HTTPS e2e test scaffolding + UCI networking notes - #21

Merged
JC-000 merged 8 commits into
masterfrom
docs/uci-networking-notes-and-https-test
May 6, 2026
Merged

Add HTTPS e2e test scaffolding + UCI networking notes#21
JC-000 merged 8 commits into
masterfrom
docs/uci-networking-notes-and-https-test

Conversation

@JC-000

Copy link
Copy Markdown
Owner

Summary

Adds an HTTPS e2e test harness for the UCI backend and records lessons from the recent investigation of TLS-at-48-MHz behaviour.

  • tools/uci/test_https_local.py — end-to-end HTTPS test against a local Python TLS listener. Reuses the ECDSA-P256 self-signed cert from tools/https_e2e/certs/, DMAs a 6502 stub that calls http_get, flips the U64E to 48 MHz turbo, captures a full diagnostic block on both pass and timeout paths, and optionally streams the 6510 bus with bounded capture (DEBUG_CAPTURE=1) using the max_bytes= / filter= kwargs added to c64-test-harness's DebugCapture in Add bounded capture options to DebugCapture (max_bytes, filter) c64-test-harness#56 .

  • CLAUDE.md — adds a note about the test, a known-issue entry for the TLS 1.3 handshake stall it exposes, and a design requirement that any future bounded-timeout work on the UCI spin-wait helpers must use a wall-clock time source.

Context on the known issue

Master is reliable for DHCP and plain HTTP at all turbo speeds (1 MHz through 48 MHz). HTTPS / TLS 1.3 handshake at 48 MHz reproducibly stalls at tls_state=0x03 after the server completes its flight — root cause is not yet identified. This PR does not attempt a fix; it only lands the scaffolding and the notes so a future effort has a running start.

Test plan

  • make BACKEND=uci builds cleanly.
  • python3 tools/uci/test_http_local.py passes on a real U64E (DHCP succeeds at turbo, plain-HTTP GET returns the expected body) — confirms master baseline.
  • python3 tools/uci/test_https_local.py reaches tls_state=0x03 (and then times out — that's the known issue this test was written to capture).

🤖 Generated with Claude Code


Originally posted by @JC-000 on 2026-04-17

JC-000and others added 8 commits April 16, 2026 15:33
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UCI banner: ULTIMATE 64 ELITE (UCI) → UCI NETWORKING
Insert 16 NOPs after every STA to UCI_CONTROL/UCI_CMD_DATA via a
uci_fence macro defined in uci_regs.inc. At 48 MHz, 16 NOPs = 32
cycles = ~0.67us, giving the FPGA time to latch each write. At 1 MHz
the overhead is 32us per write -- negligible for networking. Unlike
the LDA UCI_STATUS fence approach, NOPs cannot interfere with the
UCI state machine.
11 fence sites total: 8 in uci_cmd.s (uci_abort, uci_begin_cmd,
uci_put_byte, uci_push_wait, uci_check_err CLR_ERR, uci_drain_resp
NEXT_DATA, uci_drain_status NEXT_DATA, uci_ack) and 3 in net.s
(hostname write loop, null terminator, send data loop).
Test results on U64E hardware:
- 1 MHz: PASS (HTTP 200, body "HELLO FROM TEST SERVER")
- 48 MHz: FAIL (write-side fencing alone is insufficient; read-side
timing also needs work at turbo -- follow-up needed)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Three categories of changes for turbo-speed UCI register access:
1. Read-side fencing: uci_fence (48 NOPs) after every LDA from
$DF1C-$DF1F — UCI_STATUS, UCI_ID, UCI_RESP_DATA, UCI_STATUS_DATA.
Without this, reads return stale/glitched values at 8+ MHz.
2. Post-PUSH_CMD settle delay: 255-iteration delay loop in
uci_push_wait so the FPGA has time to latch the command and
assert CMD_BUSY before the CPU starts polling. At 48 MHz the
original uci_fence alone was only 2 us — the FPGA needs ~27 us.
3. 16-bit spin-wait in uci_read_resp_bytes: DATA_AV may not be set
immediately after push_wait returns (e.g. TCP_CONNECT waits for
a full network round-trip). The old code bailed on the first
DATA_AV=0; the new code spins up to 65536 iterations (~150 ms
at 48 MHz) before giving up.
Also bumped uci_fence from 16 to 48 NOPs (0.67 us -> 2 us at 48 MHz)
and converted two short branches to JMPs to fix range errors caused
by the larger fence expansions.
Verified: both BACKEND=uci and default ip65 builds succeed.
1 MHz baseline HTTP test passes. 48 MHz testing blocked on U64
power cycle — to be verified after device recovery.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The FPGA needs ~38 µs of wall-clock time between UCI register
accesses. A 48-NOP sled (2 µs at 48 MHz) was far too short, and
even a 256-NOP sled (10.7 µs at 48 MHz, the max that fits in
the code segment) was insufficient.
Replace the NOP sled with a nested delay loop (OUTER=5, INNER=100,
~2525 cycles = ~52 µs at 48 MHz, ~2.5 ms at 1 MHz). Binary search
found the minimum at OUTER=3 INNER=122 (~38.4 µs); the chosen
values provide 35% margin. Verified passing at both 1 MHz and
48 MHz on U64E hardware.
Also convert all branches that span a fence expansion to JMP
trampolines, since even the 14-byte delay loop can exceed the
8-bit branch range in tight loops.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update CLAUDE.md to reflect that UCI networking works at 48 MHz
turbo via a nested delay-loop fence (~52us per UCI register access).
All four test scenarios pass on real U64E: 22B and 1460B responses
at both 1 MHz and 48 MHz.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
UCI NOP-sled fencing for turbo speed support
- tools/uci/test_https_local.py: reusable HTTPS e2e harness that runs a
local TLS 1.3 listener, DMAs a 6502 stub calling http_get, toggles 48
MHz turbo, captures full post-run diagnostics, and optionally streams
the 6510 bus (DEBUG_CAPTURE=1) with bounded capture for post-mortem.
Reproducibly exposes an unresolved TLS 1.3 handshake stall at
tls_state=0x03 on real U64E at 48 MHz.
- CLAUDE.md: note the new test, record the TLS stall as a known issue,
and document the wall-clock-vs-cycle-count design requirement for any
future bounded-timeout work on the UCI adapter.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@JC-000
JC-000 merged commit 5750d99 into masterMay 6, 2026
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant

@JC-000