Demo for ch32-rs/ch32-data#26 — using LMA/VMA linker separation to represent CH32's dual flash addresses:
- VMA =
0x0000_0000(CODE) — execution address - LMA =
0x0800_0000(FLASH) — programming address
See memory.x and link.x for the implementation. Sections use >CODE AT>FLASH.
cargo build
rust-objcopy -O binary \
--only-section .vector_table \
--only-section .text \
--only-section .rodata \
--only-section .data \
target/riscv32ec-unknown-none-elf/debug/memory-layout-ch32 \
target/riscv32ec-unknown-none-elf/debug/firmware.bin
wlink flash --chip CH32V003 target/riscv32ec-unknown-none-elf/debug/firmware.bin
probe-rs attach --chip CH32V003 target/riscv32ec-unknown-none-elf/debug/memory-layout-ch32probe-rs won't be able to flash because ch32-rs/flash-algorithms expects 0x0000_0000 and internally translates to 0x0800_0000.
Crates like defmt-rtt place buffers in .uninit.* sections. Without explicit (NOLOAD) placement, these get an LMA assigned, causing wlink to see loadable segments spanning flash to RAM (~384MB) and fail. probe-rs silently ignores them. This is a pre-existing issue unrelated to this experiment, however.
The objcopy --only-section approach above avoids this.
Alternatively, link.x could include:
.uninit (NOLOAD) : ALIGN(4)
{
*(.uninit .uninit.*);
} >RAMThis will guard all .uninit sections, and I think probably appropriate to be included in link.x, but this is a separate issue...