From a8c140ab57f8cf4571a032f9bae9f3417f7c21da Mon Sep 17 00:00:00 2001 From: Jan Niehusmann Date: Tue, 27 Aug 2024 07:10:03 +0000 Subject: [PATCH] Provide arch module on RP2040 This improves code portability between rp2040-hal and rp235x-hal --- rp2040-hal-examples/src/bin/pio_side_set.rs | 2 +- rp2040-hal/src/arch.rs | 67 +++++++++++++++++++++ rp2040-hal/src/lib.rs | 1 + 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 rp2040-hal/src/arch.rs diff --git a/rp2040-hal-examples/src/bin/pio_side_set.rs b/rp2040-hal-examples/src/bin/pio_side_set.rs index 5db05f260..f1d1dae0e 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 000000000..4360d4b1b --- /dev/null +++ b/rp2040-hal/src/arch.rs @@ -0,0 +1,67 @@ +//! 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 a71cc0a95..2c16312e8 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;