Skip to content

Commit d66b479

Browse files
authored
Merge pull request rp-rs#311 from Liamolucko/multicore-no-alloc
Remove the `alloc` requirement for `Core::spawn`
2 parents e9f367f + e9534ac commit d66b479

File tree

4 files changed

+226
-86
lines changed

4 files changed

+226
-86
lines changed

rp2040-hal/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ dht-sensor = "0.2.1"
4242

4343
[features]
4444
rt = ["rp2040-pac/rt"]
45-
alloc = []
4645
rom-func-cache = []
4746
disable-intrinsics = []
4847
rom-v2-intrinsics = []

rp2040-hal/examples/multicore_fifo_blink.rs

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ const CORE1_TASK_COMPLETE: u32 = 0xEE;
5757
/// the stack guard to take up the least amount of usable RAM.
5858
static mut CORE1_STACK: Stack<4096> = Stack::new();
5959

60-
fn core1_task() -> ! {
60+
fn core1_task(sys_freq: u32) -> ! {
6161
let mut pac = unsafe { pac::Peripherals::steal() };
6262
let core = unsafe { pac::CorePeripherals::steal() };
6363

@@ -70,10 +70,6 @@ fn core1_task() -> ! {
7070
);
7171

7272
let mut led_pin = pins.gpio25.into_push_pull_output();
73-
// The first thing core0 sends us is the system bus frequency.
74-
// The systick is based on this frequency, so we need that to
75-
// be accurate when sleeping via cortex_m::delay::Delay
76-
let sys_freq = sio.fifo.read_blocking();
7773
let mut delay = cortex_m::delay::Delay::new(core.SYST, sys_freq);
7874
loop {
7975
let input = sio.fifo.read();
@@ -114,17 +110,18 @@ fn main() -> ! {
114110
.ok()
115111
.unwrap();
116112

113+
let sys_freq = clocks.system_clock.freq().integer();
114+
117115
// The single-cycle I/O block controls our GPIO pins
118116
let mut sio = hal::sio::Sio::new(pac.SIO);
119117

120-
let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio);
118+
let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo);
121119
let cores = mc.cores();
122120
let core1 = &mut cores[1];
123-
let _test = core1.spawn(core1_task, unsafe { &mut CORE1_STACK.mem });
121+
let _test = core1.spawn(unsafe { &mut CORE1_STACK.mem }, move || {
122+
core1_task(sys_freq)
123+
});
124124

125-
// Let core1 know how fast the system clock is running
126-
let sys_freq = clocks.system_clock.freq().integer();
127-
sio.fifo.write_blocking(sys_freq);
128125
/// How much we adjust the LED period every cycle
129126
const LED_PERIOD_INCREMENT: i32 = 2;
130127

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
//! # Multicore Blinking Example
2+
//!
3+
//! This application blinks two LEDs on GPIOs 2 and 3 at different rates (3Hz
4+
//! and 4Hz respectively.)
5+
//!
6+
//! See the `Cargo.toml` file for Copyright and licence details.
7+
8+
#![no_std]
9+
#![no_main]
10+
11+
use cortex_m::delay::Delay;
12+
// The macro for our start-up function
13+
use cortex_m_rt::entry;
14+
15+
use embedded_time::fixed_point::FixedPoint;
16+
use hal::clocks::Clock;
17+
use hal::gpio::Pins;
18+
use hal::multicore::{Multicore, Stack};
19+
use hal::sio::Sio;
20+
// Ensure we halt the program on panic (if we don't mention this crate it won't
21+
// be linked)
22+
use panic_halt as _;
23+
24+
// Alias for our HAL crate
25+
use rp2040_hal as hal;
26+
27+
// A shorter alias for the Peripheral Access Crate, which provides low-level
28+
// register access
29+
use hal::pac;
30+
31+
// Some traits we need
32+
use embedded_hal::digital::v2::ToggleableOutputPin;
33+
34+
/// The linker will place this boot block at the start of our program image. We
35+
/// need this to help the ROM bootloader get our code up and running.
36+
#[link_section = ".boot2"]
37+
#[used]
38+
pub static BOOT2: [u8; 256] = rp2040_boot2::BOOT_LOADER_W25Q080;
39+
40+
/// External high-speed crystal on the Raspberry Pi Pico board is 12 MHz. Adjust
41+
/// if your board has a different frequency
42+
const XTAL_FREQ_HZ: u32 = 12_000_000u32;
43+
44+
/// The frequency at which core 0 will blink its LED (Hz).
45+
const CORE0_FREQ: u32 = 3;
46+
/// The frequency at which core 1 will blink its LED (Hz).
47+
const CORE1_FREQ: u32 = 4;
48+
/// The delay between each toggle of core 0's LED (us).
49+
const CORE0_DELAY: u32 = 1_000_000 / CORE0_FREQ;
50+
/// The delay between each toggle of core 1's LED (us).
51+
const CORE1_DELAY: u32 = 1_000_000 / CORE1_FREQ;
52+
53+
/// Stack for core 1
54+
///
55+
/// Core 0 gets its stack via the normal route - any memory not used by static
56+
/// values is reserved for stack and initialised by cortex-m-rt.
57+
/// To get the same for Core 1, we would need to compile everything seperately
58+
/// and modify the linker file for both programs, and that's quite annoying.
59+
/// So instead, core1.spawn takes a [usize] which gets used for the stack.
60+
/// NOTE: We use the `Stack` struct here to ensure that it has 32-byte
61+
/// alignment, which allows the stack guard to take up the least amount of
62+
/// usable RAM.
63+
static mut CORE1_STACK: Stack<4096> = Stack::new();
64+
65+
/// Entry point to our bare-metal application.
66+
///
67+
/// The `#[entry]` macro ensures the Cortex-M start-up code calls this function
68+
/// as soon as all global variables are initialised.
69+
#[entry]
70+
fn main() -> ! {
71+
// Grab our singleton objects
72+
let mut pac = pac::Peripherals::take().unwrap();
73+
let core = pac::CorePeripherals::take().unwrap();
74+
75+
// Set up the watchdog driver - needed by the clock setup code
76+
let mut watchdog = hal::watchdog::Watchdog::new(pac.WATCHDOG);
77+
78+
// Configure the clocks
79+
let clocks = hal::clocks::init_clocks_and_plls(
80+
XTAL_FREQ_HZ,
81+
pac.XOSC,
82+
pac.CLOCKS,
83+
pac.PLL_SYS,
84+
pac.PLL_USB,
85+
&mut pac.RESETS,
86+
&mut watchdog,
87+
)
88+
.ok()
89+
.unwrap();
90+
91+
// Set up the GPIO pins
92+
let mut sio = Sio::new(pac.SIO);
93+
let pins = Pins::new(
94+
pac.IO_BANK0,
95+
pac.PADS_BANK0,
96+
sio.gpio_bank0,
97+
&mut pac.RESETS,
98+
);
99+
let mut led1 = pins.gpio2.into_push_pull_output();
100+
let mut led2 = pins.gpio3.into_push_pull_output();
101+
102+
// Set up the delay for the first core.
103+
let sys_freq = clocks.system_clock.freq().integer();
104+
let mut delay = Delay::new(core.SYST, sys_freq);
105+
106+
// Start up the second core to blink the second LED
107+
let mut mc = Multicore::new(&mut pac.PSM, &mut pac.PPB, &mut sio.fifo);
108+
let cores = mc.cores();
109+
let core1 = &mut cores[1];
110+
core1
111+
.spawn(unsafe { &mut CORE1_STACK.mem }, move || {
112+
// Get the second core's copy of the `CorePeripherals`, which are per-core.
113+
// Unfortunately, `cortex-m` doesn't support this properly right now,
114+
// so we have to use `steal`.
115+
let core = unsafe { pac::CorePeripherals::steal() };
116+
// Set up the delay for the second core.
117+
let mut delay = Delay::new(core.SYST, sys_freq);
118+
// Blink the second LED.
119+
loop {
120+
led2.toggle().unwrap();
121+
delay.delay_us(CORE1_DELAY)
122+
}
123+
})
124+
.unwrap();
125+
126+
// Blink the first LED.
127+
loop {
128+
led1.toggle().unwrap();
129+
delay.delay_us(CORE0_DELAY)
130+
}
131+
}
132+
133+
// End of file

0 commit comments

Comments
 (0)