Skip to content

Commit 7c70788

Browse files
committed
embassy-rp: allow injection of FIFO handler
Add `fifo-handler` feature for injecting a custom handler of FIFO messages. Also enable FIFO queue in core1->core0 direction. Signed-off-by: Kaspar Schleiser <[email protected]> embassy_rp: fix unsafe call to extern fn
1 parent c6371d7 commit 7c70788

File tree

3 files changed

+80
-33
lines changed

3 files changed

+80
-33
lines changed

embassy-rp/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1212
- Add PIO I2S input
1313
- Add PIO onewire parasite power strong pullup
1414
- add `wait_for_alarm` and `alarm_scheduled` methods to rtc module ([#4216](https://github.com/embassy-rs/embassy/pull/4216))
15+
- allow injection of FIFO handler
1516

1617
## 0.8.0 - 2025-08-26
1718

embassy-rp/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,11 @@ _test = []
146146
## program and other details.
147147
binary-info = ["rt", "dep:rp-binary-info", "rp-binary-info?/binary-info"]
148148

149+
## Inject function for handling FIFO messages.
150+
## If this feature is enabled, a foreign function
151+
## `fn handle_fifo(u32) -> bool` must be implemented.
152+
fifo-handler = []
153+
149154
[dependencies]
150155
embassy-sync = { version = "0.7.2", path = "../embassy-sync" }
151156
embassy-time-driver = { version = "0.2.1", path = "../embassy-time-driver", optional = true }

embassy-rp/src/multicore.rs

Lines changed: 74 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -108,54 +108,63 @@ impl<const SIZE: usize> Stack<SIZE> {
108108
}
109109
}
110110

111-
#[cfg(all(feature = "rt", feature = "rp2040"))]
112-
#[interrupt]
111+
#[cfg(feature = "fifo-handler")]
112+
extern "Rust" {
113+
fn handle_fifo_token(token: u32) -> bool;
114+
}
115+
116+
#[cfg(feature = "rt")]
113117
#[link_section = ".data.ram_func"]
114-
unsafe fn SIO_IRQ_PROC1() {
118+
#[inline]
119+
unsafe fn sio_handler() {
115120
let sio = pac::SIO;
116121
// Clear IRQ
117122
sio.fifo().st().write(|w| w.set_wof(false));
118123

119124
while sio.fifo().st().read().vld() {
120-
// Pause CORE1 execution and disable interrupts
121-
if fifo_read_wfe() == PAUSE_TOKEN {
125+
let token = fifo_read_wfe();
126+
127+
// Forward to user handler.
128+
#[cfg(feature = "fifo-handler")]
129+
if handle_fifo_token(token) {
130+
continue;
131+
}
132+
133+
// Pause this core's execution and disable interrupts
134+
if token == PAUSE_TOKEN {
122135
cortex_m::interrupt::disable();
123-
// Signal to CORE0 that execution is paused
136+
// Signal to other that execution is paused
124137
fifo_write(PAUSE_TOKEN);
125-
// Wait for `resume` signal from CORE0
138+
// Wait for `resume` signal from other core
126139
while fifo_read_wfe() != RESUME_TOKEN {
127140
cortex_m::asm::nop();
128141
}
129142
cortex_m::interrupt::enable();
130-
// Signal to CORE0 that execution is resumed
143+
// Signal to other core that execution is resumed
131144
fifo_write(RESUME_TOKEN);
132145
}
133146
}
134147
}
135148

149+
#[cfg(all(feature = "rt", feature = "rp2040"))]
150+
#[interrupt]
151+
#[link_section = ".data.ram_func"]
152+
unsafe fn SIO_IRQ_PROC0() {
153+
sio_handler();
154+
}
155+
156+
#[cfg(all(feature = "rt", feature = "rp2040"))]
157+
#[interrupt]
158+
#[link_section = ".data.ram_func"]
159+
unsafe fn SIO_IRQ_PROC1() {
160+
sio_handler();
161+
}
162+
136163
#[cfg(all(feature = "rt", feature = "_rp235x"))]
137164
#[interrupt]
138165
#[link_section = ".data.ram_func"]
139166
unsafe fn SIO_IRQ_FIFO() {
140-
let sio = pac::SIO;
141-
// Clear IRQ
142-
sio.fifo().st().write(|w| w.set_wof(false));
143-
144-
while sio.fifo().st().read().vld() {
145-
// Pause CORE1 execution and disable interrupts
146-
if fifo_read_wfe() == PAUSE_TOKEN {
147-
cortex_m::interrupt::disable();
148-
// Signal to CORE0 that execution is paused
149-
fifo_write(PAUSE_TOKEN);
150-
// Wait for `resume` signal from CORE0
151-
while fifo_read_wfe() != RESUME_TOKEN {
152-
cortex_m::asm::nop();
153-
}
154-
cortex_m::interrupt::enable();
155-
// Signal to CORE0 that execution is resumed
156-
fifo_write(RESUME_TOKEN);
157-
}
158-
}
167+
sio_handler();
159168
}
160169

161170
/// Spawn a function on this core
@@ -286,23 +295,55 @@ where
286295

287296
// Wait until the other core has copied `entry` before returning.
288297
fifo_read();
298+
299+
// Enable FIFO interrupts from core1.
300+
#[cfg(feature = "rp2040")]
301+
unsafe {
302+
interrupt::SIO_IRQ_PROC0.enable()
303+
};
304+
#[cfg(feature = "_rp235x")]
305+
unsafe {
306+
interrupt::SIO_IRQ_FIFO.enable()
307+
};
289308
}
290309

291310
/// Pause execution on CORE1.
292311
pub fn pause_core1() {
293312
if IS_CORE1_INIT.load(Ordering::Acquire) {
294-
fifo_write(PAUSE_TOKEN);
295-
// Wait for CORE1 to signal it has paused execution.
296-
while fifo_read() != PAUSE_TOKEN {}
313+
cortex_m::interrupt::free(|_| {
314+
fifo_write(PAUSE_TOKEN);
315+
// Wait for CORE1 to signal it has paused execution.
316+
loop {
317+
let token = fifo_read();
318+
if token == PAUSE_TOKEN {
319+
break;
320+
}
321+
#[cfg(feature = "fifo-handler")]
322+
unsafe {
323+
handle_fifo_token(token);
324+
}
325+
}
326+
})
297327
}
298328
}
299329

300330
/// Resume CORE1 execution.
301331
pub fn resume_core1() {
302332
if IS_CORE1_INIT.load(Ordering::Acquire) {
303-
fifo_write(RESUME_TOKEN);
304-
// Wait for CORE1 to signal it has resumed execution.
305-
while fifo_read() != RESUME_TOKEN {}
333+
cortex_m::interrupt::free(|_| {
334+
fifo_write(RESUME_TOKEN);
335+
// Wait for CORE1 to signal it has resumed execution.
336+
loop {
337+
let token = fifo_read();
338+
if token == RESUME_TOKEN {
339+
break;
340+
}
341+
#[cfg(feature = "fifo-handler")]
342+
unsafe {
343+
handle_fifo_token(token);
344+
}
345+
}
346+
})
306347
}
307348
}
308349

0 commit comments

Comments
 (0)