diff --git a/rp2040-hal-examples/src/bin/pio_side_set.rs b/rp2040-hal-examples/src/bin/pio_side_set.rs index 5db05f26..f1d1dae0 100644 --- a/rp2040-hal-examples/src/bin/pio_side_set.rs +++ b/rp2040-hal-examples/src/bin/pio_side_set.rs @@ -65,6 +65,6 @@ fn main() -> ! { // PIO runs in background, independently from CPU loop { - cortex_m::asm::wfi(); + hal::arch::wfi(); } } diff --git a/rp2040-hal/src/arch.rs b/rp2040-hal/src/arch.rs new file mode 100644 index 00000000..b8d3c9ca --- /dev/null +++ b/rp2040-hal/src/arch.rs @@ -0,0 +1,68 @@ +//! Portable in-line assembly +//! +//! On the RP235x, this is useful to write code portable between ARM and RISC-V cores. +//! While there's no such choice on the RP2040, providing the same functions helps writing +//! code that works on both RP2040 and RP235x. + +#[cfg(all(target_arch = "arm", target_os = "none"))] +mod inner { + pub use cortex_m::asm::{delay, dsb, nop, sev, wfe, wfi}; + pub use cortex_m::interrupt::{disable as interrupt_disable, enable as interrupt_enable}; + + /// Are interrupts current enabled? + pub fn interrupts_enabled() -> bool { + cortex_m::register::primask::read().is_active() + } + + /// Run the closure without interrupts + /// + /// No critical-section token because we haven't blocked the second core + pub fn interrupt_free(f: F) -> T + where + F: FnOnce() -> T, + { + let active = interrupts_enabled(); + if active { + interrupt_disable(); + } + let t = f(); + if active { + unsafe { + interrupt_enable(); + } + } + t + } +} + +#[cfg(not(all(any(target_arch = "arm", target_arch = "riscv32"), target_os = "none")))] +mod inner { + /// Placeholder function to disable interrupts + pub fn interrupt_disable() {} + /// Placeholder function to enable interrupts + pub fn interrupt_enable() {} + /// Placeholder function to check if interrupts are enabled + pub fn interrupts_enabled() -> bool { + false + } + /// Placeholder function to wait for an event + pub fn wfe() {} + /// Placeholder function to do nothing + pub fn nop() {} + /// Placeholder function to emit a data synchronisation barrier + pub fn dsb() {} + /// Placeholder function to run a closure with interrupts disabled + pub fn interrupt_free(f: F) -> T + where + F: FnOnce() -> T, + { + f() + } + /// Placeholder function to wait for some clock cycles + pub fn delay(_: u32) {} + /// Placeholder function to emit an event + pub fn sev() {} +} + +pub use inner::*; + diff --git a/rp2040-hal/src/lib.rs b/rp2040-hal/src/lib.rs index a71cc0a9..2c16312e 100644 --- a/rp2040-hal/src/lib.rs +++ b/rp2040-hal/src/lib.rs @@ -51,6 +51,7 @@ pub use rp2040_pac as pac; mod intrinsics; pub mod adc; +pub mod arch; #[macro_use] pub mod async_utils; pub(crate) mod atomic_register_access;