diff --git a/pureboot/pureboot.py b/pureboot/pureboot.py index 98befab..441164c 100644 --- a/pureboot/pureboot.py +++ b/pureboot/pureboot.py @@ -193,6 +193,8 @@ def load_image(path): """Raw binary, or Intel HEX by extension (.hex/.ihx/.ihex).""" data = open(path, "rb").read() if not path.lower().endswith((".hex", ".ihx", ".ihex")): + if not data: + raise Error(f"{path}: empty image") return data memory = {} for number, line in enumerate(data.decode("ascii", "replace").splitlines(), 1): @@ -284,8 +286,9 @@ def covered(pages, skip_blank): def op_erase_flash(loader): - """0xff over the whole application area, page 0 first — an interrupted - erase leaves the entry word blank and the chip still boots the loader.""" + """0xff over the whole application area. Order does not matter here — + every target byte is the same value — and a blank word 0 still falls + through to the loader, so an interruption is harmless.""" blank = bytes([0xFF] * loader.info.page) for address in range(0, loader.info.base, loader.info.page): loader.write_page(address, blank) diff --git a/test/pureboot_device.c b/test/pureboot_device.c index d14352e..245edbf 100644 --- a/test/pureboot_device.c +++ b/test/pureboot_device.c @@ -159,6 +159,18 @@ static void rx_start_next(void) avr_cycle_timer_register(avr, bit_cycles, rx_step, NULL); } +// A reset abandons whatever the bridge was mid-transfer: bytes still queued +// for a chip that no longer has the context to receive them meaningfully, +// and a decode in progress on a TX line the reset may have already changed. +static void bridge_reset(void) +{ + rx_head = rx_tail = 0; + rx_active = 0; + tx_active = 0; + tx_level = 1; + avr_raise_irq(rx_pin, 1); // idle line +} + static void poll_pty(void) { uint8_t chunk[256]; @@ -262,7 +274,7 @@ int main(int argc, char *argv[]) nvm.io.ioctl = nvm_ioctl; avr_register_io(avr, &nvm.io); - bit_cycles = avr->frequency / baud; + bit_cycles = (avr->frequency + baud / 2) / baud; // matches uart.hpp's own rounding exactly rx_pin = avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 0); avr_irq_register_notify(avr_io_getirq(avr, AVR_IOCTL_IOPORT_GETIRQ('B'), 1), tx_hook, NULL); avr_raise_irq(rx_pin, 1); // idle line @@ -297,6 +309,8 @@ int main(int argc, char *argv[]) avr_ioctl(avr, AVR_IOCTL_UART_GET_FLAGS('0'), &flags); flags &= ~AVR_UART_FLAG_POLL_SLEEP; avr_ioctl(avr, AVR_IOCTL_UART_SET_FLAGS('0'), &flags); + } else { + bridge_reset(); } } if (!use_uart_pty && ++since_poll >= 2000) {