pureboot 6: a build-time OSCCAL trim, applied ahead of every reset path
The RC-oscillator answer's device half (dev/tasks.md in libavr): OSCCAL joins pureboot_add_loader() as one optional byte, written at the top of run() before the WDRF bail so the watchdog hand-over inherits the corrected clock too. Orthogonal to the backend — an autobaud build may carry it purely for the application. No value, no code: the stock image differs from v5 in exactly the version's two bytes (the stamp and the 'b' immediate). Measured: +6 B where OSCCAL takes sts (328P, 404→410), +4 B in low I/O (t85, 402→406); the tightest image in the space (1284 autobaud on USART pins, 504) carries the sts form at 510 of 512. New gates: the OSCCAL size points on every chip, the wire-observed trim byte on both addressing classes (test/pbosccal.py, red-green), and the autobaud unit pinned to ram_start (test/check_unit.cmake, red-green) — the address --info's measured-clock read is about to rely on. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -72,9 +72,17 @@ constexpr std::uint8_t timeout_seconds = PUREBOOT_TIMEOUT;
|
||||
#endif
|
||||
constexpr avr::uint24_t autobaud_budget = PUREBOOT_AUTOBAUD_POLLS;
|
||||
|
||||
// A build may bake a measured oscillator trim (README.md: the RC-oscillator
|
||||
// deployment answer); the byte is applied at the top of run(). Orthogonal to
|
||||
// the serial backend — an autobaud build may carry it for the application's
|
||||
// benefit alone.
|
||||
#if defined(PUREBOOT_OSCCAL)
|
||||
static_assert(PUREBOOT_OSCCAL >= 0 && PUREBOOT_OSCCAL <= 0xff, "PUREBOOT_OSCCAL is one OSCCAL byte");
|
||||
#endif
|
||||
|
||||
// The loader's one identity number. The protocol carries none of its own —
|
||||
// a version implies it, and the host tool holds that map (README.md).
|
||||
constexpr std::uint8_t version = 5;
|
||||
constexpr std::uint8_t version = 6;
|
||||
|
||||
// The image's identity stamp, for the host tool rather than for the wire: an
|
||||
// update image is a bare 512-byte slot, and without this nothing in it says
|
||||
@@ -477,6 +485,12 @@ void fill_page(std::uint8_t bank, std::uint16_t at)
|
||||
|
||||
[[noreturn]] void run()
|
||||
{
|
||||
#if defined(PUREBOOT_OSCCAL)
|
||||
// The build's oscillator trim, ahead of everything — the WDRF bail
|
||||
// included — so every path out of reset, the watchdog hand-over to the
|
||||
// application first among them, runs on the corrected clock.
|
||||
avr::clock::calibrate(PUREBOOT_OSCCAL);
|
||||
#endif
|
||||
// A watchdog reset belongs to the application, whose watchdog stays forced
|
||||
// on until it clears WDRF — no activation window in its way.
|
||||
if (avr::hw::field_impl<wdrf_field()>::test())
|
||||
|
||||
Reference in New Issue
Block a user