Assign stack to specific memory location

On an RP2040 there are two 4k memory blocks that are unique to each core that can be assigned to each core for stack respectively. How do you do this in Rust? The following code works but you have no control over the memory location.

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
}

With a memory model like:

MEMORY {
    BOOT2 : ORIGIN = 0x10000000, LENGTH = 0x100
    FLASH : ORIGIN = 0x10000100, LENGTH = 2048K - 0x100
    RAM   : ORIGIN = 0x20000000, LENGTH = 231K
    RAM1  : ORIGIN = 0x20039c00, LENGTH =  25K
    STK   : ORIGIN = 0x20040000, LENGTH =   4K
    STK1  : ORIGIN = 0x20041000, LENGTH =   4K
}

I want to assign STK1 to Core1.

you must tell the linker where you want to put the stack. I can think of 2 different ways to do this.

method 1: use the #[link_section = "section-name"] attribute:

// rust code
#[link_section(".core1_stack")]
static mut CORE1_STACK: Stack<4096> = Stack::new();

add the section in memory.x:

 .core1_stack ORIGIN(STK1) :
  {
    *(.core1_stack);
  } > STK1

method 2: I think you can define the symbol directly in linker script and declare it as extern symbol in rust code, but I'm not sure how well the toolchain will support this:

// symbol defined in linker script
// `Stack` is `#[repr(C)]` so layout is ffi compatible
extern {
    static mut CORE1_STACK: Stack<4096>;
}

and define the symbol in memory.x directly

CORE1_STACK = STK1;
1 Like

Thanks! Yes, I was pulling my hair out with method 2, that does not work. BUT, method 1 works. Thanks again!

file: memory.x

    .core1_stack ORIGIN(STK1) :
    {
        *(.core1_stack);
        _stack1_end = .;
    } > STK1

in rust code:

#[link_section = ".core1_stack"]
static mut CORE1_STACK: Stack<0x400> = Stack::new(); /* 0x1000 bytes, 0x400 32-bit words */