Pi Pico Embedded Rust Always elf2uf2-r Always Produces Error: "Unrecognized ABI"

2026-05-26

Stack Overflow: View Question

Tags: rust, embedded, cortex-m, pi, raspberry-pi-pico

Score: 1 | Views: 239

The asker is trying to build a "blinky" style program in Rust for the original Raspberry Pi Pico (RP2040, Cortex-M0+). Their Cargo configuration looks textbook-correct: thumbv6m-none-eabi target, the linker flags that preserve the .boot2 section, and a runner that pipes the ELF through elf2uf2-rs so the resulting UF2 can be dropped onto the bootloader mass-storage device. Yet every build ends with elf2uf2-rs bailing out with "Unrecognized ABI".

What makes this one interesting is that the error message is misleading. elf2uf2-rs doesn't actually care about C ABI variants — it looks at the ELF's e_flags and the program headers and validates that the binary's load addresses fall inside the Pico's expected flash/SRAM regions. The "Unrecognized ABI" branch fires when the tool can't reconcile what it sees with the layout it knows for the RP2040. The common root causes are:

The direction I'd point them: first run arm-none-eabi-readelf -l target/thumbv6m-none-eabi/debug/<binary> and verify that LOAD segments start at 0x10000000 and that a .boot2 section exists and is non-empty. If .boot2 is empty, they're missing the #[link_section = ".boot2"] static from rp2040-boot2. If the load address is wrong, their memory.x is wrong or absent.

Gotcha worth flagging: elf2uf2-rs has been functionally superseded by picotool for newer setups, and the RP2040 vs RP2350 distinction trips up almost everyone buying a Pico in 2026 — the SKUs look nearly identical on the shelf.

The challenge: A misleading error message ("Unrecognized ABI") hides the real culprit, which is almost always a memory-map or boot2 problem — and the silent fallbacks in Cargo's linker config make it hard to tell which.

All newsletters