Pi Pico Embedded Rust Always elf2uf2-r Always Produces Error: "Unrecognized ABI"
I've been trying unsuccessfully to get a simple embedded Rust program to build and run on a Pi Pico.
Here is my project:
.cargo/config.toml:
[build]
target = "thumbv6m-none-eabi"
[target.thumbv6m-none-eabi]
rustflags = [
"-C", "link-arg=-Tlink.x",
"-C", "link-arg=--nmagic",
# This line is the magic bullet:
"-C", "link-arg=-z", "-C", "link-arg=keep-section=.boot2",
]
src/main.rs:
#![no_std]
#![no_main]
// FORCE the bootloader into the binary
#[link_section = ".boot2"]
#[used]
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
use panic_halt as _;
// Use the entry macro from the HAL, not cortex_m_rt
// This ensures the bootloader is linked correctly
use rp_pico::entry;
use core::fmt::Write;
use embedded_hal::digital::OutputPin;
use rp_pico::hal::{
clocks::{init_clocks_and_plls, Clock},
fugit::RateExtU32,
pac,
sio::Sio,
uart::{DataBits, StopBits, UartConfig, UartPeripheral},
watchdog::Watchdog,
};
const XTAL_FREQ_HZ: u32 = 12_000_000;
#[entry]
fn main() -> ! {
let mut pac = pac::Peripherals::take().unwrap();
let core = pac::CorePeripherals::take().unwrap();
let mut watchdog = Watchdog::new(pac.WATCHDOG);
let sio = Sio::new(pac.SIO);
let clocks = init_clocks_and_plls(
XTAL_FREQ_HZ,
pac.XOSC,
pac.CLOCKS,
pac.PLL_SYS,
pac.PLL_USB,
&mut pac.RESETS,
&mut watchdog,
)
.ok()
.unwrap();
let pins = rp_pico::Pins::new(
pac.IO_BANK0,
pac.PADS_BANK0,
sio.gpio_bank0,
&mut pac.RESETS,
);
let uart_pins = (
pins.gpio0.into_function(),
pins.gpio1.into_function(),
);
let mut uart = UartPeripheral::new(pac.UART0, uart_pins, &mut pac.RESETS)
.enable(
UartConfig::new(
115200.Hz(),
DataBits::Eight,
None,
StopBits::One,
),
clocks.peripheral_clock.freq(),
)
.unwrap();
let mut buzzer = pins.gpio4.into_push_pull_output();
let mut delay = cortex_m::delay::Delay::new(
core.SYST,
clocks.system_clock.freq().to_Hz(),
);
let _ = writeln!(uart, "cricket chirper starting");
let mut seed: u32 = 12345;
loop {
seed = seed.wrapping_mul(1103515245).wrapping_add(12345);
let seconds = (seed % 60) + 1;
let _ = writeln!(uart, "waiting {} seconds", seconds);
delay.delay_ms(seconds * 1000);
let _ = writeln!(uart, "buzzing");
for _ in 0..500 {
let _ = buzzer.set_high();
delay.delay_us(500);
let _ = buzzer.set_low();
delay.delay_us(500);
}
delay.delay_ms(500);
}
}
build.rs:
fn main() {
println!("cargo:rerun-if-changed=memory.x");
}
Cargo.toml:
[package]
name = "pico-buzzer"
version = "0.1.0"
edition = "2021"
[dependencies]
# Standard ARM crates
cortex-m = "0.7"
cortex-m-rt = "0.7"
panic-halt = "0.2"
# Hardware abstraction
embedded-hal = "1.0"
embedded-io = "0.6"
# The Pico HAL - 'rt' feature provides the linker script automatically
rp-pico = { version = "0.9", features = ["rt"] }
rp2040-boot2 = "0.3"
[profile.release]
panic = "abort"
opt-level = 3
lto = true
codegen-units = 1
debug = true
memory.x:
MEMORY
{
/* The 2nd stage bootloader is 256 bytes at the start of flash */
FLASH : ORIGIN = 0x10000000, LENGTH = 2048K
RAM : ORIGIN = 0x20000000, LENGTH = 264K
}
Then I run these commands:
cargo clean
cargo build --release
They both finish fine.
Then I run:
elf2uf2-rs target/thumbv6m-none-eabi/release/pico-buzzer
and always get the same error output:
Error: "Unrecognized ABI"
How can I overcome this?