如何在 Rust 中使用 RP2040 上的两个内核?

Mut*_*Bob 4 embedded multithreading rust rp2040

我读到RP2040有两个核心。如何在 Rust 程序中使用第二个核心?

我不需要一路通用多线程,我只想有两个线程,每个线程拥有一个核心,并且它们可以相互通信。

Rust 书中关于 Fearless Concurrency 的部分(由 Jeremy 建议)没有多大帮助。

thread::spawn(|| {
    let mut x = 0;
    x = x + 1;
});
Run Code Online (Sandbox Code Playgroud)

编译失败

error[E0433]: failed to resolve: use of undeclared crate or module `thread`
   --> src/main.rs:108:5
    |
108 |     thread::spawn(|| {
    |     ^^^^^^ use of undeclared crate or module `thread`
Run Code Online (Sandbox Code Playgroud)

鉴于RP2040 是环境的thread一部分,这并不奇怪。std#![no_std]

在C API中有一个函数multicore_launch_core1。有等效的 Rust API 吗?

har*_*mic 6

正如您已经发现的,Ruststd库的多线程设施依赖于操作系统内核的设施,而这些设施在裸机嵌入式环境中工作时不可用。

让第二个核心执行代码的实际过程有点复杂和低级。RP2040 数据表中标题为“2.8.2. 在处理器核心 1 上启动代码”的部分对此进行了描述。

总之,第二个内核启动后,它会进入睡眠状态,等待通过 SIO FIFO(两个内核之间的通信通道)向其发送指令。发送的指令提供了一个中断向量表、一个堆栈指针和一个内核开始执行的入口点。

幸运的是,rp2040_hal箱为此提供了更高级别的抽象。下面的示例来自multicore此板条箱的模块:

use rp2040_hal::{pac, gpio::Pins, sio::Sio, multicore::{Multicore, Stack}};

static mut CORE1_STACK: Stack<4096> = Stack::new();

fn core1_task() -> ! {
    loop {}
}

fn main() -> ! {
    let mut pac = pac::Peripherals::take().unwrap();
    let mut sio = Sio::new(pac.SIO);
    // Other init code above this line
    let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo);
    let cores = mc.cores();
    let core1 = &mut cores[1];
    let _test = core1.spawn(unsafe { &mut CORE1_STACK.mem }, core1_task);
    // The rest of your application below this line
}
Run Code Online (Sandbox Code Playgroud)

在上面的示例中,函数内的代码core1_task将在第二个核心上执行,而第一个核心继续执行该main函数。板条箱的示例目录中有更完整的示例。

免责声明:我自己没有使用过这个板条箱或微控制器 - 所有信息都是从在线文档中找到的。