diff --git a/embassy-nrf/src/buffered_uarte.rs b/embassy-nrf/src/buffered_uarte.rs index 9e138ad4..db6a83fb 100644 --- a/embassy-nrf/src/buffered_uarte.rs +++ b/embassy-nrf/src/buffered_uarte.rs @@ -17,10 +17,10 @@ use embedded_hal::digital::v2::OutputPin; use crate::hal::gpio::{Floating, Input, Output, Pin as GpioPin, Port as GpioPort, PushPull}; use crate::interrupt; -use crate::interrupt::CriticalSection; +use crate::interrupt::{CriticalSection, OwnedInterrupt}; #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] use crate::pac::UARTE1; -use crate::pac::{uarte0, Interrupt, UARTE0}; +use crate::pac::{uarte0, UARTE0}; // Re-export SVD variants to allow user to directly set values pub use uarte0::{baudrate::BAUDRATE_A as Baudrate, config::PARITY_A as Parity}; @@ -141,8 +141,9 @@ pub struct BufferedUarte { // public because it needs to be used in Instance::{get_state, set_state}, but // should not be used outside the module #[doc(hidden)] -pub struct UarteState { +pub struct UarteState { inner: T, + irq: T::Interrupt, rx: RingBuf, rx_state: RxState, @@ -164,7 +165,13 @@ fn port_bit(port: GpioPort) -> bool { } impl BufferedUarte { - pub fn new(uarte: T, mut pins: Pins, parity: Parity, baudrate: Baudrate) -> Self { + pub fn new( + uarte: T, + irq: T::Interrupt, + mut pins: Pins, + parity: Parity, + baudrate: Baudrate, + ) -> Self { // Select pins uarte.psel.rxd.write(|w| { let w = unsafe { w.pin().bits(pins.rxd.pin()) }; @@ -222,6 +229,7 @@ impl BufferedUarte { started: false, state: UnsafeCell::new(UarteState { inner: uarte, + irq, rx: RingBuf::new(), rx_state: RxState::Idle, @@ -287,9 +295,12 @@ impl AsyncWrite for BufferedUarte { impl UarteState { pub fn start(self: Pin<&mut Self>) { - interrupt::set_priority(T::interrupt(), interrupt::Priority::Level7); - interrupt::enable(T::interrupt()); - interrupt::pend(T::interrupt()); + self.irq.set_handler(|| unsafe { + interrupt::free(|cs| T::get_state(cs).as_mut().unwrap().on_interrupt()); + }); + + self.irq.pend(); + self.irq.enable(); } fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll> { @@ -324,7 +335,7 @@ impl UarteState { let this = unsafe { self.get_unchecked_mut() }; trace!("consume {:?}", amt); this.rx.pop(amt); - interrupt::pend(T::interrupt()); + this.irq.pend(); } fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll> { @@ -350,7 +361,7 @@ impl UarteState { // before any DMA action has started compiler_fence(Ordering::SeqCst); - interrupt::pend(T::interrupt()); + this.irq.pend(); Poll::Ready(Ok(n)) } @@ -509,7 +520,7 @@ mod private { } pub trait Instance: Deref + Sized + private::Sealed { - fn interrupt() -> Interrupt; + type Interrupt: OwnedInterrupt; #[doc(hidden)] fn get_state(_cs: &CriticalSection) -> *mut UarteState; @@ -518,25 +529,12 @@ pub trait Instance: Deref + Sized + private::Sea fn set_state(_cs: &CriticalSection, state: *mut UarteState); } -#[interrupt] -unsafe fn UARTE0_UART0() { - interrupt::free(|cs| UARTE0::get_state(cs).as_mut().unwrap().on_interrupt()); -} - -#[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] -#[interrupt] -unsafe fn UARTE1() { - interrupt::free(|cs| UARTE1::get_state(cs).as_mut().unwrap().on_interrupt()); -} - static mut UARTE0_STATE: *mut UarteState = ptr::null_mut(); #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] static mut UARTE1_STATE: *mut UarteState = ptr::null_mut(); impl Instance for UARTE0 { - fn interrupt() -> Interrupt { - Interrupt::UARTE0_UART0 - } + type Interrupt = interrupt::UARTE0_UART0Interrupt; fn get_state(_cs: &CriticalSection) -> *mut UarteState { unsafe { UARTE0_STATE } // Safe because of CriticalSection @@ -548,9 +546,7 @@ impl Instance for UARTE0 { #[cfg(any(feature = "52833", feature = "52840", feature = "9160"))] impl Instance for UARTE1 { - fn interrupt() -> Interrupt { - Interrupt::UARTE1 - } + type Interrupt = interrupt::UARTE1Interrupt; fn get_state(_cs: &CriticalSection) -> *mut UarteState { unsafe { UARTE1_STATE } // Safe because of CriticalSection diff --git a/embassy-nrf/src/gpiote.rs b/embassy-nrf/src/gpiote.rs index 069e9140..353f6a94 100644 --- a/embassy-nrf/src/gpiote.rs +++ b/embassy-nrf/src/gpiote.rs @@ -7,6 +7,7 @@ use embassy::util::Signal; use crate::hal::gpio::{Input, Level, Output, Pin, Port}; use crate::interrupt; +use crate::interrupt::OwnedInterrupt; use crate::pac::generic::Reg; use crate::pac::gpiote::_TASKS_OUT; #[cfg(any(feature = "52833", feature = "52840"))] @@ -58,7 +59,7 @@ pub enum NewChannelError { } impl Gpiote { - pub fn new(gpiote: GPIOTE) -> Self { + pub fn new(gpiote: GPIOTE, irq: interrupt::GPIOTEInterrupt) -> Self { #[cfg(any(feature = "52833", feature = "52840"))] let ports = unsafe { &[&*P0::ptr(), &*P1::ptr()] }; #[cfg(not(any(feature = "52833", feature = "52840")))] @@ -74,8 +75,9 @@ impl Gpiote { // Enable interrupts gpiote.events_port.write(|w| w); gpiote.intenset.write(|w| w.port().set()); - interrupt::unpend(interrupt::GPIOTE); - interrupt::enable(interrupt::GPIOTE); + irq.set_handler(Self::on_irq); + irq.unpend(); + irq.enable(); Self { inner: gpiote, @@ -293,6 +295,39 @@ impl Gpiote { }) }) } + + unsafe fn on_irq() { + let s = &(*INSTANCE); + + for i in 0..8 { + if s.inner.events_in[i].read().bits() != 0 { + s.inner.events_in[i].write(|w| w); + s.channel_signals[i].signal(()); + } + } + + if s.inner.events_port.read().bits() != 0 { + s.inner.events_port.write(|w| w); + + #[cfg(any(feature = "52833", feature = "52840"))] + let ports = &[&*P0::ptr(), &*P1::ptr()]; + #[cfg(not(any(feature = "52833", feature = "52840")))] + let ports = &[&*P0::ptr()]; + + let mut work = true; + while work { + work = false; + for (port, &p) in ports.iter().enumerate() { + for pin in BitIter(p.latch.read().bits()) { + work = true; + p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled()); + p.latch.write(|w| w.bits(1 << pin)); + s.port_signals[port * 32 + pin as usize].signal(()); + } + } + } + } + } } pub struct PortInputFuture<'a, T> { @@ -413,40 +448,6 @@ impl<'a> OutputChannel<'a> { } } -#[interrupt] -unsafe fn GPIOTE() { - let s = &(*INSTANCE); - - for i in 0..8 { - if s.inner.events_in[i].read().bits() != 0 { - s.inner.events_in[i].write(|w| w); - s.channel_signals[i].signal(()); - } - } - - if s.inner.events_port.read().bits() != 0 { - s.inner.events_port.write(|w| w); - - #[cfg(any(feature = "52833", feature = "52840"))] - let ports = &[&*P0::ptr(), &*P1::ptr()]; - #[cfg(not(any(feature = "52833", feature = "52840")))] - let ports = &[&*P0::ptr()]; - - let mut work = true; - while work { - work = false; - for (port, &p) in ports.iter().enumerate() { - for pin in BitIter(p.latch.read().bits()) { - work = true; - p.pin_cnf[pin as usize].modify(|_, w| w.sense().disabled()); - p.latch.write(|w| w.bits(1 << pin)); - s.port_signals[port * 32 + pin as usize].signal(()); - } - } - } - } -} - struct BitIter(u32); impl Iterator for BitIter { diff --git a/embassy-nrf/src/lib.rs b/embassy-nrf/src/lib.rs index c63bfd99..0ca32813 100644 --- a/embassy-nrf/src/lib.rs +++ b/embassy-nrf/src/lib.rs @@ -51,8 +51,8 @@ pub use nrf52840_hal as hal; // This mod MUST go first, so that the others see its macros. pub(crate) mod fmt; -//pub mod buffered_uarte; -//pub mod gpiote; +pub mod buffered_uarte; +pub mod gpiote; pub mod interrupt; #[cfg(feature = "52840")] pub mod qspi; diff --git a/examples/src/bin/gpiote.rs b/examples/src/bin/gpiote.rs index edc3f5ef..afa1b85d 100644 --- a/examples/src/bin/gpiote.rs +++ b/examples/src/bin/gpiote.rs @@ -7,18 +7,20 @@ mod example_common; use example_common::*; use cortex_m_rt::entry; +use defmt::panic; use nrf52840_hal::gpio; use embassy::executor::{task, Executor}; use embassy::util::Forever; use embassy_nrf::gpiote; +use embassy_nrf::interrupt; #[task] async fn run() { let p = unwrap!(embassy_nrf::pac::Peripherals::take()); let port0 = gpio::p0::Parts::new(p.P0); - let g = gpiote::Gpiote::new(p.GPIOTE); + let g = gpiote::Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE)); info!("Starting!"); diff --git a/examples/src/bin/gpiote_port.rs b/examples/src/bin/gpiote_port.rs index 58531764..f5aa8132 100644 --- a/examples/src/bin/gpiote_port.rs +++ b/examples/src/bin/gpiote_port.rs @@ -8,11 +8,13 @@ use example_common::*; use core::mem; use cortex_m_rt::entry; +use defmt::panic; use nrf52840_hal::gpio; use embassy::executor::{task, Executor}; use embassy::util::Forever; use embassy_nrf::gpiote::{Gpiote, PortInputPolarity}; +use embassy_nrf::interrupt; async fn button(g: &Gpiote, n: usize, pin: gpio::Pin>) { loop { @@ -28,7 +30,7 @@ async fn run() { let p = unwrap!(embassy_nrf::pac::Peripherals::take()); let port0 = gpio::p0::Parts::new(p.P0); - let g = Gpiote::new(p.GPIOTE); + let g = Gpiote::new(p.GPIOTE, interrupt::take!(GPIOTE)); info!( "sizeof Signal<()> = {:usize}", mem::size_of::>() diff --git a/examples/src/bin/uart.rs b/examples/src/bin/uart.rs index e664fcef..6e15fbcf 100644 --- a/examples/src/bin/uart.rs +++ b/examples/src/bin/uart.rs @@ -7,6 +7,7 @@ mod example_common; use example_common::*; use cortex_m_rt::entry; +use defmt::panic; use futures::pin_mut; use nrf52840_hal::gpio; @@ -14,6 +15,7 @@ use embassy::executor::{task, Executor}; use embassy::io::{AsyncBufRead, AsyncBufReadExt, AsyncWrite, AsyncWriteExt}; use embassy::util::Forever; use embassy_nrf::buffered_uarte; +use embassy_nrf::interrupt; #[task] async fn run() { @@ -31,8 +33,10 @@ async fn run() { rts: None, }; + let irq = interrupt::take!(UARTE0_UART0); let u = buffered_uarte::BufferedUarte::new( p.UARTE0, + irq, pins, buffered_uarte::Parity::EXCLUDED, buffered_uarte::Baudrate::BAUD115200,