Second attempt
To fix this problem, we can rely on the rp235x-hal critical section implementation that handles the multi-core nature of our code:
[package]
name = "pico-simple"
version = "0.1.0"
edition = "2024"
[dependencies]
cortex-m-rt = "0.7.0"
cortex-m-rt-macros = "0.7.5"
panic-probe = { version = "1.0.0", features = ["print-defmt"] }
defmt = "1.0.1"
defmt-rtt = "1.0.0"
rp235x-hal = { version = "0.4.0", features = ["critical-section-impl"] }
cortex-m = { version = "0.7.6" }
We have to use the crate with use rp235x_hal as _;, otherwise the linker is free to not include it our final binary (try and see what happens).
#![no_std]
#![no_main]
use cortex_m::asm;
use cortex_m_rt::entry;
use defmt::{assert_eq, error, info};
use rp235x_hal as _;
use {defmt_rtt as _, panic_probe as _};
#[unsafe(link_section = ".start_block")]
#[unsafe(no_mangle)]
static BOOT_ROM_INFO: [u8; 44] = [
0xd3, 0xde, 0xff, 0xff, 0x42, 0x01, 0x21, 0x10, 0xff, 0x01, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x79, 0x35, 0x12, 0xab, 0xf2, 0xeb, 0x88, 0x71,
0x6c, 0x93, 0x02, 0x10, 0x7c, 0x93, 0x02, 0x10, 0x70, 0xf6, 0x02, 0x10,
0x90, 0xa3, 0x1a, 0xe7, 0x1f, 0x01, 0x02, 0x03,
];
fn second_cpu() {
for _ in 1..10000 {
asm::nop();
}
loop {
info!(">>>>>>>> cpu 2 is alive");
for _ in 1..100 {
asm::nop();
}
}
}
#[entry]
fn main() -> ! {
unsafe {
let vector_table_address =
core::ptr::read_volatile(0xE000ED08 as *const usize);
info!("vector table address: {:#x}", vector_table_address);
let cmd_sequence: [usize; 6] = [
0,
0,
1,
vector_table_address,
0x20040000,
second_cpu as *const usize as usize,
];
// algorithm in page 377
'outer: loop {
for _ in 1..10000 {
asm::nop();
}
// discard data from read FIFO until empty
// SIO: FIFO_RD Register
while core::ptr::read_volatile(0xd0000050 as *const usize) & 1 == 1
{
let answer =
core::ptr::read_volatile(0xd0000058 as *const usize);
info!("cleaning with answer: {}", answer);
}
for cmd in cmd_sequence {
// validate no FIFO error
// SIO: FIFO_ST Register
assert_eq!(
core::ptr::read_volatile(0xd0000050 as *const usize)
& 0b1110,
2
);
// SIO: FIFO_WR Register
core::ptr::write_volatile(0xd0000054 as *mut usize, cmd);
asm::sev();
info!("waiting for data");
while core::ptr::read_volatile(0xd0000050 as *const usize) & 1
== 0
{
asm::nop();
}
info!("got data");
let answer =
core::ptr::read_volatile(0xd0000058 as *const usize);
info!("cmd: {} with answer: {}", cmd, answer);
if answer != cmd {
error!("bad answer, will restart");
continue 'outer;
}
}
break;
}
for _ in 1..10000 {
asm::nop();
}
loop {
info!(">>>>>>>> cpu 1 is alive");
for _ in 1..100 {
asm::nop();
}
}
}
}