pureboot: the classic megas' idle poll is a bit-skip — 7 cycles, and their stock window goes wide

The window gate's first full sweep caught it on the atmega8: 6.22 s
measured against 8 declared, the exact 7/9 of a poll modeled as an
extended-I/O lds + skip on a chip whose UCSRA sits in bit-addressable
I/O and compiles to a 2-cycle skip. poll_cycles now follows the status
register's home (7 below 0x40, 9 above). At 16 MHz over 7 cycles the
poll count no longer fits uint24_t, so the classic megas' stock windows
take the wide countdown — 8.000 s measured on all three, +4 B of stock
image (m8 362, m16/m32 364), README stock rows updated.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-30 16:11:34 +02:00
parent 8e7cc86fb3
commit 459d463283
2 changed files with 9 additions and 7 deletions

View File

@@ -35,9 +35,9 @@ without the trim the same loaders run 1030 B smaller.
| ATtiny25 † | 2 KiB | 0x0600 | software | 388 B | 446 B | | ATtiny25 † | 2 KiB | 0x0600 | software | 388 B | 446 B |
| ATtiny45 † | 4 KiB | 0x0e00 | software | 388 B | 446 B | | ATtiny45 † | 4 KiB | 0x0e00 | software | 388 B | 446 B |
| ATtiny85 † | 8 KiB | 0x1e00 | software | 388 B | 446 B | | ATtiny85 † | 8 KiB | 0x1e00 | software | 388 B | 446 B |
| ATmega8, 8A | 8 KiB | 0x1e00 | USART0 | 358 B | 476 B | | ATmega8, 8A | 8 KiB | 0x1e00 | USART0 | 362 B | 476 B |
| ATmega16, 16A | 16 KiB | 0x3e00 | USART0 | 360 B | 480 B | | ATmega16, 16A | 16 KiB | 0x3e00 | USART0 | 364 B | 480 B |
| ATmega32, 32A | 32 KiB | 0x7e00 | USART0 | 360 B | 480 B | | ATmega32, 32A | 32 KiB | 0x7e00 | USART0 | 364 B | 480 B |
| ATmega48, 48A, 48P, 48PA † | 4 KiB | 0x0e00 | USART0 | 378 B | 450 B | | ATmega48, 48A, 48P, 48PA † | 4 KiB | 0x0e00 | USART0 | 378 B | 450 B |
| ATmega88, 88A, 88P, 88PA | 8 KiB | 0x1e00 | USART0 | 388 B | 460 B | | ATmega88, 88A, 88P, 88PA | 8 KiB | 0x1e00 | USART0 | 388 B | 460 B |
| ATmega168, 168A, 168P, 168PA | 16 KiB | 0x3e00 | USART0 | 390 B | 464 B | | ATmega168, 168A, 168P, 168PA | 16 KiB | 0x3e00 | USART0 | 390 B | 464 B |

View File

@@ -172,10 +172,12 @@ struct hardware_link {
using uart = avr::uart::usart<usart_unit, C, {.baud = B, .max_baud_error = 2.5_pct}>; using uart = avr::uart::usart<usart_unit, C, {.baud = B, .max_baud_error = 2.5_pct}>;
// The compiled idle poll around the window's narrow (uint24_t) countdown: // The compiled idle poll around the window's narrow (uint24_t) countdown:
// lds UCSR0A (2), sbrc skipping the exit (2), sbiw + sbci + brne (5). // the RXC test, then sbiw + sbci + brne (5). The test's cost follows the
// A uint32_t countdown pays one more sbci — window_polls() adds it where // status register's home — a 2-cycle bit-skip where UCSRnA sits in
// the count forces the wide type. Held by the pureboot.window gate. // bit-addressable I/O (the classic megas), lds + skip (4) in extended
static constexpr std::uint8_t poll_cycles = 9; // I/O. A uint32_t countdown pays one more sbci — window_polls() adds it
// where the count forces the wide type. Held by the pureboot.window gate.
static constexpr std::uint8_t poll_cycles = avr::hw::usart_of<usart_unit>::ucsra::addr < 0x40 ? 7 : 9;
static void init() static void init()
{ {