diff --git a/embassy-rp/src/adc.rs b/embassy-rp/src/adc.rs
index 145ba9c59..59c7a47ce 100644
--- a/embassy-rp/src/adc.rs
+++ b/embassy-rp/src/adc.rs
@@ -3,12 +3,12 @@ use core::marker::PhantomData;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
-use embassy_hal_common::into_ref;
+use embassy_cortex_m::interrupt::{Binding, Interrupt};
use embassy_sync::waitqueue::AtomicWaker;
use embedded_hal_02::adc::{Channel, OneShot};
use crate::gpio::Pin;
-use crate::interrupt::{self, InterruptExt};
+use crate::interrupt::{self, InterruptExt, ADC_IRQ_FIFO};
use crate::peripherals::ADC;
use crate::{pac, peripherals, Peripheral};
static WAKER: AtomicWaker = AtomicWaker::new();
@@ -47,10 +47,9 @@ impl<'d> Adc<'d> {
pub fn new(
_inner: impl Peripheral
+ 'd,
- irq: impl Peripheral
+ 'd,
+ _irq: impl Binding,
_config: Config,
) -> Self {
- into_ref!(irq);
unsafe {
let reset = Self::reset();
crate::reset::reset(reset);
@@ -63,14 +62,10 @@ impl<'d> Adc<'d> {
}
// Setup IRQ
- irq.disable();
- irq.set_handler(|_| unsafe {
- let r = Self::regs();
- r.inte().write(|w| w.set_fifo(false));
- WAKER.wake();
- });
- irq.unpend();
- irq.enable();
+ unsafe {
+ ADC_IRQ_FIFO::steal().unpend();
+ ADC_IRQ_FIFO::steal().enable();
+ };
Self { phantom: PhantomData }
}
@@ -165,6 +160,18 @@ macro_rules! impl_pin {
};
}
+pub struct InterruptHandler {
+ _empty: (),
+}
+
+impl interrupt::Handler 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_27, 1);
impl_pin!(PIN_28, 2);
diff --git a/embassy-rp/src/i2c.rs b/embassy-rp/src/i2c.rs
index d5dc94406..6ce77f073 100644
--- a/embassy-rp/src/i2c.rs
+++ b/embassy-rp/src/i2c.rs
@@ -2,7 +2,7 @@ use core::future;
use core::marker::PhantomData;
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_sync::waitqueue::AtomicWaker;
use pac::i2c;
@@ -75,23 +75,21 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
peri: impl Peripheral + 'd,
scl: impl Peripheral
> + 'd,
sda: impl Peripheral
> + 'd,
- irq: impl Peripheral
+ 'd,
+ _irq: impl Binding>,
config: Config,
) -> Self {
- into_ref!(scl, sda, irq);
+ into_ref!(scl, sda);
let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config);
- irq.set_handler(Self::on_interrupt);
unsafe {
let i2c = T::regs();
// mask everything initially
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
}
@@ -115,14 +113,6 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
.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> {
if buffer.is_empty() {
return Err(Error::InvalidReadBufferLength);
@@ -320,6 +310,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
}
}
+pub struct InterruptHandler {
+ _uart: PhantomData,
+}
+
+impl interrupt::Handler for InterruptHandler {
+ // 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> {
fn new_inner(
_peri: impl Peripheral + 'd,
diff --git a/embassy-rp/src/interrupt.rs b/embassy-rp/src/interrupt.rs
index 989f5dc2d..1db13deef 100644
--- a/embassy-rp/src/interrupt.rs
+++ b/embassy-rp/src/interrupt.rs
@@ -1,11 +1,7 @@
-//! Interrupt management
-//!
-//! This module implements an API for managing interrupts compatible with
-//! nrf_softdevice::interrupt. Intended for switching between the two at compile-time.
-
-// Re-exports
+//! Interrupt definitions and macros to bind them.
+pub use cortex_m::interrupt::{CriticalSection, Mutex};
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;
declare!(TIMER_IRQ_0);
@@ -40,3 +36,30 @@ declare!(SWI_IRQ_2);
declare!(SWI_IRQ_3);
declare!(SWI_IRQ_4);
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 {}
+ )*
+ )*
+ };
+}
diff --git a/embassy-rp/src/uart/buffered.rs b/embassy-rp/src/uart/buffered.rs
index 9d3de1bd8..12d6b8d91 100644
--- a/embassy-rp/src/uart/buffered.rs
+++ b/embassy-rp/src/uart/buffered.rs
@@ -3,7 +3,7 @@ use core::slice;
use core::task::Poll;
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_sync::waitqueue::AtomicWaker;
use embassy_time::{Duration, Timer};
@@ -52,7 +52,7 @@ pub struct BufferedUartTx<'d, T: Instance> {
}
pub(crate) fn init_buffers<'d, T: Instance + 'd>(
- irq: PeripheralRef<'d, T::Interrupt>,
+ _irq: impl Binding>,
tx_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_txim(true);
});
- };
- irq.set_handler(on_interrupt::);
- irq.unpend();
- irq.enable();
+ T::Interrupt::steal().unpend();
+ T::Interrupt::steal().enable();
+ };
}
impl<'d, T: Instance> BufferedUart<'d, T> {
pub fn new(
_uart: impl Peripheral + 'd,
- irq: impl Peripheral
+ 'd,
+ irq: impl Binding>,
tx: impl Peripheral> + 'd,
rx: impl Peripheral
> + 'd,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
config: Config,
) -> 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);
init_buffers::(irq, tx_buffer, rx_buffer);
@@ -109,7 +108,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
pub fn new_with_rtscts(
_uart: impl Peripheral + 'd,
- irq: impl Peripheral
+ 'd,
+ irq: impl Binding>,
tx: impl Peripheral> + 'd,
rx: impl Peripheral
> + 'd,
rts: impl Peripheral
> + 'd,
@@ -118,7 +117,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
- into_ref!(irq, tx, rx, cts, rts);
+ into_ref!(tx, rx, cts, rts);
super::Uart::<'d, T, Async>::init(
Some(tx.map_into()),
@@ -163,12 +162,12 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
impl<'d, T: Instance> BufferedUartRx<'d, T> {
pub fn new(
_uart: impl Peripheral
+ 'd,
- irq: impl Peripheral
+ 'd,
+ irq: impl Binding>,
rx: impl Peripheral> + 'd,
rx_buffer: &'d mut [u8],
config: Config,
) -> Self {
- into_ref!(irq, rx);
+ into_ref!(rx);
super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config);
init_buffers::(irq, &mut [], rx_buffer);
@@ -178,13 +177,13 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
pub fn new_with_rts(
_uart: impl Peripheral + 'd,
- irq: impl Peripheral
+ 'd,
+ irq: impl Binding>,
rx: impl Peripheral> + 'd,
rts: impl Peripheral
> + 'd,
rx_buffer: &'d mut [u8],
config: Config,
) -> 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);
init_buffers::(irq, &mut [], rx_buffer);
@@ -312,12 +311,12 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
impl<'d, T: Instance> BufferedUartTx<'d, T> {
pub fn new(
_uart: impl Peripheral + 'd,
- irq: impl Peripheral
+ 'd,
+ irq: impl Binding>,
tx: impl Peripheral> + 'd,
tx_buffer: &'d mut [u8],
config: Config,
) -> Self {
- into_ref!(irq, tx);
+ into_ref!(tx);
super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config);
init_buffers::(irq, tx_buffer, &mut []);
@@ -327,13 +326,13 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
pub fn new_with_cts(
_uart: impl Peripheral + 'd,
- irq: impl Peripheral
+ 'd,
+ irq: impl Binding>,
tx: impl Peripheral> + 'd,
cts: impl Peripheral
> + 'd,
tx_buffer: &'d mut [u8],
config: Config,
) -> 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);
init_buffers::(irq, tx_buffer, &mut []);
@@ -482,97 +481,107 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
}
}
-pub(crate) unsafe fn on_interrupt(_: *mut ()) {
- let r = T::regs();
- let s = T::buffered_state();
+pub struct BufferedInterruptHandler {
+ _uart: PhantomData,
+}
- unsafe {
- // Clear TX and error interrupt flags
- // RX interrupt flags are cleared by reading from the FIFO.
- let ris = r.uartris().read();
- r.uarticr().write(|w| {
- w.set_txic(ris.txris());
- w.set_feic(ris.feris());
- w.set_peic(ris.peris());
- w.set_beic(ris.beris());
- w.set_oeic(ris.oeris());
- });
-
- trace!("on_interrupt ris={:#X}", ris.0);
-
- // Errors
- if ris.feris() {
- warn!("Framing error");
- }
- if ris.peris() {
- warn!("Parity error");
- }
- if ris.beris() {
- warn!("Break error");
- }
- if ris.oeris() {
- warn!("Overrun error");
+impl interrupt::Handler for BufferedInterruptHandler {
+ unsafe fn on_interrupt() {
+ let r = T::regs();
+ if r.uartdmacr().read().rxdmae() {
+ return;
}
- // RX
- let mut rx_writer = s.rx_buf.writer();
- let rx_buf = rx_writer.push_slice();
- let mut n_read = 0;
- let mut error = false;
- for rx_byte in rx_buf {
- if r.uartfr().read().rxfe() {
- break;
- }
- let dr = r.uartdr().read();
- if (dr.0 >> 8) != 0 {
- s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed);
- error = true;
- // only fill the buffer with valid characters. the current character is fine
- // if the error is an overrun, but if we add it to the buffer we'll report
- // the overrun one character too late. drop it instead and pretend we were
- // a bit slower at draining the rx fifo than we actually were.
- // this is consistent with blocking uart error reporting.
- break;
- }
- *rx_byte = dr.data();
- n_read += 1;
- }
- if n_read > 0 {
- rx_writer.push_done(n_read);
- s.rx_waker.wake();
- } else if error {
- s.rx_waker.wake();
- }
- // Disable any further RX interrupts when the buffer becomes full or
- // errors have occurred. This lets us buffer additional errors in the
- // fifo without needing more error storage locations, and most applications
- // will want to do a full reset of their uart state anyway once an error
- // has happened.
- if s.rx_buf.is_full() || error {
- r.uartimsc().write_clear(|w| {
- w.set_rxim(true);
- w.set_rtim(true);
+ let s = T::buffered_state();
+
+ unsafe {
+ // Clear TX and error interrupt flags
+ // RX interrupt flags are cleared by reading from the FIFO.
+ let ris = r.uartris().read();
+ r.uarticr().write(|w| {
+ w.set_txic(ris.txris());
+ w.set_feic(ris.feris());
+ w.set_peic(ris.peris());
+ w.set_beic(ris.beris());
+ w.set_oeic(ris.oeris());
});
- }
- // TX
- let mut tx_reader = s.tx_buf.reader();
- let tx_buf = tx_reader.pop_slice();
- let mut n_written = 0;
- for tx_byte in tx_buf.iter_mut() {
- if r.uartfr().read().txff() {
- break;
+ trace!("on_interrupt ris={:#X}", ris.0);
+
+ // Errors
+ if ris.feris() {
+ warn!("Framing error");
}
- r.uartdr().write(|w| w.set_data(*tx_byte));
- n_written += 1;
+ if ris.peris() {
+ warn!("Parity error");
+ }
+ if ris.beris() {
+ warn!("Break error");
+ }
+ if ris.oeris() {
+ warn!("Overrun error");
+ }
+
+ // RX
+ let mut rx_writer = s.rx_buf.writer();
+ let rx_buf = rx_writer.push_slice();
+ let mut n_read = 0;
+ let mut error = false;
+ for rx_byte in rx_buf {
+ if r.uartfr().read().rxfe() {
+ break;
+ }
+ let dr = r.uartdr().read();
+ if (dr.0 >> 8) != 0 {
+ s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed);
+ error = true;
+ // only fill the buffer with valid characters. the current character is fine
+ // if the error is an overrun, but if we add it to the buffer we'll report
+ // the overrun one character too late. drop it instead and pretend we were
+ // a bit slower at draining the rx fifo than we actually were.
+ // this is consistent with blocking uart error reporting.
+ break;
+ }
+ *rx_byte = dr.data();
+ n_read += 1;
+ }
+ if n_read > 0 {
+ rx_writer.push_done(n_read);
+ s.rx_waker.wake();
+ } else if error {
+ s.rx_waker.wake();
+ }
+ // Disable any further RX interrupts when the buffer becomes full or
+ // errors have occurred. This lets us buffer additional errors in the
+ // fifo without needing more error storage locations, and most applications
+ // will want to do a full reset of their uart state anyway once an error
+ // has happened.
+ if s.rx_buf.is_full() || error {
+ r.uartimsc().write_clear(|w| {
+ w.set_rxim(true);
+ w.set_rtim(true);
+ });
+ }
+
+ // TX
+ let mut tx_reader = s.tx_buf.reader();
+ let tx_buf = tx_reader.pop_slice();
+ let mut n_written = 0;
+ for tx_byte in tx_buf.iter_mut() {
+ if r.uartfr().read().txff() {
+ break;
+ }
+ r.uartdr().write(|w| w.set_data(*tx_byte));
+ n_written += 1;
+ }
+ if n_written > 0 {
+ tx_reader.pop_done(n_written);
+ s.tx_waker.wake();
+ }
+ // The TX interrupt only triggers once when the FIFO threshold is
+ // crossed. No need to disable it when the buffer becomes empty
+ // as it does re-trigger anymore once we have cleared it.
}
- if n_written > 0 {
- tx_reader.pop_done(n_written);
- s.tx_waker.wake();
- }
- // The TX interrupt only triggers once when the FIFO threshold is
- // crossed. No need to disable it when the buffer becomes empty
- // as it does re-trigger anymore once we have cleared it.
}
}
diff --git a/embassy-rp/src/uart/mod.rs b/embassy-rp/src/uart/mod.rs
index a0ee6b4ce..7234336b4 100644
--- a/embassy-rp/src/uart/mod.rs
+++ b/embassy-rp/src/uart/mod.rs
@@ -3,7 +3,7 @@ use core::marker::PhantomData;
use core::task::Poll;
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_hal_common::{into_ref, PeripheralRef};
use embassy_sync::waitqueue::AtomicWaker;
@@ -20,7 +20,7 @@ use crate::{pac, peripherals, Peripheral, RegExt};
#[cfg(feature = "nightly")]
mod buffered;
#[cfg(feature = "nightly")]
-pub use buffered::{BufferedUart, BufferedUartRx, BufferedUartTx};
+pub use buffered::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx};
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub enum DataBits {
@@ -203,11 +203,9 @@ impl<'d, T: Instance> UartTx<'d, T, Blocking> {
#[cfg(feature = "nightly")]
pub fn into_buffered(
self,
- irq: impl Peripheral + 'd,
+ irq: impl Binding>,
tx_buffer: &'d mut [u8],
) -> BufferedUartTx<'d, T> {
- into_ref!(irq);
-
buffered::init_buffers::(irq, tx_buffer, &mut []);
BufferedUartTx { phantom: PhantomData }
@@ -235,25 +233,24 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
pub fn new(
_uart: impl Peripheral + 'd,
rx: impl Peripheral
> + 'd,
- irq: impl Peripheral
+ 'd,
+ _irq: impl Binding>,
rx_dma: impl Peripheral + 'd,
config: Config,
) -> Self {
- into_ref!(rx, irq, rx_dma);
+ into_ref!(rx, rx_dma);
Uart::::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>, rx_dma: Option>) -> Self {
- debug_assert_eq!(irq.is_some(), rx_dma.is_some());
- if let Some(irq) = irq {
+ fn new_inner(has_irq: bool, rx_dma: Option>) -> Self {
+ debug_assert_eq!(has_irq, rx_dma.is_some());
+ if has_irq {
unsafe {
// disable all error interrupts initially
T::regs().uartimsc().write(|w| w.0 = 0);
+ T::Interrupt::steal().unpend();
+ T::Interrupt::steal().enable();
}
- irq.set_handler(on_interrupt::);
- irq.unpend();
- irq.enable();
}
Self {
rx_dma,
@@ -299,6 +296,12 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
if let Some(_) = self.rx_dma {
unsafe {
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,33 +315,41 @@ impl<'d, T: Instance> UartRx<'d, T, Blocking> {
) -> Self {
into_ref!(rx);
Uart::::init(None, Some(rx.map_into()), None, None, config);
- Self::new_inner(None, None)
+ Self::new_inner(false, None)
}
#[cfg(feature = "nightly")]
pub fn into_buffered(
self,
- irq: impl Peripheral + 'd,
+ irq: impl Binding>,
rx_buffer: &'d mut [u8],
) -> BufferedUartRx<'d, T> {
- into_ref!(irq);
-
buffered::init_buffers::(irq, &mut [], rx_buffer);
BufferedUartRx { phantom: PhantomData }
}
}
-unsafe fn on_interrupt(_: *mut ()) {
- let uart = T::regs();
- let state = T::dma_state();
- let errs = uart.uartris().read();
- state.rx_errs.store(errs.0 as u16, Ordering::Relaxed);
- state.rx_err_waker.wake();
- // disable the error interrupts instead of clearing the flags. clearing the
- // flags would allow the dma transfer to continue, potentially signaling
- // completion before we can check for errors that happened *during* the transfer.
- uart.uartimsc().write_clear(|w| w.0 = errs.0);
+pub struct InterruptHandler {
+ _uart: PhantomData,
+}
+
+impl interrupt::Handler for InterruptHandler {
+ unsafe fn on_interrupt() {
+ let uart = T::regs();
+ if !uart.uartdmacr().read().rxdmae() {
+ return;
+ }
+
+ let state = T::dma_state();
+ let errs = uart.uartris().read();
+ state.rx_errs.store(errs.0 as u16, Ordering::Relaxed);
+ state.rx_err_waker.wake();
+ // disable the error interrupts instead of clearing the flags. clearing the
+ // flags would allow the dma transfer to continue, potentially signaling
+ // completion before we can check for errors that happened *during* the transfer.
+ uart.uartimsc().write_clear(|w| w.0 = errs.0);
+ }
}
impl<'d, T: Instance> UartRx<'d, T, Async> {
@@ -428,7 +439,17 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
config: Config,
) -> Self {
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)
@@ -447,7 +468,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
rx.map_into(),
Some(rts.map_into()),
Some(cts.map_into()),
- None,
+ false,
None,
None,
config,
@@ -457,12 +478,10 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
#[cfg(feature = "nightly")]
pub fn into_buffered(
self,
- irq: impl Peripheral + 'd,
+ irq: impl Binding>,
tx_buffer: &'d mut [u8],
rx_buffer: &'d mut [u8],
) -> BufferedUart<'d, T> {
- into_ref!(irq);
-
buffered::init_buffers::(irq, tx_buffer, rx_buffer);
BufferedUart {
@@ -478,19 +497,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
uart: impl Peripheral + 'd,
tx: impl Peripheral
> + 'd,
rx: impl Peripheral
> + 'd,
- irq: impl Peripheral
+ 'd,
+ _irq: impl Binding>,
tx_dma: impl Peripheral + 'd,
rx_dma: impl Peripheral
+ 'd,
config: Config,
) -> Self {
- into_ref!(tx, rx, irq, tx_dma, rx_dma);
+ into_ref!(tx, rx, tx_dma, rx_dma);
Self::new_inner(
uart,
tx.map_into(),
rx.map_into(),
None,
None,
- Some(irq),
+ true,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
config,
@@ -504,19 +523,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
rx: impl Peripheral
> + 'd,
rts: impl Peripheral
> + 'd,
cts: impl Peripheral
> + 'd,
- irq: impl Peripheral
+ 'd,
+ _irq: impl Binding>,
tx_dma: impl Peripheral + 'd,
rx_dma: impl Peripheral
+ 'd,
config: Config,
) -> 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(
uart,
tx.map_into(),
rx.map_into(),
Some(rts.map_into()),
Some(cts.map_into()),
- Some(irq),
+ true,
Some(tx_dma.map_into()),
Some(rx_dma.map_into()),
config,
@@ -531,7 +550,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
mut rx: PeripheralRef<'d, AnyPin>,
mut rts: Option>,
mut cts: Option>,
- irq: Option>,
+ has_irq: bool,
tx_dma: Option>,
rx_dma: Option>,
config: Config,
@@ -546,7 +565,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
Self {
tx: UartTx::new_inner(tx_dma),
- rx: UartRx::new_inner(irq, rx_dma),
+ rx: UartRx::new_inner(has_irq, rx_dma),
}
}
diff --git a/embassy-rp/src/usb.rs b/embassy-rp/src/usb.rs
index a049e4769..fada2790f 100644
--- a/embassy-rp/src/usb.rs
+++ b/embassy-rp/src/usb.rs
@@ -4,7 +4,7 @@ use core::slice;
use core::sync::atomic::{compiler_fence, Ordering};
use core::task::Poll;
-use embassy_hal_common::into_ref;
+use embassy_cortex_m::interrupt::{self, Binding};
use embassy_sync::waitqueue::AtomicWaker;
use embassy_usb_driver as driver;
use embassy_usb_driver::{
@@ -105,11 +105,11 @@ pub struct Driver<'d, T: Instance> {
}
impl<'d, T: Instance> Driver<'d, T> {
- pub fn new(_usb: impl Peripheral + 'd, irq: impl Peripheral
+ 'd) -> Self {
- into_ref!(irq);
- irq.set_handler(Self::on_interrupt);
- irq.unpend();
- irq.enable();
+ pub fn new(_usb: impl Peripheral
+ 'd, _irq: impl Binding>) -> Self {
+ unsafe {
+ T::Interrupt::steal().unpend();
+ T::Interrupt::steal().enable();
+ }
let regs = T::regs();
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(
&mut self,
ep_type: EndpointType,
@@ -288,6 +247,51 @@ impl<'d, T: Instance> Driver<'d, T> {
}
}
+pub struct InterruptHandler {
+ _uart: PhantomData,
+}
+
+impl interrupt::Handler for InterruptHandler {
+ 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> {
type EndpointOut = Endpoint<'d, T, Out>;
type EndpointIn = Endpoint<'d, T, In>;
diff --git a/examples/rp/src/bin/adc.rs b/examples/rp/src/bin/adc.rs
index 4202fd394..7c2ca19f7 100644
--- a/examples/rp/src/bin/adc.rs
+++ b/examples/rp/src/bin/adc.rs
@@ -4,16 +4,19 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_rp::adc::{Adc, Config};
-use embassy_rp::interrupt;
+use embassy_rp::adc::{Adc, Config, InterruptHandler};
+use embassy_rp::bind_interrupts;
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ ADC_IRQ_FIFO => InterruptHandler;
+});
+
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
- let irq = interrupt::take!(ADC_IRQ_FIFO);
- let mut adc = Adc::new(p.ADC, irq, Config::default());
+ let mut adc = Adc::new(p.ADC, Irqs, Config::default());
let mut p26 = p.PIN_26;
let mut p27 = p.PIN_27;
diff --git a/examples/rp/src/bin/i2c_async.rs b/examples/rp/src/bin/i2c_async.rs
index d1a2e3cd7..cf3cf742c 100644
--- a/examples/rp/src/bin/i2c_async.rs
+++ b/examples/rp/src/bin/i2c_async.rs
@@ -4,12 +4,17 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_rp::i2c::{self, Config};
-use embassy_rp::interrupt;
+use embassy_rp::bind_interrupts;
+use embassy_rp::i2c::{self, Config, InterruptHandler};
+use embassy_rp::peripherals::I2C1;
use embassy_time::{Duration, Timer};
use embedded_hal_async::i2c::I2c;
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ I2C1_IRQ => InterruptHandler;
+});
+
#[allow(dead_code)]
mod mcp23017 {
pub const ADDR: u8 = 0x20; // default addr
@@ -64,10 +69,9 @@ async fn main(_spawner: Spawner) {
let sda = p.PIN_14;
let scl = p.PIN_15;
- let irq = interrupt::take!(I2C1_IRQ);
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::*;
diff --git a/examples/rp/src/bin/uart_buffered_split.rs b/examples/rp/src/bin/uart_buffered_split.rs
index a8a682274..d6f01b4de 100644
--- a/examples/rp/src/bin/uart_buffered_split.rs
+++ b/examples/rp/src/bin/uart_buffered_split.rs
@@ -5,13 +5,17 @@
use defmt::*;
use embassy_executor::Spawner;
use embassy_executor::_export::StaticCell;
-use embassy_rp::interrupt;
+use embassy_rp::bind_interrupts;
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 embedded_io::asynch::{Read, Write};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ UART0_IRQ => BufferedInterruptHandler;
+});
+
macro_rules! singleton {
($val:expr) => {{
type T = impl Sized;
@@ -26,10 +30,9 @@ async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
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 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();
unwrap!(spawner.spawn(reader(rx)));
diff --git a/examples/rp/src/bin/uart_unidir.rs b/examples/rp/src/bin/uart_unidir.rs
index 4119a309f..c0943a1b8 100644
--- a/examples/rp/src/bin/uart_unidir.rs
+++ b/examples/rp/src/bin/uart_unidir.rs
@@ -7,24 +7,22 @@
use defmt::*;
use embassy_executor::Spawner;
-use embassy_rp::interrupt;
+use embassy_rp::bind_interrupts;
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 {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ UART1_IRQ => InterruptHandler;
+});
+
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
- let uart_rx = UartRx::new(
- p.UART1,
- p.PIN_5,
- interrupt::take!(UART1_IRQ),
- p.DMA_CH1,
- Config::default(),
- );
+ let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default());
unwrap!(spawner.spawn(reader(uart_rx)));
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 66a6ed4d0..2ddfb6344 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -6,8 +6,9 @@ use defmt::*;
use embassy_executor::Spawner;
use embassy_net::tcp::TcpSocket;
use embassy_net::{Stack, StackResources};
-use embassy_rp::usb::Driver;
-use embassy_rp::{interrupt, peripherals};
+use embassy_rp::peripherals::USB;
+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::{CdcNcmClass, State};
use embassy_usb::{Builder, Config, UsbDevice};
@@ -15,6 +16,10 @@ use embedded_io::asynch::Write;
use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ USBCTRL_IRQ => InterruptHandler;
+});
+
type MyDriver = Driver<'static, peripherals::USB>;
macro_rules! singleton {
@@ -48,8 +53,7 @@ async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
// Create the driver, from the HAL.
- let irq = interrupt::take!(USBCTRL_IRQ);
- let driver = Driver::new(p.USB, irq);
+ let driver = Driver::new(p.USB, Irqs);
// Create embassy-usb Config
let mut config = Config::new(0xc0de, 0xcafe);
diff --git a/examples/rp/src/bin/usb_logger.rs b/examples/rp/src/bin/usb_logger.rs
index 52417a02e..7c90d0ca3 100644
--- a/examples/rp/src/bin/usb_logger.rs
+++ b/examples/rp/src/bin/usb_logger.rs
@@ -3,12 +3,16 @@
#![feature(type_alias_impl_trait)]
use embassy_executor::Spawner;
-use embassy_rp::interrupt;
+use embassy_rp::bind_interrupts;
use embassy_rp::peripherals::USB;
-use embassy_rp::usb::Driver;
+use embassy_rp::usb::{Driver, InterruptHandler};
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ USBCTRL_IRQ => InterruptHandler;
+});
+
#[embassy_executor::task]
async fn logger_task(driver: Driver<'static, USB>) {
embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver);
@@ -17,8 +21,7 @@ async fn logger_task(driver: Driver<'static, USB>) {
#[embassy_executor::main]
async fn main(spawner: Spawner) {
let p = embassy_rp::init(Default::default());
- let irq = interrupt::take!(USBCTRL_IRQ);
- let driver = Driver::new(p.USB, irq);
+ let driver = Driver::new(p.USB, Irqs);
spawner.spawn(logger_task(driver)).unwrap();
let mut counter = 0;
diff --git a/examples/rp/src/bin/usb_serial.rs b/examples/rp/src/bin/usb_serial.rs
index 8160a1875..ca728536c 100644
--- a/examples/rp/src/bin/usb_serial.rs
+++ b/examples/rp/src/bin/usb_serial.rs
@@ -5,13 +5,18 @@
use defmt::{info, panic};
use embassy_executor::Spawner;
use embassy_futures::join::join;
-use embassy_rp::interrupt;
-use embassy_rp::usb::{Driver, Instance};
+use embassy_rp::bind_interrupts;
+use embassy_rp::peripherals::USB;
+use embassy_rp::usb::{Driver, Instance, InterruptHandler};
use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
use embassy_usb::driver::EndpointError;
use embassy_usb::{Builder, Config};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ USBCTRL_IRQ => InterruptHandler;
+});
+
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
info!("Hello there!");
@@ -19,8 +24,7 @@ async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
// Create the driver, from the HAL.
- let irq = interrupt::take!(USBCTRL_IRQ);
- let driver = Driver::new(p.USB, irq);
+ let driver = Driver::new(p.USB, Irqs);
// Create embassy-usb Config
let mut config = Config::new(0xc0de, 0xcafe);
diff --git a/tests/rp/src/bin/uart_buffered.rs b/tests/rp/src/bin/uart_buffered.rs
index 1deb22ce6..1dcf57d07 100644
--- a/tests/rp/src/bin/uart_buffered.rs
+++ b/tests/rp/src/bin/uart_buffered.rs
@@ -4,13 +4,18 @@
use defmt::{assert_eq, panic, *};
use embassy_executor::Spawner;
+use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output};
-use embassy_rp::interrupt;
-use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
+use embassy_rp::peripherals::UART0;
+use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
use embassy_time::{Duration, Timer};
use embedded_io::asynch::{Read, ReadExactError, Write};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ UART0_IRQ => BufferedInterruptHandler;
+});
+
async fn read(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
let mut buf = [255; N];
match uart.read_exact(&mut buf).await {
@@ -60,13 +65,12 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
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 tx_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
// bufferedUart.
@@ -86,7 +90,7 @@ async fn main(_spawner: Spawner) {
let config = Config::default();
let tx_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
// bufferedUart.
@@ -121,7 +125,7 @@ async fn main(_spawner: Spawner) {
config.baudrate = 1000;
let tx_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
uart.send_break(20).await;
@@ -155,7 +159,7 @@ async fn main(_spawner: Spawner) {
config.baudrate = 1000;
config.parity = Parity::ParityEven;
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) {
send(pin, v, Some(parity != 0)).await;
@@ -202,7 +206,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.baudrate = 1000;
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) {
if good {
diff --git a/tests/rp/src/bin/uart_dma.rs b/tests/rp/src/bin/uart_dma.rs
index 52f42e582..75be76eda 100644
--- a/tests/rp/src/bin/uart_dma.rs
+++ b/tests/rp/src/bin/uart_dma.rs
@@ -4,12 +4,17 @@
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
+use embassy_rp::bind_interrupts;
use embassy_rp::gpio::{Level, Output};
-use embassy_rp::interrupt;
-use embassy_rp::uart::{Async, Config, Error, Instance, Parity, Uart, UartRx};
+use embassy_rp::peripherals::UART0;
+use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
use embassy_time::{Duration, Timer};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ UART0_IRQ => InterruptHandler;
+});
+
async fn read(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
let mut buf = [255; N];
uart.read(&mut buf).await?;
@@ -51,7 +56,6 @@ async fn main(_spawner: Spawner) {
info!("Hello World!");
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.
// This is because we aren't sending+receiving at the same time.
@@ -61,7 +65,7 @@ async fn main(_spawner: Spawner) {
&mut uart,
&mut tx,
&mut rx,
- &mut irq,
+ Irqs,
&mut p.DMA_CH0,
&mut p.DMA_CH1,
config,
@@ -82,7 +86,7 @@ async fn main(_spawner: Spawner) {
&mut uart,
&mut tx,
&mut rx,
- &mut irq,
+ Irqs,
&mut p.DMA_CH0,
&mut p.DMA_CH1,
config,
@@ -111,7 +115,7 @@ async fn main(_spawner: Spawner) {
&mut uart,
&mut tx,
&mut rx,
- &mut irq,
+ Irqs,
&mut p.DMA_CH0,
&mut p.DMA_CH1,
config,
@@ -154,7 +158,7 @@ async fn main(_spawner: Spawner) {
let mut config = Config::default();
config.baudrate = 1000;
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) {
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
let mut config = Config::default();
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) {
if good {
diff --git a/tests/rp/src/bin/uart_upgrade.rs b/tests/rp/src/bin/uart_upgrade.rs
index d8c9aecf6..8605bb1c5 100644
--- a/tests/rp/src/bin/uart_upgrade.rs
+++ b/tests/rp/src/bin/uart_upgrade.rs
@@ -4,11 +4,16 @@
use defmt::{assert_eq, *};
use embassy_executor::Spawner;
-use embassy_rp::interrupt;
-use embassy_rp::uart::{Config, Uart};
+use embassy_rp::bind_interrupts;
+use embassy_rp::peripherals::UART0;
+use embassy_rp::uart::{BufferedInterruptHandler, Config, Uart};
use embedded_io::asynch::{Read, Write};
use {defmt_rtt as _, panic_probe as _};
+bind_interrupts!(struct Irqs {
+ UART0_IRQ => BufferedInterruptHandler;
+});
+
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_rp::init(Default::default());
@@ -29,11 +34,10 @@ async fn main(_spawner: Spawner) {
uart.blocking_read(&mut buf).unwrap();
assert_eq!(buf, data);
- let irq = interrupt::take!(UART0_IRQ);
let tx_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
// bufferedUart.