zephyr-cp: restore "ranges" on RP2040 partitions, fixing unbootable images - #13
zephyr-cp: restore "ranges" on RP2040 partitions, fixing unbootable images#13tyeth wants to merge 2 commits into
Conversation
…mages
Every RP2040 board overlay in this port does
&flash0 {
/delete-node/ partitions;
partitions { #address-cells = <1>; #size-cells = <1>; ... };
};
to replace the stock partition table. Re-creating the node dropped the
"ranges;" property that the upstream board DTS puts on "partitions"
(zephyr/boards/raspberrypi/rpi_pico/rpi_pico-common.dtsi and
zephyr/boards/adafruit/feather_rp2040/adafruit_feather_rp2040.dts).
"ranges" is what makes devicetree address translation walk from a
partition up through flash0's "ranges = <0x0 0x10000000 ...>" into the
SoC address space. Without it the translation stops at "partitions", so
for the "zephyr,mapped-partition" children DT_REG_ADDR() returns the
bare in-flash offset instead of the XIP address:
before: code_partition REG_IDX_0_VAL_ADDRESS = 0x100
after: code_partition REG_IDX_0_VAL_ADDRESS = 0x10000100
Two independent things then went wrong, and together they made the
image unbootable:
1. With CONFIG_FLASH_USES_MAPPED_PARTITION=y, ROM_ADDR in
zephyr/include/zephyr/arch/arm/cortex_m/scripts/linker.ld is
DT_REG_ADDR(DT_CHOSEN(zephyr_code_partition)), so FLASH ORIGIN
became 0x100 and the whole image was linked below the XIP window.
2. soc/raspberrypi/rpi_pico/rp2040/Kconfig gates
RP2_REQUIRES_SECOND_STAGE_BOOT on that address being exactly
0x10000100. It defaulted to n, so neither
modules/hal_rpi_pico/CMakeLists.txt (which compiles and checksums
boot_stage2) nor soc/raspberrypi/rpi_pico/rp2040/linker.ld (which
places .boot2 at 0x10000000) did anything, and the image shipped
with no second-stage bootloader at all. It also flipped the UF2
base from BUILD_OUTPUT_UF2_USE_FLASH_BASE to _USE_FLASH_OFFSET.
The resulting UF2 targeted 0x00000100..0x00107b00 and wrote nothing to
0x10000000, so the RP2040 bootrom found no boot2 and dropped straight
back into BOOTSEL.
Adding "ranges;" back restores both. Verified by rebuilding:
rpi_pico/rp2040/w .boot2 0x10000000 (256 B), rom_start 0x10000100
UF2 family 0xe48bff56, 0x10000000..0x10107c00
rpi_pico/rp2040 .boot2 0x10000000 (256 B), rom_start 0x10000100
UF2 family 0xe48bff56, 0x10000000..0x10062b00
The RP2350 boards were never affected: their overlays merge into the
existing "partitions" node instead of deleting it, so they kept
"ranges" and already linked at 0x10000000.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Two failure modes that cost real debugging time, written down so the next board port does not rediscover them: - Replacing the partitions node without re-adding "ranges;" mis-links the whole image on any SoC whose flash base is not 0x0, and on RP2040 also silently drops the second-stage bootloader. - Undersizing or misaligning the settings partition makes NVS report zero sectors, so bt_enable() fails before opening the HCI driver and the application sees an unexplained OSError from "import _bleio". Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Closing: this diff is now on
The board files this PR edited ( The second commit on this branch, the README "Board overlay pitfalls" section, is still worth having and is being reworked against the new layout in a separate PR. Branch left in place. 🤖 Generated with Claude Code |
Fixes #6.
Independent of the Bluetooth work — this is why no RP2040 board in
ports/zephyr-cphas ever booted from its UF2. Based onmain, not on the BLE stack.The RP2040 overlays
/delete-node/ partitions;and rebuild the node, dropping theranges;the upstream board DTS provides. Address translation then can't reachflash0'sranges = <0x0 0x10000000 ...>, so the code partition resolves to0x100instead of0x10000100. That both mis-links the image and, becausesoc/raspberrypi/rpi_pico/rp2040/Kconfiggates second-stage boot on the address being exactly0x10000100, drops.boot2from the ELF entirely.The Pico 2 W overlay merges into the existing
partitionsnode instead of deleting it, so it keptranges;and booted. That was the whole difference.Before / after
rom_startVMA/LMA0x000001000x10000100.boot20x10000000, 256 B0x00000100..0x00107b000x10000000..0x10107b000x10000000All three affected boards verified by regenerating artifacts:
raspberrypi_rpi_pico_zephyr,raspberrypi_rpi_pico_w_zephyr,adafruit_feather_rp2040_zephyr. UF2 family id stays0xe48bff56.Verified on hardware
A Pico W flashed with the fixed UF2 boots, enumerates CDC +
CIRCUITPY, and runs code — where the same build before this change fell straight back to BOOTSEL (2e8a:0003 RP2 Boot).Pre-flash static checks also held: the CRC32 the RP2040 bootrom validates over boot2 (MPEG-2 variant, bytes 0–251, stored LE at 252–255) matches at
0xd58f0b07on all three boards' UF2s, and the vector table at0x10000100has a sane initial SP (0x2001f300) and reset vector (0x1000f889,z_arm_reset+ Thumb bit).Nothing under
zephyr/ormodules/is touched — upstream is correct, the port was supplying malformed devicetree.Note the code partition is now
0x100..0x180000rather than0x0..0x180000, so the image gains 256 usable bytes;nvm/storage/circuitpyoffsets are unchanged, so existing filesystem contents survive.Related, not fixed here: #7 (same defect in the STM32WBA overlay, unverified).
🤖 Generated with Claude Code