Skip to content

doc: SWD flashing RAM-clear contract - #5309

Open
packerlschupfer wants to merge 1 commit into
prusa3d:masterfrom
packerlschupfer:pr/doc-swd-flashing
Open

doc: SWD flashing RAM-clear contract#5309
packerlschupfer wants to merge 1 commit into
prusa3d:masterfrom
packerlschupfer:pr/doc-swd-flashing

Conversation

@packerlschupfer

Copy link
Copy Markdown

Summary

Adds doc/swd_flashing.md explaining the RAM-state contract that st-flash write alone doesn't satisfy. Documentation only, no code change.

Why

The xBuddy STM32F427 has three RAM regions that survive an SWD-only flash but get cleared by a physical power-cycle. Specifically:

  • Shared SRAM at 0x20000000 — holds the DataExchange struct that the bootloader and main firmware use to communicate. Its first byte is the FwAutoUpdate enum value. ~3% of random bytes match one of the "do an update" values across the enum range (on=0xAA, older=0x55, specified=0xBB, tester_mode_1=0xCA, tester_mode_2=0xCB, tester_mode_3=0xCC). When that happens after an SWD-only flash, the bootloader tries to flash a BBF that isn't there and hangs at "50%".
  • Backup SRAM at 0x40024000 — holds power_panic_storage_bkpsram's state. Protected by CRC + magic, so a random match is far less likely than the shared-RAM case, but checking the data still delays boot.

st-flash write only touches application flash (0x08020000+). It does not clear any SRAM region and does not issue the same cold-boot reset the physical power switch produces. So the next boot sees stale state from whatever firmware was running just before the flash.

This wasted me a couple of hours of debugging when first scripting SWD flashes for a Core One+. The fix at the openocd-script level is a handful of mwb/mww commands, but it's not obvious until you trace through data_exchange.cpp and power_panic_storage_bkpsram.cpp. This doc puts the trace in one place so the next person doesn't have to repeat it.

What's in the doc

  • TL;DR openocd snippet that clears the right bytes
  • Why each region needs clearing (one section per region, with file/line references into the tree)
  • Reference end-to-end openocd invocation
  • Note that a physical power-cycle is equivalent (and why)

Test plan

  • Reviewed for accuracy against src/common/data_exchange.cpp and src/common/power_panic_storage_bkpsram.cpp.
  • Renders cleanly on GitHub.

Related

I'd love to make this less needed at the source — e.g. have the bootloader check a magic value in shared RAM before acting on the FwAutoUpdate flag, the same way power-panic checks its magic + CRC. But the bootloader lives in .dependencies/bootloader-* as a pre-built blob in this tree, so that's a coordination issue with whoever maintains the bootloader binary, not a patch I can submit here. Happy to follow up if there's interest.

After st-flash write, the bootloader and main firmware see whatever
was in shared RAM (0x20000000+) and backup SRAM (0x40024000) at the
moment SWD started talking to the MCU. That stale state can:

  - trigger a false firmware-update on next boot (shared RAM holds
    the FwAutoUpdate flag; ~3% chance of a random byte matching one
    of the "do an update" enum values → bootloader stuck at 50% with
    no BBF to flash);
  - trigger a false power-panic recovery (backup SRAM holds the
    power_panic magic + CRC; in practice protected by the CRC check
    but still wastes boot time).

A power-cycle drops both regions because they only persist via V_BAT,
but SWD-only flashing has no chance to invoke that. The openocd-side
clear sequence used in flash_coreone.sh is documented here.

This is documentation only — no code change. The expectation is that
anyone debugging via SWD now has a single reference for "why does the
printer hang at the bootloader bar after my flash" and how to fix it
in their openocd script.
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