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:
parent
8fc92fdf62
commit
849011b826
4 changed files with 75 additions and 7 deletions
|
@ -136,6 +136,13 @@ pub enum InterruptTrigger {
|
||||||
AnyEdge,
|
AnyEdge,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) unsafe fn init() {
|
||||||
|
let irq = interrupt::IO_IRQ_BANK0::steal();
|
||||||
|
irq.disable();
|
||||||
|
irq.set_priority(interrupt::Priority::P3);
|
||||||
|
irq.enable();
|
||||||
|
}
|
||||||
|
|
||||||
#[interrupt]
|
#[interrupt]
|
||||||
unsafe fn IO_IRQ_BANK0() {
|
unsafe fn IO_IRQ_BANK0() {
|
||||||
let cpu = SIO.cpuid().read() as usize;
|
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 {
|
pub fn new(pin: impl Peripheral<P = T> + 'd, level: InterruptTrigger) -> Self {
|
||||||
into_ref!(pin);
|
into_ref!(pin);
|
||||||
unsafe {
|
unsafe {
|
||||||
let irq = interrupt::IO_IRQ_BANK0::steal();
|
|
||||||
irq.disable();
|
|
||||||
irq.set_priority(interrupt::Priority::P3);
|
|
||||||
|
|
||||||
let pin_group = (pin.pin() % 8) as usize;
|
let pin_group = (pin.pin() % 8) as usize;
|
||||||
// first, clear the INTR register bits. without this INTR will still
|
// first, clear the INTR register bits. without this INTR will still
|
||||||
// contain reports of previous edges, causing the IRQ to fire early
|
// 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);
|
w.set_edge_low(pin_group, true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
irq.enable();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Self { pin, level }
|
Self { pin, level }
|
||||||
|
|
|
@ -157,6 +157,7 @@ pub fn init(_config: config::Config) -> Peripherals {
|
||||||
timer::init();
|
timer::init();
|
||||||
dma::init();
|
dma::init();
|
||||||
pio::init();
|
pio::init();
|
||||||
|
gpio::init();
|
||||||
}
|
}
|
||||||
|
|
||||||
peripherals
|
peripherals
|
||||||
|
|
|
@ -33,7 +33,7 @@ use core::sync::atomic::{compiler_fence, AtomicBool, Ordering};
|
||||||
|
|
||||||
use crate::interrupt::{Interrupt, InterruptExt};
|
use crate::interrupt::{Interrupt, InterruptExt};
|
||||||
use crate::peripherals::CORE1;
|
use crate::peripherals::CORE1;
|
||||||
use crate::{interrupt, pac};
|
use crate::{gpio, interrupt, pac};
|
||||||
|
|
||||||
const PAUSE_TOKEN: u32 = 0xDEADBEEF;
|
const PAUSE_TOKEN: u32 = 0xDEADBEEF;
|
||||||
const RESUME_TOKEN: u32 = !0xDEADBEEF;
|
const RESUME_TOKEN: u32 = !0xDEADBEEF;
|
||||||
|
@ -68,6 +68,9 @@ fn install_stack_guard(stack_bottom: *mut usize) {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn core1_setup(stack_bottom: *mut usize) {
|
fn core1_setup(stack_bottom: *mut usize) {
|
||||||
install_stack_guard(stack_bottom);
|
install_stack_guard(stack_bottom);
|
||||||
|
unsafe {
|
||||||
|
gpio::init();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data type for a properly aligned stack of N bytes
|
/// Data type for a properly aligned stack of N bytes
|
||||||
|
|
63
tests/rp/src/bin/gpio_multicore.rs
Normal file
63
tests/rp/src/bin/gpio_multicore.rs
Normal 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;
|
||||||
|
}
|
Loading…
Reference in a new issue