Skip to content

perf(wire): the ENC28J60 sends a frame while the one before is on the wire - #276

Merged
angeloINTJ merged 1 commit into
mainfrom
perf/enc28j60-two-tx-frames
Oct 15, 2026
Merged

angeloINTJ merged 1 commit into
mainfrom
perf/enc28j60-two-tx-frames

Conversation

@angeloINTJ

Copy link
Copy Markdown
Owner

The SIMUT Wire's ENC28J60 module moves its receive buffer from 0x1A00 to 0x141C, the default of PicoENC28J60 since 1.3.0. It now receives three full-size frames instead of four, and has room for two to send from. The library's lwIP interface needs that room to put a frame into the chip while the one before is on the wire; #275 kept 0x1A00, with room for one, for the maintainer to choose.

0x1A00 was there for flash writes. They hold the interrupts off, and four frames is as many as TCP_WND lets a sender have in flight. So the test that matters is a receive with flash writes in it, next to the sending that this change speeds up.

Tests on the bench, 2026-10-15

The target is a Pico W with an ENC28J60 on the cable, INT on GP11, library 1.3.1, and no other client on the port. Each image of main runs against the same image with this change.

pico_wiretft (main 9ab9e315 against 8f3886c2, the image this branch builds)

0x1A00 0x141C
32 KB upload, written to LittleFS while it arrives; medians of 3 runs of 20, each file read back and compared 1,598 / 1,636 / 1,648 ms 1,635 / 1,590 / 1,620 ms
/lang.js, 12.4 KB, one download at a time; medians of 50 33.8 / 33.7 / 33.8 ms 32.2 / 32.4 ms
/login, 6.7 KB 22.9 ms 22.0 ms
four clients fetching pages on fresh connections for 300 s 10,051 / 9,667 / 9,076 pages 10,444 / 10,554 pages
/api/status reader beside that load, median 108–121 ms 105–109 ms
HTTPS with a bench pair: lone requests / reads on one connection 20 of 20 / 1,000 of 1,000, 31 ms 20 of 20 / 1,000 of 1,000, 31 ms

pico_wire (main f7be7f4b against 3fe223cb)

0x1A00 0x141C
32 KB upload, medians 1,733 / 1,735 ms 1,685 ms
/lang.js 33.2 ms 31.7 ms

What the tests show

  • Uploads: the same with either buffer.
  • Sending: about 4% faster one download at a time, and about 9% more pages under the four-client load.
  • Failures: no run had a failed request, a tcp_write sem memoria or a restart.
  • Unchanged behaviour: on both images, 1,000 reads of /api/status on one connection, the 34-route GET sweep (status, headers and chunk count) and the reboot reply ({"ok":true}, whole, over HTTP and over TLS) are what they were.

The load and download clients close each connection once the body is whole, as a browser does. A client that waits for the device to close measures HTTP_MAX_CLOSE_WAIT instead (#274).

On the host

  • Sizes: flash used, .bin and RAM of both wired images are main's. The budgets and the OTA headroom table do not move.
  • Radio images: the seven are byte for byte main's (17bd31c), compared by sha256. The header is compiled only where SIMUT_NET_ENC28J60 is set.
  • Gates: the gates job, run locally, has 45 steps OK.

Not covered

  • OTA: a stage, a 600 KB receive into flash, was not run on the bench; the 32 KB uploads stand in for it.
  • Soak: no long soak ran. The longest run was the 300 s load.

🤖 Generated with Claude Code

https://claude.ai/code/session_013C6NHM2fJi3M7EMr47WyQ3

… wire

src/net/Enc28j60Device.h takes the module's receive buffer from 0x1A00 to
0x141C, the default of PicoENC28J60 since 1.3.0. That is three full-size
frames to receive instead of four, and room for two to send from. The
library's lwIP interface needs two to put a frame into the chip while the
one before is on the wire. #275 kept 0x1A00, and its room for one frame,
for the maintainer to choose.

0x1A00 was there for flash writes: they hold the interrupts off, and four
frames is as many as TCP_WND lets a sender have in flight. Measured on the
bench on 2026-10-15: a Pico W with an ENC28J60 on the cable, INT on GP11,
library 1.3.1, no other client. main against this change:

pico_wiretft (9ab9e315 against 8f3886c2, the image these lines build):
- 32 KB uploads, written to LittleFS while they arrive, 3 runs of 20,
  each read back whole: medians 1,598 / 1,636 / 1,648 ms against
  1,635 / 1,590 / 1,620. The same.
- /lang.js (12.4 KB), one download at a time: 33.8 ms against 32.3.
- Four clients fetching pages on fresh connections for 300 s:
  10,051 / 9,667 / 9,076 pages against 10,444 / 10,554.
- HTTPS with a bench pair: 20 of 20 requests on fresh connections, and
  1,000 of 1,000 reads on one, at a 31 ms median on both.

pico_wire (f7be7f4b against 3fe223cb):
- Uploads: 1,733 / 1,735 ms against 1,685.
- /lang.js: 33.2 ms against 31.7.

No run had a failure, a tcp_write out of memory or a restart. On both
images, 1,000 reads of /api/status, the 34-route sweep and the reboot
reply are what they were.

Sizes do not change: flash used, .bin and RAM of both wired images are
main's. The seven radio images are byte for byte main's (17bd31c),
compared by sha256. The gates job, run locally, has 45 steps OK.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013C6NHM2fJi3M7EMr47WyQ3
@github-actions github-actions Bot added the code Firmware source changes (src/, WebUI.h) label Oct 15, 2026
@angeloINTJ
angeloINTJ merged commit d5f7063 into main Oct 15, 2026
13 checks passed
@angeloINTJ
angeloINTJ deleted the perf/enc28j60-two-tx-frames branch October 15, 2026 22:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

code Firmware source changes (src/, WebUI.h)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant