1458: rp: remove take!, add bind_interrupts! r=Dirbaio a=pennae

both of the uart interrupts now check a flag that only the dma rx path ever sets (and now unsets again on drop) to return early if it's not as they expect. this is ... not our preferred solution, but if bind_interrupts *must* allow mutiple handlers to be specified then this is the only way we can think of that doesn't break uarts.

Co-authored-by: pennae <github@quasiparticle.net>
This commit is contained in:
bors[bot] 2023-05-15 15:59:30 +00:00 committed by GitHub
commit 1a87f7477a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
16 changed files with 374 additions and 277 deletions

View file

@ -3,12 +3,12 @@ use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy_hal_common::into_ref; use embassy_cortex_m::interrupt::{Binding, Interrupt};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use embedded_hal_02::adc::{Channel, OneShot}; use embedded_hal_02::adc::{Channel, OneShot};
use crate::gpio::Pin; use crate::gpio::Pin;
use crate::interrupt::{self, InterruptExt}; use crate::interrupt::{self, InterruptExt, ADC_IRQ_FIFO};
use crate::peripherals::ADC; use crate::peripherals::ADC;
use crate::{pac, peripherals, Peripheral}; use crate::{pac, peripherals, Peripheral};
static WAKER: AtomicWaker = AtomicWaker::new(); static WAKER: AtomicWaker = AtomicWaker::new();
@ -47,10 +47,9 @@ impl<'d> Adc<'d> {
pub fn new( pub fn new(
_inner: impl Peripheral<P = ADC> + 'd, _inner: impl Peripheral<P = ADC> + 'd,
irq: impl Peripheral<P = interrupt::ADC_IRQ_FIFO> + 'd, _irq: impl Binding<ADC_IRQ_FIFO, InterruptHandler>,
_config: Config, _config: Config,
) -> Self { ) -> Self {
into_ref!(irq);
unsafe { unsafe {
let reset = Self::reset(); let reset = Self::reset();
crate::reset::reset(reset); crate::reset::reset(reset);
@ -63,14 +62,10 @@ impl<'d> Adc<'d> {
} }
// Setup IRQ // Setup IRQ
irq.disable(); unsafe {
irq.set_handler(|_| unsafe { ADC_IRQ_FIFO::steal().unpend();
let r = Self::regs(); ADC_IRQ_FIFO::steal().enable();
r.inte().write(|w| w.set_fifo(false)); };
WAKER.wake();
});
irq.unpend();
irq.enable();
Self { phantom: PhantomData } Self { phantom: PhantomData }
} }
@ -165,6 +160,18 @@ macro_rules! impl_pin {
}; };
} }
pub struct InterruptHandler {
_empty: (),
}
impl interrupt::Handler<ADC_IRQ_FIFO> for InterruptHandler {
unsafe fn on_interrupt() {
let r = Adc::regs();
r.inte().write(|w| w.set_fifo(false));
WAKER.wake();
}
}
impl_pin!(PIN_26, 0); impl_pin!(PIN_26, 0);
impl_pin!(PIN_27, 1); impl_pin!(PIN_27, 1);
impl_pin!(PIN_28, 2); impl_pin!(PIN_28, 2);

View file

@ -2,7 +2,7 @@ use core::future;
use core::marker::PhantomData; use core::marker::PhantomData;
use core::task::Poll; use core::task::Poll;
use embassy_cortex_m::interrupt::InterruptExt; use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt};
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use pac::i2c; use pac::i2c;
@ -75,23 +75,21 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
peri: impl Peripheral<P = T> + 'd, peri: impl Peripheral<P = T> + 'd,
scl: impl Peripheral<P = impl SclPin<T>> + 'd, scl: impl Peripheral<P = impl SclPin<T>> + 'd,
sda: impl Peripheral<P = impl SdaPin<T>> + 'd, sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(scl, sda, irq); into_ref!(scl, sda);
let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config); let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config);
irq.set_handler(Self::on_interrupt);
unsafe { unsafe {
let i2c = T::regs(); let i2c = T::regs();
// mask everything initially // mask everything initially
i2c.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)); i2c.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0));
T::Interrupt::steal().unpend();
T::Interrupt::steal().enable();
} }
irq.unpend();
debug_assert!(!irq.is_pending());
irq.enable();
i2c i2c
} }
@ -115,14 +113,6 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
.await .await
} }
// Mask interrupts and wake any task waiting for this interrupt
unsafe fn on_interrupt(_: *mut ()) {
let i2c = T::regs();
i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default());
T::waker().wake();
}
async fn read_async_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> { async fn read_async_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> {
if buffer.is_empty() { if buffer.is_empty() {
return Err(Error::InvalidReadBufferLength); return Err(Error::InvalidReadBufferLength);
@ -320,6 +310,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
} }
} }
pub struct InterruptHandler<T: Instance> {
_uart: PhantomData<T>,
}
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
// Mask interrupts and wake any task waiting for this interrupt
unsafe fn on_interrupt() {
let i2c = T::regs();
i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default());
T::waker().wake();
}
}
impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
fn new_inner( fn new_inner(
_peri: impl Peripheral<P = T> + 'd, _peri: impl Peripheral<P = T> + 'd,

View file

@ -1,11 +1,7 @@
//! Interrupt management //! Interrupt definitions and macros to bind them.
//! pub use cortex_m::interrupt::{CriticalSection, Mutex};
//! This module implements an API for managing interrupts compatible with
//! nrf_softdevice::interrupt. Intended for switching between the two at compile-time.
// Re-exports
use embassy_cortex_m::interrupt::_export::declare; use embassy_cortex_m::interrupt::_export::declare;
pub use embassy_cortex_m::interrupt::*; pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority};
use crate::pac::Interrupt as InterruptEnum; use crate::pac::Interrupt as InterruptEnum;
declare!(TIMER_IRQ_0); declare!(TIMER_IRQ_0);
@ -40,3 +36,30 @@ declare!(SWI_IRQ_2);
declare!(SWI_IRQ_3); declare!(SWI_IRQ_3);
declare!(SWI_IRQ_4); declare!(SWI_IRQ_4);
declare!(SWI_IRQ_5); declare!(SWI_IRQ_5);
/// Macro to bind interrupts to handlers.
///
/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
/// prove at compile-time that the right interrupts have been bound.
// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`.
#[macro_export]
macro_rules! bind_interrupts {
($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
$vis struct $name;
$(
#[allow(non_snake_case)]
#[no_mangle]
unsafe extern "C" fn $irq() {
$(
<$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt();
)*
}
$(
unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {}
)*
)*
};
}

View file

@ -3,7 +3,7 @@ use core::slice;
use core::task::Poll; use core::task::Poll;
use atomic_polyfill::{AtomicU8, Ordering}; use atomic_polyfill::{AtomicU8, Ordering};
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt};
use embassy_hal_common::atomic_ring_buffer::RingBuffer; use embassy_hal_common::atomic_ring_buffer::RingBuffer;
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
@ -52,7 +52,7 @@ pub struct BufferedUartTx<'d, T: Instance> {
} }
pub(crate) fn init_buffers<'d, T: Instance + 'd>( pub(crate) fn init_buffers<'d, T: Instance + 'd>(
irq: PeripheralRef<'d, T::Interrupt>, _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
) { ) {
@ -79,24 +79,23 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
w.set_rtim(true); w.set_rtim(true);
w.set_txim(true); w.set_txim(true);
}); });
};
irq.set_handler(on_interrupt::<T>); T::Interrupt::steal().unpend();
irq.unpend(); T::Interrupt::steal().enable();
irq.enable(); };
} }
impl<'d, T: Instance> BufferedUart<'d, T> { impl<'d, T: Instance> BufferedUart<'d, T> {
pub fn new( pub fn new(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(irq, tx, rx); into_ref!(tx, rx);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), Some(rx.map_into()), None, None, config); super::Uart::<'d, T, Async>::init(Some(tx.map_into()), Some(rx.map_into()), None, None, config);
init_buffers::<T>(irq, tx_buffer, rx_buffer); init_buffers::<T>(irq, tx_buffer, rx_buffer);
@ -109,7 +108,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
pub fn new_with_rtscts( pub fn new_with_rtscts(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd, rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
@ -118,7 +117,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(irq, tx, rx, cts, rts); into_ref!(tx, rx, cts, rts);
super::Uart::<'d, T, Async>::init( super::Uart::<'d, T, Async>::init(
Some(tx.map_into()), Some(tx.map_into()),
@ -163,12 +162,12 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
impl<'d, T: Instance> BufferedUartRx<'d, T> { impl<'d, T: Instance> BufferedUartRx<'d, T> {
pub fn new( pub fn new(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(irq, rx); into_ref!(rx);
super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config); super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config);
init_buffers::<T>(irq, &mut [], rx_buffer); init_buffers::<T>(irq, &mut [], rx_buffer);
@ -178,13 +177,13 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
pub fn new_with_rts( pub fn new_with_rts(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd, rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(irq, rx, rts); into_ref!(rx, rts);
super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), Some(rts.map_into()), None, config); super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), Some(rts.map_into()), None, config);
init_buffers::<T>(irq, &mut [], rx_buffer); init_buffers::<T>(irq, &mut [], rx_buffer);
@ -312,12 +311,12 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
impl<'d, T: Instance> BufferedUartTx<'d, T> { impl<'d, T: Instance> BufferedUartTx<'d, T> {
pub fn new( pub fn new(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(irq, tx); into_ref!(tx);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config); super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config);
init_buffers::<T>(irq, tx_buffer, &mut []); init_buffers::<T>(irq, tx_buffer, &mut []);
@ -327,13 +326,13 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
pub fn new_with_cts( pub fn new_with_cts(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd, cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(irq, tx, cts); into_ref!(tx, cts);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, Some(cts.map_into()), config); super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, Some(cts.map_into()), config);
init_buffers::<T>(irq, tx_buffer, &mut []); init_buffers::<T>(irq, tx_buffer, &mut []);
@ -482,8 +481,17 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
} }
} }
pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) { pub struct BufferedInterruptHandler<T: Instance> {
_uart: PhantomData<T>,
}
impl<T: Instance> interrupt::Handler<T::Interrupt> for BufferedInterruptHandler<T> {
unsafe fn on_interrupt() {
let r = T::regs(); let r = T::regs();
if r.uartdmacr().read().rxdmae() {
return;
}
let s = T::buffered_state(); let s = T::buffered_state();
unsafe { unsafe {
@ -574,6 +582,7 @@ pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) {
// crossed. No need to disable it when the buffer becomes empty // crossed. No need to disable it when the buffer becomes empty
// as it does re-trigger anymore once we have cleared it. // as it does re-trigger anymore once we have cleared it.
} }
}
} }
impl embedded_io::Error for Error { impl embedded_io::Error for Error {

View file

@ -3,7 +3,7 @@ use core::marker::PhantomData;
use core::task::Poll; use core::task::Poll;
use atomic_polyfill::{AtomicU16, Ordering}; use atomic_polyfill::{AtomicU16, Ordering};
use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt};
use embassy_futures::select::{select, Either}; use embassy_futures::select::{select, Either};
use embassy_hal_common::{into_ref, PeripheralRef}; use embassy_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
@ -20,7 +20,7 @@ use crate::{pac, peripherals, Peripheral, RegExt};
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
mod buffered; mod buffered;
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub use buffered::{BufferedUart, BufferedUartRx, BufferedUartTx}; pub use buffered::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx};
#[derive(Clone, Copy, PartialEq, Eq, Debug)] #[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum DataBits { pub enum DataBits {
@ -203,11 +203,9 @@ impl<'d, T: Instance> UartTx<'d, T, Blocking> {
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub fn into_buffered( pub fn into_buffered(
self, self,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
) -> BufferedUartTx<'d, T> { ) -> BufferedUartTx<'d, T> {
into_ref!(irq);
buffered::init_buffers::<T>(irq, tx_buffer, &mut []); buffered::init_buffers::<T>(irq, tx_buffer, &mut []);
BufferedUartTx { phantom: PhantomData } BufferedUartTx { phantom: PhantomData }
@ -235,25 +233,24 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
pub fn new( pub fn new(
_uart: impl Peripheral<P = T> + 'd, _uart: impl Peripheral<P = T> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
rx_dma: impl Peripheral<P = impl Channel> + 'd, rx_dma: impl Peripheral<P = impl Channel> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(rx, irq, rx_dma); into_ref!(rx, rx_dma);
Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config); Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
Self::new_inner(Some(irq), Some(rx_dma.map_into())) Self::new_inner(true, Some(rx_dma.map_into()))
} }
fn new_inner(irq: Option<PeripheralRef<'d, T::Interrupt>>, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self { fn new_inner(has_irq: bool, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
debug_assert_eq!(irq.is_some(), rx_dma.is_some()); debug_assert_eq!(has_irq, rx_dma.is_some());
if let Some(irq) = irq { if has_irq {
unsafe { unsafe {
// disable all error interrupts initially // disable all error interrupts initially
T::regs().uartimsc().write(|w| w.0 = 0); T::regs().uartimsc().write(|w| w.0 = 0);
T::Interrupt::steal().unpend();
T::Interrupt::steal().enable();
} }
irq.set_handler(on_interrupt::<T>);
irq.unpend();
irq.enable();
} }
Self { Self {
rx_dma, rx_dma,
@ -299,6 +296,12 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
if let Some(_) = self.rx_dma { if let Some(_) = self.rx_dma {
unsafe { unsafe {
T::Interrupt::steal().disable(); T::Interrupt::steal().disable();
// clear dma flags. irq handlers use these to disambiguate among themselves.
T::regs().uartdmacr().write_clear(|reg| {
reg.set_rxdmae(true);
reg.set_txdmae(true);
reg.set_dmaonerr(true);
});
} }
} }
} }
@ -312,25 +315,32 @@ impl<'d, T: Instance> UartRx<'d, T, Blocking> {
) -> Self { ) -> Self {
into_ref!(rx); into_ref!(rx);
Uart::<T, Blocking>::init(None, Some(rx.map_into()), None, None, config); Uart::<T, Blocking>::init(None, Some(rx.map_into()), None, None, config);
Self::new_inner(None, None) Self::new_inner(false, None)
} }
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub fn into_buffered( pub fn into_buffered(
self, self,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
) -> BufferedUartRx<'d, T> { ) -> BufferedUartRx<'d, T> {
into_ref!(irq);
buffered::init_buffers::<T>(irq, &mut [], rx_buffer); buffered::init_buffers::<T>(irq, &mut [], rx_buffer);
BufferedUartRx { phantom: PhantomData } BufferedUartRx { phantom: PhantomData }
} }
} }
unsafe fn on_interrupt<T: Instance>(_: *mut ()) { pub struct InterruptHandler<T: Instance> {
_uart: PhantomData<T>,
}
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
let uart = T::regs(); let uart = T::regs();
if !uart.uartdmacr().read().rxdmae() {
return;
}
let state = T::dma_state(); let state = T::dma_state();
let errs = uart.uartris().read(); let errs = uart.uartris().read();
state.rx_errs.store(errs.0 as u16, Ordering::Relaxed); state.rx_errs.store(errs.0 as u16, Ordering::Relaxed);
@ -339,6 +349,7 @@ unsafe fn on_interrupt<T: Instance>(_: *mut ()) {
// flags would allow the dma transfer to continue, potentially signaling // flags would allow the dma transfer to continue, potentially signaling
// completion before we can check for errors that happened *during* the transfer. // completion before we can check for errors that happened *during* the transfer.
uart.uartimsc().write_clear(|w| w.0 = errs.0); uart.uartimsc().write_clear(|w| w.0 = errs.0);
}
} }
impl<'d, T: Instance> UartRx<'d, T, Async> { impl<'d, T: Instance> UartRx<'d, T, Async> {
@ -428,7 +439,17 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(tx, rx); into_ref!(tx, rx);
Self::new_inner(uart, tx.map_into(), rx.map_into(), None, None, None, None, None, config) Self::new_inner(
uart,
tx.map_into(),
rx.map_into(),
None,
None,
false,
None,
None,
config,
)
} }
/// Create a new UART with hardware flow control (RTS/CTS) /// Create a new UART with hardware flow control (RTS/CTS)
@ -447,7 +468,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
rx.map_into(), rx.map_into(),
Some(rts.map_into()), Some(rts.map_into()),
Some(cts.map_into()), Some(cts.map_into()),
None, false,
None, None,
None, None,
config, config,
@ -457,12 +478,10 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
#[cfg(feature = "nightly")] #[cfg(feature = "nightly")]
pub fn into_buffered( pub fn into_buffered(
self, self,
irq: impl Peripheral<P = T::Interrupt> + 'd, irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
tx_buffer: &'d mut [u8], tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8], rx_buffer: &'d mut [u8],
) -> BufferedUart<'d, T> { ) -> BufferedUart<'d, T> {
into_ref!(irq);
buffered::init_buffers::<T>(irq, tx_buffer, rx_buffer); buffered::init_buffers::<T>(irq, tx_buffer, rx_buffer);
BufferedUart { BufferedUart {
@ -478,19 +497,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
uart: impl Peripheral<P = T> + 'd, uart: impl Peripheral<P = T> + 'd,
tx: impl Peripheral<P = impl TxPin<T>> + 'd, tx: impl Peripheral<P = impl TxPin<T>> + 'd,
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
tx_dma: impl Peripheral<P = impl Channel> + 'd, tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd, rx_dma: impl Peripheral<P = impl Channel> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(tx, rx, irq, tx_dma, rx_dma); into_ref!(tx, rx, tx_dma, rx_dma);
Self::new_inner( Self::new_inner(
uart, uart,
tx.map_into(), tx.map_into(),
rx.map_into(), rx.map_into(),
None, None,
None, None,
Some(irq), true,
Some(tx_dma.map_into()), Some(tx_dma.map_into()),
Some(rx_dma.map_into()), Some(rx_dma.map_into()),
config, config,
@ -504,19 +523,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
rx: impl Peripheral<P = impl RxPin<T>> + 'd, rx: impl Peripheral<P = impl RxPin<T>> + 'd,
rts: impl Peripheral<P = impl RtsPin<T>> + 'd, rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
cts: impl Peripheral<P = impl CtsPin<T>> + 'd, cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
irq: impl Peripheral<P = T::Interrupt> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
tx_dma: impl Peripheral<P = impl Channel> + 'd, tx_dma: impl Peripheral<P = impl Channel> + 'd,
rx_dma: impl Peripheral<P = impl Channel> + 'd, rx_dma: impl Peripheral<P = impl Channel> + 'd,
config: Config, config: Config,
) -> Self { ) -> Self {
into_ref!(tx, rx, cts, rts, irq, tx_dma, rx_dma); into_ref!(tx, rx, cts, rts, tx_dma, rx_dma);
Self::new_inner( Self::new_inner(
uart, uart,
tx.map_into(), tx.map_into(),
rx.map_into(), rx.map_into(),
Some(rts.map_into()), Some(rts.map_into()),
Some(cts.map_into()), Some(cts.map_into()),
Some(irq), true,
Some(tx_dma.map_into()), Some(tx_dma.map_into()),
Some(rx_dma.map_into()), Some(rx_dma.map_into()),
config, config,
@ -531,7 +550,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
mut rx: PeripheralRef<'d, AnyPin>, mut rx: PeripheralRef<'d, AnyPin>,
mut rts: Option<PeripheralRef<'d, AnyPin>>, mut rts: Option<PeripheralRef<'d, AnyPin>>,
mut cts: Option<PeripheralRef<'d, AnyPin>>, mut cts: Option<PeripheralRef<'d, AnyPin>>,
irq: Option<PeripheralRef<'d, T::Interrupt>>, has_irq: bool,
tx_dma: Option<PeripheralRef<'d, AnyChannel>>, tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
rx_dma: Option<PeripheralRef<'d, AnyChannel>>, rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
config: Config, config: Config,
@ -546,7 +565,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
Self { Self {
tx: UartTx::new_inner(tx_dma), tx: UartTx::new_inner(tx_dma),
rx: UartRx::new_inner(irq, rx_dma), rx: UartRx::new_inner(has_irq, rx_dma),
} }
} }

View file

@ -4,7 +4,7 @@ use core::slice;
use core::sync::atomic::{compiler_fence, Ordering}; use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll; use core::task::Poll;
use embassy_hal_common::into_ref; use embassy_cortex_m::interrupt::{self, Binding};
use embassy_sync::waitqueue::AtomicWaker; use embassy_sync::waitqueue::AtomicWaker;
use embassy_usb_driver as driver; use embassy_usb_driver as driver;
use embassy_usb_driver::{ use embassy_usb_driver::{
@ -105,11 +105,11 @@ pub struct Driver<'d, T: Instance> {
} }
impl<'d, T: Instance> Driver<'d, T> { impl<'d, T: Instance> Driver<'d, T> {
pub fn new(_usb: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd) -> Self { pub fn new(_usb: impl Peripheral<P = T> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> Self {
into_ref!(irq); unsafe {
irq.set_handler(Self::on_interrupt); T::Interrupt::steal().unpend();
irq.unpend(); T::Interrupt::steal().enable();
irq.enable(); }
let regs = T::regs(); let regs = T::regs();
unsafe { unsafe {
@ -149,47 +149,6 @@ impl<'d, T: Instance> Driver<'d, T> {
} }
} }
fn on_interrupt(_: *mut ()) {
unsafe {
let regs = T::regs();
//let x = regs.istr().read().0;
//trace!("USB IRQ: {:08x}", x);
let ints = regs.ints().read();
if ints.bus_reset() {
regs.inte().write_clear(|w| w.set_bus_reset(true));
BUS_WAKER.wake();
}
if ints.dev_resume_from_host() {
regs.inte().write_clear(|w| w.set_dev_resume_from_host(true));
BUS_WAKER.wake();
}
if ints.dev_suspend() {
regs.inte().write_clear(|w| w.set_dev_suspend(true));
BUS_WAKER.wake();
}
if ints.setup_req() {
regs.inte().write_clear(|w| w.set_setup_req(true));
EP_OUT_WAKERS[0].wake();
}
if ints.buff_status() {
let s = regs.buff_status().read();
regs.buff_status().write_value(s);
for i in 0..EP_COUNT {
if s.ep_in(i) {
EP_IN_WAKERS[i].wake();
}
if s.ep_out(i) {
EP_OUT_WAKERS[i].wake();
}
}
}
}
}
fn alloc_endpoint<D: Dir>( fn alloc_endpoint<D: Dir>(
&mut self, &mut self,
ep_type: EndpointType, ep_type: EndpointType,
@ -288,6 +247,51 @@ impl<'d, T: Instance> Driver<'d, T> {
} }
} }
pub struct InterruptHandler<T: Instance> {
_uart: PhantomData<T>,
}
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
unsafe fn on_interrupt() {
let regs = T::regs();
//let x = regs.istr().read().0;
//trace!("USB IRQ: {:08x}", x);
let ints = regs.ints().read();
if ints.bus_reset() {
regs.inte().write_clear(|w| w.set_bus_reset(true));
BUS_WAKER.wake();
}
if ints.dev_resume_from_host() {
regs.inte().write_clear(|w| w.set_dev_resume_from_host(true));
BUS_WAKER.wake();
}
if ints.dev_suspend() {
regs.inte().write_clear(|w| w.set_dev_suspend(true));
BUS_WAKER.wake();
}
if ints.setup_req() {
regs.inte().write_clear(|w| w.set_setup_req(true));
EP_OUT_WAKERS[0].wake();
}
if ints.buff_status() {
let s = regs.buff_status().read();
regs.buff_status().write_value(s);
for i in 0..EP_COUNT {
if s.ep_in(i) {
EP_IN_WAKERS[i].wake();
}
if s.ep_out(i) {
EP_OUT_WAKERS[i].wake();
}
}
}
}
}
impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
type EndpointOut = Endpoint<'d, T, Out>; type EndpointOut = Endpoint<'d, T, Out>;
type EndpointIn = Endpoint<'d, T, In>; type EndpointIn = Endpoint<'d, T, In>;

View file

@ -4,16 +4,19 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::adc::{Adc, Config}; use embassy_rp::adc::{Adc, Config, InterruptHandler};
use embassy_rp::interrupt; use embassy_rp::bind_interrupts;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
ADC_IRQ_FIFO => InterruptHandler;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
let irq = interrupt::take!(ADC_IRQ_FIFO); let mut adc = Adc::new(p.ADC, Irqs, Config::default());
let mut adc = Adc::new(p.ADC, irq, Config::default());
let mut p26 = p.PIN_26; let mut p26 = p.PIN_26;
let mut p27 = p.PIN_27; let mut p27 = p.PIN_27;

View file

@ -4,12 +4,17 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::i2c::{self, Config}; use embassy_rp::bind_interrupts;
use embassy_rp::interrupt; use embassy_rp::i2c::{self, Config, InterruptHandler};
use embassy_rp::peripherals::I2C1;
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use embedded_hal_async::i2c::I2c; use embedded_hal_async::i2c::I2c;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
I2C1_IRQ => InterruptHandler<I2C1>;
});
#[allow(dead_code)] #[allow(dead_code)]
mod mcp23017 { mod mcp23017 {
pub const ADDR: u8 = 0x20; // default addr pub const ADDR: u8 = 0x20; // default addr
@ -64,10 +69,9 @@ async fn main(_spawner: Spawner) {
let sda = p.PIN_14; let sda = p.PIN_14;
let scl = p.PIN_15; let scl = p.PIN_15;
let irq = interrupt::take!(I2C1_IRQ);
info!("set up i2c "); info!("set up i2c ");
let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, irq, Config::default()); let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, Config::default());
use mcp23017::*; use mcp23017::*;

View file

@ -5,13 +5,17 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_executor::_export::StaticCell; use embassy_executor::_export::StaticCell;
use embassy_rp::interrupt; use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::UART0; use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config}; use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use embedded_io::asynch::{Read, Write}; use embedded_io::asynch::{Read, Write};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UART0_IRQ => BufferedInterruptHandler<UART0>;
});
macro_rules! singleton { macro_rules! singleton {
($val:expr) => {{ ($val:expr) => {{
type T = impl Sized; type T = impl Sized;
@ -26,10 +30,9 @@ async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0);
let irq = interrupt::take!(UART0_IRQ);
let tx_buf = &mut singleton!([0u8; 16])[..]; let tx_buf = &mut singleton!([0u8; 16])[..];
let rx_buf = &mut singleton!([0u8; 16])[..]; let rx_buf = &mut singleton!([0u8; 16])[..];
let uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default());
let (rx, mut tx) = uart.split(); let (rx, mut tx) = uart.split();
unwrap!(spawner.spawn(reader(rx))); unwrap!(spawner.spawn(reader(rx)));

View file

@ -7,24 +7,22 @@
use defmt::*; use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::interrupt; use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::UART1; use embassy_rp::peripherals::UART1;
use embassy_rp::uart::{Async, Config, UartRx, UartTx}; use embassy_rp::uart::{Async, Config, InterruptHandler, UartRx, UartTx};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UART1_IRQ => InterruptHandler<UART1>;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
let uart_rx = UartRx::new( let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default());
p.UART1,
p.PIN_5,
interrupt::take!(UART1_IRQ),
p.DMA_CH1,
Config::default(),
);
unwrap!(spawner.spawn(reader(uart_rx))); unwrap!(spawner.spawn(reader(uart_rx)));

View file

@ -6,8 +6,9 @@ use defmt::*;
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket; use embassy_net::tcp::TcpSocket;
use embassy_net::{Stack, StackResources}; use embassy_net::{Stack, StackResources};
use embassy_rp::usb::Driver; use embassy_rp::peripherals::USB;
use embassy_rp::{interrupt, peripherals}; use embassy_rp::usb::{Driver, InterruptHandler};
use embassy_rp::{bind_interrupts, peripherals};
use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
use embassy_usb::{Builder, Config, UsbDevice}; use embassy_usb::{Builder, Config, UsbDevice};
@ -15,6 +16,10 @@ use embedded_io::asynch::Write;
use static_cell::StaticCell; use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
USBCTRL_IRQ => InterruptHandler<USB>;
});
type MyDriver = Driver<'static, peripherals::USB>; type MyDriver = Driver<'static, peripherals::USB>;
macro_rules! singleton { macro_rules! singleton {
@ -48,8 +53,7 @@ async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
// Create the driver, from the HAL. // Create the driver, from the HAL.
let irq = interrupt::take!(USBCTRL_IRQ); let driver = Driver::new(p.USB, Irqs);
let driver = Driver::new(p.USB, irq);
// Create embassy-usb Config // Create embassy-usb Config
let mut config = Config::new(0xc0de, 0xcafe); let mut config = Config::new(0xc0de, 0xcafe);

View file

@ -3,12 +3,16 @@
#![feature(type_alias_impl_trait)] #![feature(type_alias_impl_trait)]
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::interrupt; use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::USB; use embassy_rp::peripherals::USB;
use embassy_rp::usb::Driver; use embassy_rp::usb::{Driver, InterruptHandler};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
USBCTRL_IRQ => InterruptHandler<USB>;
});
#[embassy_executor::task] #[embassy_executor::task]
async fn logger_task(driver: Driver<'static, USB>) { async fn logger_task(driver: Driver<'static, USB>) {
embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver);
@ -17,8 +21,7 @@ async fn logger_task(driver: Driver<'static, USB>) {
#[embassy_executor::main] #[embassy_executor::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
let irq = interrupt::take!(USBCTRL_IRQ); let driver = Driver::new(p.USB, Irqs);
let driver = Driver::new(p.USB, irq);
spawner.spawn(logger_task(driver)).unwrap(); spawner.spawn(logger_task(driver)).unwrap();
let mut counter = 0; let mut counter = 0;

View file

@ -5,13 +5,18 @@
use defmt::{info, panic}; use defmt::{info, panic};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_futures::join::join; use embassy_futures::join::join;
use embassy_rp::interrupt; use embassy_rp::bind_interrupts;
use embassy_rp::usb::{Driver, Instance}; use embassy_rp::peripherals::USB;
use embassy_rp::usb::{Driver, Instance, InterruptHandler};
use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
use embassy_usb::driver::EndpointError; use embassy_usb::driver::EndpointError;
use embassy_usb::{Builder, Config}; use embassy_usb::{Builder, Config};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
USBCTRL_IRQ => InterruptHandler<USB>;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
info!("Hello there!"); info!("Hello there!");
@ -19,8 +24,7 @@ async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
// Create the driver, from the HAL. // Create the driver, from the HAL.
let irq = interrupt::take!(USBCTRL_IRQ); let driver = Driver::new(p.USB, Irqs);
let driver = Driver::new(p.USB, irq);
// Create embassy-usb Config // Create embassy-usb Config
let mut config = Config::new(0xc0de, 0xcafe); let mut config = Config::new(0xc0de, 0xcafe);

View file

@ -4,13 +4,18 @@
use defmt::{assert_eq, panic, *}; use defmt::{assert_eq, panic, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output}; use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt; use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config, Error, Instance, Parity}; use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use embedded_io::asynch::{Read, ReadExactError, Write}; use embedded_io::asynch::{Read, ReadExactError, Write};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UART0_IRQ => BufferedInterruptHandler<UART0>;
});
async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> { async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
let mut buf = [255; N]; let mut buf = [255; N];
match uart.read_exact(&mut buf).await { match uart.read_exact(&mut buf).await {
@ -60,13 +65,12 @@ async fn main(_spawner: Spawner) {
info!("Hello World!"); info!("Hello World!");
let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
let mut irq = interrupt::take!(UART0_IRQ);
{ {
let config = Config::default(); let config = Config::default();
let tx_buf = &mut [0u8; 16]; let tx_buf = &mut [0u8; 16];
let rx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16];
let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
// Make sure we send more bytes than fits in the FIFO, to test the actual // Make sure we send more bytes than fits in the FIFO, to test the actual
// bufferedUart. // bufferedUart.
@ -86,7 +90,7 @@ async fn main(_spawner: Spawner) {
let config = Config::default(); let config = Config::default();
let tx_buf = &mut [0u8; 16]; let tx_buf = &mut [0u8; 16];
let rx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16];
let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
// Make sure we send more bytes than fits in the FIFO, to test the actual // Make sure we send more bytes than fits in the FIFO, to test the actual
// bufferedUart. // bufferedUart.
@ -121,7 +125,7 @@ async fn main(_spawner: Spawner) {
config.baudrate = 1000; config.baudrate = 1000;
let tx_buf = &mut [0u8; 16]; let tx_buf = &mut [0u8; 16];
let rx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16];
let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
// break on empty buffer // break on empty buffer
uart.send_break(20).await; uart.send_break(20).await;
@ -155,7 +159,7 @@ async fn main(_spawner: Spawner) {
config.baudrate = 1000; config.baudrate = 1000;
config.parity = Parity::ParityEven; config.parity = Parity::ParityEven;
let rx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16];
let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config); let mut uart = BufferedUartRx::new(&mut uart, Irqs, &mut rx, rx_buf, config);
async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) { async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
send(pin, v, Some(parity != 0)).await; send(pin, v, Some(parity != 0)).await;
@ -202,7 +206,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.baudrate = 1000; config.baudrate = 1000;
let rx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16];
let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config); let mut uart = BufferedUartRx::new(&mut uart, Irqs, &mut rx, rx_buf, config);
async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
if good { if good {

View file

@ -4,12 +4,17 @@
use defmt::{assert_eq, *}; use defmt::{assert_eq, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output}; use embassy_rp::gpio::{Level, Output};
use embassy_rp::interrupt; use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{Async, Config, Error, Instance, Parity, Uart, UartRx}; use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UART0_IRQ => InterruptHandler<UART0>;
});
async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> { async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
let mut buf = [255; N]; let mut buf = [255; N];
uart.read(&mut buf).await?; uart.read(&mut buf).await?;
@ -51,7 +56,6 @@ async fn main(_spawner: Spawner) {
info!("Hello World!"); info!("Hello World!");
let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
let mut irq = interrupt::take!(UART0_IRQ);
// We can't send too many bytes, they have to fit in the FIFO. // We can't send too many bytes, they have to fit in the FIFO.
// This is because we aren't sending+receiving at the same time. // This is because we aren't sending+receiving at the same time.
@ -61,7 +65,7 @@ async fn main(_spawner: Spawner) {
&mut uart, &mut uart,
&mut tx, &mut tx,
&mut rx, &mut rx,
&mut irq, Irqs,
&mut p.DMA_CH0, &mut p.DMA_CH0,
&mut p.DMA_CH1, &mut p.DMA_CH1,
config, config,
@ -82,7 +86,7 @@ async fn main(_spawner: Spawner) {
&mut uart, &mut uart,
&mut tx, &mut tx,
&mut rx, &mut rx,
&mut irq, Irqs,
&mut p.DMA_CH0, &mut p.DMA_CH0,
&mut p.DMA_CH1, &mut p.DMA_CH1,
config, config,
@ -111,7 +115,7 @@ async fn main(_spawner: Spawner) {
&mut uart, &mut uart,
&mut tx, &mut tx,
&mut rx, &mut rx,
&mut irq, Irqs,
&mut p.DMA_CH0, &mut p.DMA_CH0,
&mut p.DMA_CH1, &mut p.DMA_CH1,
config, config,
@ -154,7 +158,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default(); let mut config = Config::default();
config.baudrate = 1000; config.baudrate = 1000;
config.parity = Parity::ParityEven; config.parity = Parity::ParityEven;
let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config); let mut uart = UartRx::new(&mut uart, &mut rx, Irqs, &mut p.DMA_CH0, config);
async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) { async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
send(pin, v, Some(parity != 0)).await; send(pin, v, Some(parity != 0)).await;
@ -199,7 +203,7 @@ async fn main(_spawner: Spawner) {
// choose a very slow baud rate to make tests reliable even with O0 // choose a very slow baud rate to make tests reliable even with O0
let mut config = Config::default(); let mut config = Config::default();
config.baudrate = 1000; config.baudrate = 1000;
let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config); let mut uart = UartRx::new(&mut uart, &mut rx, Irqs, &mut p.DMA_CH0, config);
async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
if good { if good {

View file

@ -4,11 +4,16 @@
use defmt::{assert_eq, *}; use defmt::{assert_eq, *};
use embassy_executor::Spawner; use embassy_executor::Spawner;
use embassy_rp::interrupt; use embassy_rp::bind_interrupts;
use embassy_rp::uart::{Config, Uart}; use embassy_rp::peripherals::UART0;
use embassy_rp::uart::{BufferedInterruptHandler, Config, Uart};
use embedded_io::asynch::{Read, Write}; use embedded_io::asynch::{Read, Write};
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
bind_interrupts!(struct Irqs {
UART0_IRQ => BufferedInterruptHandler<UART0>;
});
#[embassy_executor::main] #[embassy_executor::main]
async fn main(_spawner: Spawner) { async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default()); let p = embassy_rp::init(Default::default());
@ -29,11 +34,10 @@ async fn main(_spawner: Spawner) {
uart.blocking_read(&mut buf).unwrap(); uart.blocking_read(&mut buf).unwrap();
assert_eq!(buf, data); assert_eq!(buf, data);
let irq = interrupt::take!(UART0_IRQ);
let tx_buf = &mut [0u8; 16]; let tx_buf = &mut [0u8; 16];
let rx_buf = &mut [0u8; 16]; let rx_buf = &mut [0u8; 16];
let mut uart = uart.into_buffered(irq, tx_buf, rx_buf); let mut uart = uart.into_buffered(Irqs, tx_buf, rx_buf);
// Make sure we send more bytes than fits in the FIFO, to test the actual // Make sure we send more bytes than fits in the FIFO, to test the actual
// bufferedUart. // bufferedUart.