Skip to content

flash: ignore SPM executed outside the boot loader section#581

Open
ZsoltSaskovy wants to merge 1 commit into
buserror:masterfrom
ZsoltSaskovy:spm-boot-section
Open

flash: ignore SPM executed outside the boot loader section#581
ZsoltSaskovy wants to merge 1 commit into
buserror:masterfrom
ZsoltSaskovy:spm-boot-section

Conversation

@ZsoltSaskovy

Copy link
Copy Markdown

Motivation

On real AVR silicon, the SPM instruction only executes when the program counter is inside the boot loader section; executed from the application (RWW) section it is a no-op. simavr currently executes SPM from any address.

This gap bit us in practice: an ATmega2560 bootloader accidentally linked at 0x3C000 (the boot section starts at 0x3E000 with BOOTSZ=00) passed a full simavr-based integration test suite — including complete STK500v2 and TFTP firmware-upload flows — while on real hardware every SPM was silently ignored and nothing was ever written to flash.

Change

  • avr_flash_t gets an opt-in bls_start field: when non-zero, SPM issued with avr->pc below it is ignored and a warning is logged.
  • Cores that do not set the field keep the old permissive behaviour, so nothing changes for any other MCU.
  • Enabled for the ATmega2560 core with the largest legal boot section (BOOTSZ=00, byte address 0x3E000). This is the most permissive boundary, so no valid fuse configuration is rejected, while SPM from the application section is caught.

Modelling the actual BOOTSZ fuse decoding would be more precise; this conservative boundary already catches the realistic failure mode (bootloader linked below the boot section) without touching fuse handling.

Validation

  • A probe firmware linked at 0x0000 that attempts boot_page_erase/boot_page_fill/boot_page_write via <avr/boot.h>: flash stays 0xFF after the patch (it was silently written before).
  • Positive control: a real STK500v2+TFTP bootloader linked at 0x3E000 still programs flash correctly in simulation (full upload round-trips, verified against the same firmware running on physical ATmega2560 hardware).

🤖 Generated with Claude Code

On real parts SPM only executes when the program counter is inside the
boot loader section; executed from the application (RWW) section it is
a no-op. simavr executed SPM from any address, so firmware that
misplaces its bootloader (e.g. linked at 0x3C000 on the ATmega2560,
where the boot section starts at 0x3E000) passed simulation but failed
silently on real hardware.

Add an opt-in bls_start field to avr_flash_t: when non-zero, SPM with
avr->pc below it is ignored with a warning log. Cores that do not set
the field keep the old permissive behaviour.

Enable it for the ATmega2560 using the largest possible boot section
(BOOTSZ=00, byte address 0x3E000). This is the most permissive legal
boundary, so no valid fuse configuration is rejected, while SPM from
the application section is caught.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@ZsoltSaskovy

Copy link
Copy Markdown
Author

Build is failing as "install dependencies" is failing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant