From c535c4756c6d655efe0686b9e9c7c6afd1384af9 Mon Sep 17 00:00:00 2001 From: BlackMark Date: Tue, 28 Jul 2026 14:47:29 +0200 Subject: [PATCH] pureboot: the activation countdown in the narrowest type that holds it MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The fixed-baud window counted down a uint32 where almost every window fits 24 bits; the countdown now takes avr::uint24_t when the poll budget allows (the autobaud budget's own choice), uint32 past 16.7M polls — four bytes off every fixed-baud image on every chip, the full suites green on the changed window. The README size table is refreshed — its autobaud column had also gone stale by the no-assembly pass's measurement-loop win, which nothing gated: sizes.py check-readme now runs as the gate's final stage, where every tree is freshly built and the table can actually be held. Co-Authored-By: Claude Fable 5 --- ide/README.md | 2 +- pureboot/README.md | 32 ++++++++++++++++---------------- pureboot/pureboot.cpp | 7 ++++++- tools/check.sh | 6 ++++++ 4 files changed, 29 insertions(+), 18 deletions(-) diff --git a/ide/README.md b/ide/README.md index acf6263..c55d583 100644 --- a/ide/README.md +++ b/ide/README.md @@ -2,7 +2,7 @@ `master` carries `bootloader.atsln`, so this branch does too: `ide/bootloader.atsln` builds the loaders from the same sources Ninja does, to a **byte-identical -`.text`** — 404 B for the 328P pureboot loader, 510 B for the `tsb_asm` tier in +`.text`** — 400 B for the 328P pureboot loader, 510 B for the `tsb_asm` tier in its 512-byte section. CMake remains the build system; the solution is here so the port opens in Studio as its predecessor did. diff --git a/pureboot/README.md b/pureboot/README.md index ac90704..3d0a411 100644 --- a/pureboot/README.md +++ b/pureboot/README.md @@ -28,21 +28,21 @@ it carries the calibration machinery and no clock at all. | Chip | Flash | Loader at | Link | Stock | Autobaud | |---|---|---|---|---|---| -| ATtiny13, ATtiny13A † | 1 KiB | 0x0200 | software | 394 B | 464 B | -| ATtiny25 † | 2 KiB | 0x0600 | software | 398 B | 468 B | -| ATtiny45 † | 4 KiB | 0x0e00 | software | 402 B | 472 B | -| ATtiny85 † | 8 KiB | 0x1e00 | software | 402 B | 472 B | -| ATmega8, 8A | 8 KiB | 0x1e00 | USART0 | 364 B | 478 B | -| ATmega16, 16A | 16 KiB | 0x3e00 | USART0 | 366 B | 482 B | -| ATmega32, 32A | 32 KiB | 0x7e00 | USART0 | 366 B | 482 B | -| ATmega48, 48A, 48P, 48PA † | 4 KiB | 0x0e00 | USART0 | 392 B | 468 B | -| ATmega88, 88A, 88P, 88PA | 8 KiB | 0x1e00 | USART0 | 402 B | 478 B | -| ATmega168, 168A, 168P, 168PA | 16 KiB | 0x3e00 | USART0 | 404 B | 482 B | -| ATmega328, 328P | 32 KiB | 0x7e00 | USART0 | 404 B | 482 B | -| ATmega164A, 164P, 164PA | 16 KiB | 0x3e00 | USART0 | 404 B | 482 B | -| ATmega324A, 324P, 324PA | 32 KiB | 0x7e00 | USART0 | 404 B | 482 B | -| ATmega644, 644A, 644P, 644PA | 64 KiB | 0xfe00 | USART0 | 398 B | 476 B | -| ATmega1284, 1284P | 128 KiB | 0x1fe00 | USART0 | 424 B | 502 B | +| ATtiny13, ATtiny13A † | 1 KiB | 0x0200 | software | 390 B | 460 B | +| ATtiny25 † | 2 KiB | 0x0600 | software | 394 B | 464 B | +| ATtiny45 † | 4 KiB | 0x0e00 | software | 398 B | 468 B | +| ATtiny85 † | 8 KiB | 0x1e00 | software | 398 B | 468 B | +| ATmega8, 8A | 8 KiB | 0x1e00 | USART0 | 360 B | 474 B | +| ATmega16, 16A | 16 KiB | 0x3e00 | USART0 | 362 B | 480 B | +| ATmega32, 32A | 32 KiB | 0x7e00 | USART0 | 362 B | 480 B | +| ATmega48, 48A, 48P, 48PA † | 4 KiB | 0x0e00 | USART0 | 388 B | 464 B | +| ATmega88, 88A, 88P, 88PA | 8 KiB | 0x1e00 | USART0 | 398 B | 474 B | +| ATmega168, 168A, 168P, 168PA | 16 KiB | 0x3e00 | USART0 | 400 B | 480 B | +| ATmega328, 328P | 32 KiB | 0x7e00 | USART0 | 400 B | 480 B | +| ATmega164A, 164P, 164PA | 16 KiB | 0x3e00 | USART0 | 400 B | 480 B | +| ATmega324A, 324P, 324PA | 32 KiB | 0x7e00 | USART0 | 400 B | 480 B | +| ATmega644, 644A, 644P, 644PA | 64 KiB | 0xfe00 | USART0 | 394 B | 474 B | +| ATmega1284, 1284P | 128 KiB | 0x1fe00 | USART0 | 420 B | 500 B | † No hardware boot section: the host patches the reset vector, and the budget is 510 bytes, since the slot's last word is the trampoline. @@ -52,7 +52,7 @@ USART's own pins with the `OSCCAL` trim baked, 510 of its 512 — they alone carry the far-flash machinery (ELPM reads, RAMPZ page commands), autobaud alone carries the calibration loop, a bit-banged link on a USART's pins alone has to release it (below), and the trim adds its one register write. Without -the trim that build is 504; on the default pins, 502. The flash bank riding +the trim that build is 504; on the default pins, 500. The flash bank riding in a transfer's selector byte keeps even those chips' addressing the same 16-bit form every other chip uses, which is why they are no longer the outlier they were. diff --git a/pureboot/pureboot.cpp b/pureboot/pureboot.cpp index c521b8f..964d8ea 100644 --- a/pureboot/pureboot.cpp +++ b/pureboot/pureboot.cpp @@ -351,9 +351,14 @@ consteval std::uint32_t window_polls() return timeout_seconds * static_cast(dev::clock.hz / link::poll_cycles); } +// The countdown in the narrowest type that holds it: a fourth byte would +// cost a wider decrement chain at every poll for range most windows never +// use (the autobaud budget makes the same choice). +using window_t = std::conditional_t; + bool pending_before_deadline() { - std::uint32_t polls = window_polls(); + window_t polls = window_polls(); do { if (link::pending()) return true; diff --git a/tools/check.sh b/tools/check.sh index e797297..05beb1e 100755 --- a/tools/check.sh +++ b/tools/check.sh @@ -36,4 +36,10 @@ if ((full)); then done fi +# Every tree is freshly built now — the one moment the README's size table +# can be held to what the images measure (a per-preset ctest sees only its +# own chip; the table needs all of them, and ungated it drifts: a +# common-code shave moves every row at once with nothing over budget). +python3 tools/sizes.py check-readme + echo "check: every chip green"