From 849011b8261194629830b4b85d062394e8eb3c58 Mon Sep 17 00:00:00 2001 From: pennae Date: Tue, 2 May 2023 08:39:05 +0200 Subject: [PATCH] rp/gpio: set up gpio interrupts only once doing this setup work repeatedly, on every wait, is unnecessary. with nothing ever disabling the interrupt it is sufficient to enable it once during device init and never touch it again. --- embassy-rp/src/gpio.rs | 13 +++--- embassy-rp/src/lib.rs | 1 + embassy-rp/src/multicore.rs | 5 ++- tests/rp/src/bin/gpio_multicore.rs | 63 ++++++++++++++++++++++++++++++ 4 files changed, 75 insertions(+), 7 deletions(-) create mode 100644 tests/rp/src/bin/gpio_multicore.rs diff --git a/embassy-rp/src/gpio.rs b/embassy-rp/src/gpio.rs index 66b9af04b..da8efba91 100644 --- a/embassy-rp/src/gpio.rs +++ b/embassy-rp/src/gpio.rs @@ -136,6 +136,13 @@ pub enum InterruptTrigger { AnyEdge, } +pub(crate) unsafe fn init() { + let irq = interrupt::IO_IRQ_BANK0::steal(); + irq.disable(); + irq.set_priority(interrupt::Priority::P3); + irq.enable(); +} + #[interrupt] unsafe fn IO_IRQ_BANK0() { let cpu = SIO.cpuid().read() as usize; @@ -179,10 +186,6 @@ impl<'d, T: Pin> InputFuture<'d, T> { pub fn new(pin: impl Peripheral

+ 'd, level: InterruptTrigger) -> Self { into_ref!(pin); unsafe { - let irq = interrupt::IO_IRQ_BANK0::steal(); - irq.disable(); - irq.set_priority(interrupt::Priority::P3); - let pin_group = (pin.pin() % 8) as usize; // first, clear the INTR register bits. without this INTR will still // contain reports of previous edges, causing the IRQ to fire early @@ -221,8 +224,6 @@ impl<'d, T: Pin> InputFuture<'d, T> { w.set_edge_low(pin_group, true); } }); - - irq.enable(); } Self { pin, level } diff --git a/embassy-rp/src/lib.rs b/embassy-rp/src/lib.rs index d69d12a30..cba7559df 100644 --- a/embassy-rp/src/lib.rs +++ b/embassy-rp/src/lib.rs @@ -157,6 +157,7 @@ pub fn init(_config: config::Config) -> Peripherals { timer::init(); dma::init(); pio::init(); + gpio::init(); } peripherals diff --git a/embassy-rp/src/multicore.rs b/embassy-rp/src/multicore.rs index e51fc218a..c84fea5c8 100644 --- a/embassy-rp/src/multicore.rs +++ b/embassy-rp/src/multicore.rs @@ -33,7 +33,7 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering}; use crate::interrupt::{Interrupt, InterruptExt}; use crate::peripherals::CORE1; -use crate::{interrupt, pac}; +use crate::{gpio, interrupt, pac}; const PAUSE_TOKEN: u32 = 0xDEADBEEF; const RESUME_TOKEN: u32 = !0xDEADBEEF; @@ -68,6 +68,9 @@ fn install_stack_guard(stack_bottom: *mut usize) { #[inline(always)] fn core1_setup(stack_bottom: *mut usize) { install_stack_guard(stack_bottom); + unsafe { + gpio::init(); + } } /// Data type for a properly aligned stack of N bytes diff --git a/tests/rp/src/bin/gpio_multicore.rs b/tests/rp/src/bin/gpio_multicore.rs new file mode 100644 index 000000000..6c13ccaae --- /dev/null +++ b/tests/rp/src/bin/gpio_multicore.rs @@ -0,0 +1,63 @@ +#![no_std] +#![no_main] +#![feature(type_alias_impl_trait)] + +use defmt::{info, unwrap}; +use embassy_executor::Executor; +use embassy_executor::_export::StaticCell; +use embassy_rp::gpio::{Input, Level, Output, Pull}; +use embassy_rp::multicore::{spawn_core1, Stack}; +use embassy_rp::peripherals::{PIN_0, PIN_1}; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::channel::Channel; +use {defmt_rtt as _, panic_probe as _}; + +static mut CORE1_STACK: Stack<1024> = Stack::new(); +static EXECUTOR0: StaticCell = StaticCell::new(); +static EXECUTOR1: StaticCell = StaticCell::new(); +static CHANNEL0: Channel = Channel::new(); +static CHANNEL1: Channel = Channel::new(); + +#[cortex_m_rt::entry] +fn main() -> ! { + let p = embassy_rp::init(Default::default()); + spawn_core1(p.CORE1, unsafe { &mut CORE1_STACK }, move || { + let executor1 = EXECUTOR1.init(Executor::new()); + executor1.run(|spawner| unwrap!(spawner.spawn(core1_task(p.PIN_1)))); + }); + let executor0 = EXECUTOR0.init(Executor::new()); + executor0.run(|spawner| unwrap!(spawner.spawn(core0_task(p.PIN_0)))); +} + +#[embassy_executor::task] +async fn core0_task(p: PIN_0) { + info!("CORE0 is running"); + + let mut pin = Output::new(p, Level::Low); + + CHANNEL0.send(()).await; + CHANNEL1.recv().await; + + pin.set_high(); + + CHANNEL1.recv().await; + + info!("Test OK"); + cortex_m::asm::bkpt(); +} + +#[embassy_executor::task] +async fn core1_task(p: PIN_1) { + info!("CORE1 is running"); + + CHANNEL0.recv().await; + + let mut pin = Input::new(p, Pull::Down); + let wait = pin.wait_for_rising_edge(); + + CHANNEL1.send(()).await; + + wait.await; + + CHANNEL1.send(()).await; +}