diff --git a/libavr b/libavr index 6f8771f..674e63e 160000 --- a/libavr +++ b/libavr @@ -1 +1 @@ -Subproject commit 6f8771f411cd6f68e4af7e442902e37b52b33789 +Subproject commit 674e63e8f907e34a31ec3d505f977e0b7ccc7fe8 diff --git a/pureboot/README.md b/pureboot/README.md index d4a6875..7bbc70e 100644 --- a/pureboot/README.md +++ b/pureboot/README.md @@ -2,8 +2,8 @@ A serial bootloader on [libavr](https://git.blackmark.me/avr/libavr), pure by constraint: one C++ source, no inline assembly, no global register variables -(attributes and compiler flags allowed), **512 bytes on every chip libavr -targets — all 37**. The device speaks primitives; every composite — verify, +(attributes and compiler flags allowed), **a 512-byte slot on every chip +libavr targets — all 37**. The device speaks primitives; every composite — verify, erase, reset-vector surgery, updating the loader itself — lives in the host tool (`pureboot.py`). @@ -88,7 +88,8 @@ the usual one where a board's USB bridge is wired to RXD/TXD: the link's `init` clears that USART's `UCSRnB` first, because while its `TXEN` is set the USART — not the port register — owns the TX pin, and a loader entered from an application that left it enabled would receive and obey while answering nothing -(§20.2). It costs four bytes, and only on those pins. +(§20.6.3). It costs one store — four bytes on the extended-I/O chips, two on +the classic megas — and only on those pins. `SERIAL autobaud` takes neither: the loader **measures** the host's bit timing at run time, so `CLOCK` and `BAUD` are not build parameters there and one diff --git a/pureboot/pureboot.cpp b/pureboot/pureboot.cpp index b93302c..03129fd 100644 --- a/pureboot/pureboot.cpp +++ b/pureboot/pureboot.cpp @@ -1,6 +1,6 @@ // pureboot — a serial bootloader on libavr: one C++ source, no inline -// assembly, no global register variables, 512 bytes on every chip libavr -// targets. The device speaks primitives; every composite (verify, erase, +// assembly, no global register variables, a 512-byte slot on every chip +// libavr targets. The device speaks primitives; every composite (verify, erase, // reset-vector surgery, self-update) lives in the host tool. Protocol, // deployment and configuration: README.md next to this file. // @@ -242,8 +242,8 @@ struct software_link { // clock to time a window against — so this backend brings its own, below. struct autobaud_link { // The unit in GPIOR2:GPIOR1 where the chip has them: the loader owns the - // whole chip while it runs, and the pair is four instructions cheaper per - // session than a RAM word. + // whole chip while it runs, and the pair costs one word per access where + // the RAM word costs two — six words across the image. using uart = avr::uart::software_autobaud; static void init() diff --git a/pureboot/pureboot.py b/pureboot/pureboot.py index 645f72e..ec3126e 100644 --- a/pureboot/pureboot.py +++ b/pureboot/pureboot.py @@ -42,6 +42,10 @@ RETRIES = 3 # rewrites of a page that reads back wrong, before the run stops # 'g' writes, each taking a selector byte, a 16-bit address and a count, over # the spaces below. The loader carries one transfer loop instead of four bodies # — which is what buys the data space and the host-issued SPM operations. +# 6 marks the builds that may carry a baked OSCCAL trim, nothing on the wire; +# 7 gives 'J' a selector byte (older loaders take the bare address — jump() +# sends each form to the version that speaks it) and re-homes the autobaud +# unit into the GPIOR pair where the chip has one. UNIFIED_LOADER = 5 SP_FLASH, SP_EEPROM, SP_RAM, SP_FUSE, SP_SPM = 0, 1, 2, 3, 4