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.
This commit is contained in:
pennae 2023-05-02 08:39:05 +02:00
parent 8fc92fdf62
commit 849011b826
4 changed files with 75 additions and 7 deletions

View File

@ -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<P = T> + '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 }

View File

@ -157,6 +157,7 @@ pub fn init(_config: config::Config) -> Peripherals {
timer::init();
dma::init();
pio::init();
gpio::init();
}
peripherals

View File

@ -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

View File

@ -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<Executor> = StaticCell::new();
static EXECUTOR1: StaticCell<Executor> = StaticCell::new();
static CHANNEL0: Channel<CriticalSectionRawMutex, (), 1> = Channel::new();
static CHANNEL1: Channel<CriticalSectionRawMutex, (), 1> = 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;
}