aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2023-05-15 15:59:30 +0000
committerGitHub <[email protected]>2023-05-15 15:59:30 +0000
commit1a87f7477abdb033d960a6af63c95a9e0575e670 (patch)
tree0523c59fe3ef2bd406d44ab414f2903c68a918b9
parent2bf2e54db925e1d8845deb5eaea737b6add95402 (diff)
parent14a5d03af2a74eccaa9930bdf81eef43791a4b33 (diff)
Merge #1458
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 <[email protected]>
-rw-r--r--embassy-rp/src/adc.rs31
-rw-r--r--embassy-rp/src/i2c.rs34
-rw-r--r--embassy-rp/src/interrupt.rs37
-rw-r--r--embassy-rp/src/uart/buffered.rs209
-rw-r--r--embassy-rp/src/uart/mod.rs101
-rw-r--r--embassy-rp/src/usb.rs98
-rw-r--r--examples/rp/src/bin/adc.rs11
-rw-r--r--examples/rp/src/bin/i2c_async.rs12
-rw-r--r--examples/rp/src/bin/uart_buffered_split.rs11
-rw-r--r--examples/rp/src/bin/uart_unidir.rs16
-rw-r--r--examples/rp/src/bin/usb_ethernet.rs12
-rw-r--r--examples/rp/src/bin/usb_logger.rs11
-rw-r--r--examples/rp/src/bin/usb_serial.rs12
-rw-r--r--tests/rp/src/bin/uart_buffered.rs20
-rw-r--r--tests/rp/src/bin/uart_dma.rs20
-rw-r--r--tests/rp/src/bin/uart_upgrade.rs12
16 files changed, 372 insertions, 275 deletions
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;
3use core::sync::atomic::{compiler_fence, Ordering}; 3use core::sync::atomic::{compiler_fence, Ordering};
4use core::task::Poll; 4use core::task::Poll;
5 5
6use embassy_hal_common::into_ref; 6use embassy_cortex_m::interrupt::{Binding, Interrupt};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use embedded_hal_02::adc::{Channel, OneShot}; 8use embedded_hal_02::adc::{Channel, OneShot};
9 9
10use crate::gpio::Pin; 10use crate::gpio::Pin;
11use crate::interrupt::{self, InterruptExt}; 11use crate::interrupt::{self, InterruptExt, ADC_IRQ_FIFO};
12use crate::peripherals::ADC; 12use crate::peripherals::ADC;
13use crate::{pac, peripherals, Peripheral}; 13use crate::{pac, peripherals, Peripheral};
14static WAKER: AtomicWaker = AtomicWaker::new(); 14static WAKER: AtomicWaker = AtomicWaker::new();
@@ -47,10 +47,9 @@ impl<'d> Adc<'d> {
47 47
48 pub fn new( 48 pub fn new(
49 _inner: impl Peripheral<P = ADC> + 'd, 49 _inner: impl Peripheral<P = ADC> + 'd,
50 irq: impl Peripheral<P = interrupt::ADC_IRQ_FIFO> + 'd, 50 _irq: impl Binding<ADC_IRQ_FIFO, InterruptHandler>,
51 _config: Config, 51 _config: Config,
52 ) -> Self { 52 ) -> Self {
53 into_ref!(irq);
54 unsafe { 53 unsafe {
55 let reset = Self::reset(); 54 let reset = Self::reset();
56 crate::reset::reset(reset); 55 crate::reset::reset(reset);
@@ -63,14 +62,10 @@ impl<'d> Adc<'d> {
63 } 62 }
64 63
65 // Setup IRQ 64 // Setup IRQ
66 irq.disable(); 65 unsafe {
67 irq.set_handler(|_| unsafe { 66 ADC_IRQ_FIFO::steal().unpend();
68 let r = Self::regs(); 67 ADC_IRQ_FIFO::steal().enable();
69 r.inte().write(|w| w.set_fifo(false)); 68 };
70 WAKER.wake();
71 });
72 irq.unpend();
73 irq.enable();
74 69
75 Self { phantom: PhantomData } 70 Self { phantom: PhantomData }
76 } 71 }
@@ -165,6 +160,18 @@ macro_rules! impl_pin {
165 }; 160 };
166} 161}
167 162
163pub struct InterruptHandler {
164 _empty: (),
165}
166
167impl interrupt::Handler<ADC_IRQ_FIFO> for InterruptHandler {
168 unsafe fn on_interrupt() {
169 let r = Adc::regs();
170 r.inte().write(|w| w.set_fifo(false));
171 WAKER.wake();
172 }
173}
174
168impl_pin!(PIN_26, 0); 175impl_pin!(PIN_26, 0);
169impl_pin!(PIN_27, 1); 176impl_pin!(PIN_27, 1);
170impl_pin!(PIN_28, 2); 177impl_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;
2use core::marker::PhantomData; 2use core::marker::PhantomData;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use embassy_cortex_m::interrupt::InterruptExt; 5use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt};
6use embassy_hal_common::{into_ref, PeripheralRef}; 6use embassy_hal_common::{into_ref, PeripheralRef};
7use embassy_sync::waitqueue::AtomicWaker; 7use embassy_sync::waitqueue::AtomicWaker;
8use pac::i2c; 8use pac::i2c;
@@ -75,23 +75,21 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
75 peri: impl Peripheral<P = T> + 'd, 75 peri: impl Peripheral<P = T> + 'd,
76 scl: impl Peripheral<P = impl SclPin<T>> + 'd, 76 scl: impl Peripheral<P = impl SclPin<T>> + 'd,
77 sda: impl Peripheral<P = impl SdaPin<T>> + 'd, 77 sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
78 irq: impl Peripheral<P = T::Interrupt> + 'd, 78 _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
79 config: Config, 79 config: Config,
80 ) -> Self { 80 ) -> Self {
81 into_ref!(scl, sda, irq); 81 into_ref!(scl, sda);
82 82
83 let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config); 83 let i2c = Self::new_inner(peri, scl.map_into(), sda.map_into(), config);
84 84
85 irq.set_handler(Self::on_interrupt);
86 unsafe { 85 unsafe {
87 let i2c = T::regs(); 86 let i2c = T::regs();
88 87
89 // mask everything initially 88 // mask everything initially
90 i2c.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0)); 89 i2c.ic_intr_mask().write_value(i2c::regs::IcIntrMask(0));
90 T::Interrupt::steal().unpend();
91 T::Interrupt::steal().enable();
91 } 92 }
92 irq.unpend();
93 debug_assert!(!irq.is_pending());
94 irq.enable();
95 93
96 i2c 94 i2c
97 } 95 }
@@ -115,14 +113,6 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
115 .await 113 .await
116 } 114 }
117 115
118 // Mask interrupts and wake any task waiting for this interrupt
119 unsafe fn on_interrupt(_: *mut ()) {
120 let i2c = T::regs();
121 i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default());
122
123 T::waker().wake();
124 }
125
126 async fn read_async_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> { 116 async fn read_async_internal(&mut self, buffer: &mut [u8], restart: bool, send_stop: bool) -> Result<(), Error> {
127 if buffer.is_empty() { 117 if buffer.is_empty() {
128 return Err(Error::InvalidReadBufferLength); 118 return Err(Error::InvalidReadBufferLength);
@@ -320,6 +310,20 @@ impl<'d, T: Instance> I2c<'d, T, Async> {
320 } 310 }
321} 311}
322 312
313pub struct InterruptHandler<T: Instance> {
314 _uart: PhantomData<T>,
315}
316
317impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
318 // Mask interrupts and wake any task waiting for this interrupt
319 unsafe fn on_interrupt() {
320 let i2c = T::regs();
321 i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default());
322
323 T::waker().wake();
324 }
325}
326
323impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> { 327impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
324 fn new_inner( 328 fn new_inner(
325 _peri: impl Peripheral<P = T> + 'd, 329 _peri: impl Peripheral<P = T> + '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 @@
1//! Interrupt management 1//! Interrupt definitions and macros to bind them.
2//! 2pub use cortex_m::interrupt::{CriticalSection, Mutex};
3//! This module implements an API for managing interrupts compatible with
4//! nrf_softdevice::interrupt. Intended for switching between the two at compile-time.
5
6// Re-exports
7use embassy_cortex_m::interrupt::_export::declare; 3use embassy_cortex_m::interrupt::_export::declare;
8pub use embassy_cortex_m::interrupt::*; 4pub use embassy_cortex_m::interrupt::{Binding, Handler, Interrupt, InterruptExt, Priority};
9 5
10use crate::pac::Interrupt as InterruptEnum; 6use crate::pac::Interrupt as InterruptEnum;
11declare!(TIMER_IRQ_0); 7declare!(TIMER_IRQ_0);
@@ -40,3 +36,30 @@ declare!(SWI_IRQ_2);
40declare!(SWI_IRQ_3); 36declare!(SWI_IRQ_3);
41declare!(SWI_IRQ_4); 37declare!(SWI_IRQ_4);
42declare!(SWI_IRQ_5); 38declare!(SWI_IRQ_5);
39
40/// Macro to bind interrupts to handlers.
41///
42/// This defines the right interrupt handlers, and creates a unit struct (like `struct Irqs;`)
43/// and implements the right [`Binding`]s for it. You can pass this struct to drivers to
44/// prove at compile-time that the right interrupts have been bound.
45// developer note: this macro can't be in `embassy-cortex-m` due to the use of `$crate`.
46#[macro_export]
47macro_rules! bind_interrupts {
48 ($vis:vis struct $name:ident { $($irq:ident => $($handler:ty),*;)* }) => {
49 $vis struct $name;
50
51 $(
52 #[allow(non_snake_case)]
53 #[no_mangle]
54 unsafe extern "C" fn $irq() {
55 $(
56 <$handler as $crate::interrupt::Handler<$crate::interrupt::$irq>>::on_interrupt();
57 )*
58 }
59
60 $(
61 unsafe impl $crate::interrupt::Binding<$crate::interrupt::$irq, $handler> for $name {}
62 )*
63 )*
64 };
65}
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;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicU8, Ordering}; 5use atomic_polyfill::{AtomicU8, Ordering};
6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 6use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt};
7use embassy_hal_common::atomic_ring_buffer::RingBuffer; 7use embassy_hal_common::atomic_ring_buffer::RingBuffer;
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
@@ -52,7 +52,7 @@ pub struct BufferedUartTx<'d, T: Instance> {
52} 52}
53 53
54pub(crate) fn init_buffers<'d, T: Instance + 'd>( 54pub(crate) fn init_buffers<'d, T: Instance + 'd>(
55 irq: PeripheralRef<'d, T::Interrupt>, 55 _irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
56 tx_buffer: &'d mut [u8], 56 tx_buffer: &'d mut [u8],
57 rx_buffer: &'d mut [u8], 57 rx_buffer: &'d mut [u8],
58) { 58) {
@@ -79,24 +79,23 @@ pub(crate) fn init_buffers<'d, T: Instance + 'd>(
79 w.set_rtim(true); 79 w.set_rtim(true);
80 w.set_txim(true); 80 w.set_txim(true);
81 }); 81 });
82 };
83 82
84 irq.set_handler(on_interrupt::<T>); 83 T::Interrupt::steal().unpend();
85 irq.unpend(); 84 T::Interrupt::steal().enable();
86 irq.enable(); 85 };
87} 86}
88 87
89impl<'d, T: Instance> BufferedUart<'d, T> { 88impl<'d, T: Instance> BufferedUart<'d, T> {
90 pub fn new( 89 pub fn new(
91 _uart: impl Peripheral<P = T> + 'd, 90 _uart: impl Peripheral<P = T> + 'd,
92 irq: impl Peripheral<P = T::Interrupt> + 'd, 91 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
93 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 92 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
94 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 93 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
95 tx_buffer: &'d mut [u8], 94 tx_buffer: &'d mut [u8],
96 rx_buffer: &'d mut [u8], 95 rx_buffer: &'d mut [u8],
97 config: Config, 96 config: Config,
98 ) -> Self { 97 ) -> Self {
99 into_ref!(irq, tx, rx); 98 into_ref!(tx, rx);
100 99
101 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), Some(rx.map_into()), None, None, config); 100 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), Some(rx.map_into()), None, None, config);
102 init_buffers::<T>(irq, tx_buffer, rx_buffer); 101 init_buffers::<T>(irq, tx_buffer, rx_buffer);
@@ -109,7 +108,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
109 108
110 pub fn new_with_rtscts( 109 pub fn new_with_rtscts(
111 _uart: impl Peripheral<P = T> + 'd, 110 _uart: impl Peripheral<P = T> + 'd,
112 irq: impl Peripheral<P = T::Interrupt> + 'd, 111 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
113 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 112 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
114 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 113 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
115 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 114 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
@@ -118,7 +117,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
118 rx_buffer: &'d mut [u8], 117 rx_buffer: &'d mut [u8],
119 config: Config, 118 config: Config,
120 ) -> Self { 119 ) -> Self {
121 into_ref!(irq, tx, rx, cts, rts); 120 into_ref!(tx, rx, cts, rts);
122 121
123 super::Uart::<'d, T, Async>::init( 122 super::Uart::<'d, T, Async>::init(
124 Some(tx.map_into()), 123 Some(tx.map_into()),
@@ -163,12 +162,12 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
163impl<'d, T: Instance> BufferedUartRx<'d, T> { 162impl<'d, T: Instance> BufferedUartRx<'d, T> {
164 pub fn new( 163 pub fn new(
165 _uart: impl Peripheral<P = T> + 'd, 164 _uart: impl Peripheral<P = T> + 'd,
166 irq: impl Peripheral<P = T::Interrupt> + 'd, 165 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
167 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 166 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
168 rx_buffer: &'d mut [u8], 167 rx_buffer: &'d mut [u8],
169 config: Config, 168 config: Config,
170 ) -> Self { 169 ) -> Self {
171 into_ref!(irq, rx); 170 into_ref!(rx);
172 171
173 super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config); 172 super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), None, None, config);
174 init_buffers::<T>(irq, &mut [], rx_buffer); 173 init_buffers::<T>(irq, &mut [], rx_buffer);
@@ -178,13 +177,13 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
178 177
179 pub fn new_with_rts( 178 pub fn new_with_rts(
180 _uart: impl Peripheral<P = T> + 'd, 179 _uart: impl Peripheral<P = T> + 'd,
181 irq: impl Peripheral<P = T::Interrupt> + 'd, 180 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
182 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 181 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
183 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 182 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
184 rx_buffer: &'d mut [u8], 183 rx_buffer: &'d mut [u8],
185 config: Config, 184 config: Config,
186 ) -> Self { 185 ) -> Self {
187 into_ref!(irq, rx, rts); 186 into_ref!(rx, rts);
188 187
189 super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), Some(rts.map_into()), None, config); 188 super::Uart::<'d, T, Async>::init(None, Some(rx.map_into()), Some(rts.map_into()), None, config);
190 init_buffers::<T>(irq, &mut [], rx_buffer); 189 init_buffers::<T>(irq, &mut [], rx_buffer);
@@ -312,12 +311,12 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
312impl<'d, T: Instance> BufferedUartTx<'d, T> { 311impl<'d, T: Instance> BufferedUartTx<'d, T> {
313 pub fn new( 312 pub fn new(
314 _uart: impl Peripheral<P = T> + 'd, 313 _uart: impl Peripheral<P = T> + 'd,
315 irq: impl Peripheral<P = T::Interrupt> + 'd, 314 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
316 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 315 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
317 tx_buffer: &'d mut [u8], 316 tx_buffer: &'d mut [u8],
318 config: Config, 317 config: Config,
319 ) -> Self { 318 ) -> Self {
320 into_ref!(irq, tx); 319 into_ref!(tx);
321 320
322 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config); 321 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, None, config);
323 init_buffers::<T>(irq, tx_buffer, &mut []); 322 init_buffers::<T>(irq, tx_buffer, &mut []);
@@ -327,13 +326,13 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
327 326
328 pub fn new_with_cts( 327 pub fn new_with_cts(
329 _uart: impl Peripheral<P = T> + 'd, 328 _uart: impl Peripheral<P = T> + 'd,
330 irq: impl Peripheral<P = T::Interrupt> + 'd, 329 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
331 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 330 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
332 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 331 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
333 tx_buffer: &'d mut [u8], 332 tx_buffer: &'d mut [u8],
334 config: Config, 333 config: Config,
335 ) -> Self { 334 ) -> Self {
336 into_ref!(irq, tx, cts); 335 into_ref!(tx, cts);
337 336
338 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, Some(cts.map_into()), config); 337 super::Uart::<'d, T, Async>::init(Some(tx.map_into()), None, None, Some(cts.map_into()), config);
339 init_buffers::<T>(irq, tx_buffer, &mut []); 338 init_buffers::<T>(irq, tx_buffer, &mut []);
@@ -482,97 +481,107 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
482 } 481 }
483} 482}
484 483
485pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) { 484pub struct BufferedInterruptHandler<T: Instance> {
486 let r = T::regs(); 485 _uart: PhantomData<T>,
487 let s = T::buffered_state(); 486}
488 487
489 unsafe { 488impl<T: Instance> interrupt::Handler<T::Interrupt> for BufferedInterruptHandler<T> {
490 // Clear TX and error interrupt flags 489 unsafe fn on_interrupt() {
491 // RX interrupt flags are cleared by reading from the FIFO. 490 let r = T::regs();
492 let ris = r.uartris().read(); 491 if r.uartdmacr().read().rxdmae() {
493 r.uarticr().write(|w| { 492 return;
494 w.set_txic(ris.txris()); 493 }
495 w.set_feic(ris.feris());
496 w.set_peic(ris.peris());
497 w.set_beic(ris.beris());
498 w.set_oeic(ris.oeris());
499 });
500 494
501 trace!("on_interrupt ris={:#X}", ris.0); 495 let s = T::buffered_state();
502 496
503 // Errors 497 unsafe {
504 if ris.feris() { 498 // Clear TX and error interrupt flags
505 warn!("Framing error"); 499 // RX interrupt flags are cleared by reading from the FIFO.
506 } 500 let ris = r.uartris().read();
507 if ris.peris() { 501 r.uarticr().write(|w| {
508 warn!("Parity error"); 502 w.set_txic(ris.txris());
509 } 503 w.set_feic(ris.feris());
510 if ris.beris() { 504 w.set_peic(ris.peris());
511 warn!("Break error"); 505 w.set_beic(ris.beris());
512 } 506 w.set_oeic(ris.oeris());
513 if ris.oeris() { 507 });
514 warn!("Overrun error");
515 }
516 508
517 // RX 509 trace!("on_interrupt ris={:#X}", ris.0);
518 let mut rx_writer = s.rx_buf.writer(); 510
519 let rx_buf = rx_writer.push_slice(); 511 // Errors
520 let mut n_read = 0; 512 if ris.feris() {
521 let mut error = false; 513 warn!("Framing error");
522 for rx_byte in rx_buf {
523 if r.uartfr().read().rxfe() {
524 break;
525 } 514 }
526 let dr = r.uartdr().read(); 515 if ris.peris() {
527 if (dr.0 >> 8) != 0 { 516 warn!("Parity error");
528 s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed); 517 }
529 error = true; 518 if ris.beris() {
530 // only fill the buffer with valid characters. the current character is fine 519 warn!("Break error");
531 // if the error is an overrun, but if we add it to the buffer we'll report 520 }
532 // the overrun one character too late. drop it instead and pretend we were 521 if ris.oeris() {
533 // a bit slower at draining the rx fifo than we actually were. 522 warn!("Overrun error");
534 // this is consistent with blocking uart error reporting.
535 break;
536 } 523 }
537 *rx_byte = dr.data();
538 n_read += 1;
539 }
540 if n_read > 0 {
541 rx_writer.push_done(n_read);
542 s.rx_waker.wake();
543 } else if error {
544 s.rx_waker.wake();
545 }
546 // Disable any further RX interrupts when the buffer becomes full or
547 // errors have occurred. This lets us buffer additional errors in the
548 // fifo without needing more error storage locations, and most applications
549 // will want to do a full reset of their uart state anyway once an error
550 // has happened.
551 if s.rx_buf.is_full() || error {
552 r.uartimsc().write_clear(|w| {
553 w.set_rxim(true);
554 w.set_rtim(true);
555 });
556 }
557 524
558 // TX 525 // RX
559 let mut tx_reader = s.tx_buf.reader(); 526 let mut rx_writer = s.rx_buf.writer();
560 let tx_buf = tx_reader.pop_slice(); 527 let rx_buf = rx_writer.push_slice();
561 let mut n_written = 0; 528 let mut n_read = 0;
562 for tx_byte in tx_buf.iter_mut() { 529 let mut error = false;
563 if r.uartfr().read().txff() { 530 for rx_byte in rx_buf {
564 break; 531 if r.uartfr().read().rxfe() {
532 break;
533 }
534 let dr = r.uartdr().read();
535 if (dr.0 >> 8) != 0 {
536 s.rx_error.fetch_or((dr.0 >> 8) as u8, Ordering::Relaxed);
537 error = true;
538 // only fill the buffer with valid characters. the current character is fine
539 // if the error is an overrun, but if we add it to the buffer we'll report
540 // the overrun one character too late. drop it instead and pretend we were
541 // a bit slower at draining the rx fifo than we actually were.
542 // this is consistent with blocking uart error reporting.
543 break;
544 }
545 *rx_byte = dr.data();
546 n_read += 1;
565 } 547 }
566 r.uartdr().write(|w| w.set_data(*tx_byte)); 548 if n_read > 0 {
567 n_written += 1; 549 rx_writer.push_done(n_read);
568 } 550 s.rx_waker.wake();
569 if n_written > 0 { 551 } else if error {
570 tx_reader.pop_done(n_written); 552 s.rx_waker.wake();
571 s.tx_waker.wake(); 553 }
554 // Disable any further RX interrupts when the buffer becomes full or
555 // errors have occurred. This lets us buffer additional errors in the
556 // fifo without needing more error storage locations, and most applications
557 // will want to do a full reset of their uart state anyway once an error
558 // has happened.
559 if s.rx_buf.is_full() || error {
560 r.uartimsc().write_clear(|w| {
561 w.set_rxim(true);
562 w.set_rtim(true);
563 });
564 }
565
566 // TX
567 let mut tx_reader = s.tx_buf.reader();
568 let tx_buf = tx_reader.pop_slice();
569 let mut n_written = 0;
570 for tx_byte in tx_buf.iter_mut() {
571 if r.uartfr().read().txff() {
572 break;
573 }
574 r.uartdr().write(|w| w.set_data(*tx_byte));
575 n_written += 1;
576 }
577 if n_written > 0 {
578 tx_reader.pop_done(n_written);
579 s.tx_waker.wake();
580 }
581 // The TX interrupt only triggers once when the FIFO threshold is
582 // crossed. No need to disable it when the buffer becomes empty
583 // as it does re-trigger anymore once we have cleared it.
572 } 584 }
573 // The TX interrupt only triggers once when the FIFO threshold is
574 // crossed. No need to disable it when the buffer becomes empty
575 // as it does re-trigger anymore once we have cleared it.
576 } 585 }
577} 586}
578 587
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;
3use core::task::Poll; 3use core::task::Poll;
4 4
5use atomic_polyfill::{AtomicU16, Ordering}; 5use atomic_polyfill::{AtomicU16, Ordering};
6use embassy_cortex_m::interrupt::{Interrupt, InterruptExt}; 6use embassy_cortex_m::interrupt::{self, Binding, Interrupt, InterruptExt};
7use embassy_futures::select::{select, Either}; 7use embassy_futures::select::{select, Either};
8use embassy_hal_common::{into_ref, PeripheralRef}; 8use embassy_hal_common::{into_ref, PeripheralRef};
9use embassy_sync::waitqueue::AtomicWaker; 9use embassy_sync::waitqueue::AtomicWaker;
@@ -20,7 +20,7 @@ use crate::{pac, peripherals, Peripheral, RegExt};
20#[cfg(feature = "nightly")] 20#[cfg(feature = "nightly")]
21mod buffered; 21mod buffered;
22#[cfg(feature = "nightly")] 22#[cfg(feature = "nightly")]
23pub use buffered::{BufferedUart, BufferedUartRx, BufferedUartTx}; 23pub use buffered::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, BufferedUartTx};
24 24
25#[derive(Clone, Copy, PartialEq, Eq, Debug)] 25#[derive(Clone, Copy, PartialEq, Eq, Debug)]
26pub enum DataBits { 26pub enum DataBits {
@@ -203,11 +203,9 @@ impl<'d, T: Instance> UartTx<'d, T, Blocking> {
203 #[cfg(feature = "nightly")] 203 #[cfg(feature = "nightly")]
204 pub fn into_buffered( 204 pub fn into_buffered(
205 self, 205 self,
206 irq: impl Peripheral<P = T::Interrupt> + 'd, 206 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
207 tx_buffer: &'d mut [u8], 207 tx_buffer: &'d mut [u8],
208 ) -> BufferedUartTx<'d, T> { 208 ) -> BufferedUartTx<'d, T> {
209 into_ref!(irq);
210
211 buffered::init_buffers::<T>(irq, tx_buffer, &mut []); 209 buffered::init_buffers::<T>(irq, tx_buffer, &mut []);
212 210
213 BufferedUartTx { phantom: PhantomData } 211 BufferedUartTx { phantom: PhantomData }
@@ -235,25 +233,24 @@ impl<'d, T: Instance, M: Mode> UartRx<'d, T, M> {
235 pub fn new( 233 pub fn new(
236 _uart: impl Peripheral<P = T> + 'd, 234 _uart: impl Peripheral<P = T> + 'd,
237 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 235 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
238 irq: impl Peripheral<P = T::Interrupt> + 'd, 236 _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
239 rx_dma: impl Peripheral<P = impl Channel> + 'd, 237 rx_dma: impl Peripheral<P = impl Channel> + 'd,
240 config: Config, 238 config: Config,
241 ) -> Self { 239 ) -> Self {
242 into_ref!(rx, irq, rx_dma); 240 into_ref!(rx, rx_dma);
243 Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config); 241 Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
244 Self::new_inner(Some(irq), Some(rx_dma.map_into())) 242 Self::new_inner(true, Some(rx_dma.map_into()))
245 } 243 }
246 244
247 fn new_inner(irq: Option<PeripheralRef<'d, T::Interrupt>>, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self { 245 fn new_inner(has_irq: bool, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
248 debug_assert_eq!(irq.is_some(), rx_dma.is_some()); 246 debug_assert_eq!(has_irq, rx_dma.is_some());
249 if let Some(irq) = irq { 247 if has_irq {
250 unsafe { 248 unsafe {
251 // disable all error interrupts initially 249 // disable all error interrupts initially
252 T::regs().uartimsc().write(|w| w.0 = 0); 250 T::regs().uartimsc().write(|w| w.0 = 0);
251 T::Interrupt::steal().unpend();
252 T::Interrupt::steal().enable();
253 } 253 }
254 irq.set_handler(on_interrupt::<T>);
255 irq.unpend();
256 irq.enable();
257 } 254 }
258 Self { 255 Self {
259 rx_dma, 256 rx_dma,
@@ -299,6 +296,12 @@ impl<'d, T: Instance, M: Mode> Drop for UartRx<'d, T, M> {
299 if let Some(_) = self.rx_dma { 296 if let Some(_) = self.rx_dma {
300 unsafe { 297 unsafe {
301 T::Interrupt::steal().disable(); 298 T::Interrupt::steal().disable();
299 // clear dma flags. irq handlers use these to disambiguate among themselves.
300 T::regs().uartdmacr().write_clear(|reg| {
301 reg.set_rxdmae(true);
302 reg.set_txdmae(true);
303 reg.set_dmaonerr(true);
304 });
302 } 305 }
303 } 306 }
304 } 307 }
@@ -312,33 +315,41 @@ impl<'d, T: Instance> UartRx<'d, T, Blocking> {
312 ) -> Self { 315 ) -> Self {
313 into_ref!(rx); 316 into_ref!(rx);
314 Uart::<T, Blocking>::init(None, Some(rx.map_into()), None, None, config); 317 Uart::<T, Blocking>::init(None, Some(rx.map_into()), None, None, config);
315 Self::new_inner(None, None) 318 Self::new_inner(false, None)
316 } 319 }
317 320
318 #[cfg(feature = "nightly")] 321 #[cfg(feature = "nightly")]
319 pub fn into_buffered( 322 pub fn into_buffered(
320 self, 323 self,
321 irq: impl Peripheral<P = T::Interrupt> + 'd, 324 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
322 rx_buffer: &'d mut [u8], 325 rx_buffer: &'d mut [u8],
323 ) -> BufferedUartRx<'d, T> { 326 ) -> BufferedUartRx<'d, T> {
324 into_ref!(irq);
325
326 buffered::init_buffers::<T>(irq, &mut [], rx_buffer); 327 buffered::init_buffers::<T>(irq, &mut [], rx_buffer);
327 328
328 BufferedUartRx { phantom: PhantomData } 329 BufferedUartRx { phantom: PhantomData }
329 } 330 }
330} 331}
331 332
332unsafe fn on_interrupt<T: Instance>(_: *mut ()) { 333pub struct InterruptHandler<T: Instance> {
333 let uart = T::regs(); 334 _uart: PhantomData<T>,
334 let state = T::dma_state(); 335}
335 let errs = uart.uartris().read(); 336
336 state.rx_errs.store(errs.0 as u16, Ordering::Relaxed); 337impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
337 state.rx_err_waker.wake(); 338 unsafe fn on_interrupt() {
338 // disable the error interrupts instead of clearing the flags. clearing the 339 let uart = T::regs();
339 // flags would allow the dma transfer to continue, potentially signaling 340 if !uart.uartdmacr().read().rxdmae() {
340 // completion before we can check for errors that happened *during* the transfer. 341 return;
341 uart.uartimsc().write_clear(|w| w.0 = errs.0); 342 }
343
344 let state = T::dma_state();
345 let errs = uart.uartris().read();
346 state.rx_errs.store(errs.0 as u16, Ordering::Relaxed);
347 state.rx_err_waker.wake();
348 // disable the error interrupts instead of clearing the flags. clearing the
349 // flags would allow the dma transfer to continue, potentially signaling
350 // completion before we can check for errors that happened *during* the transfer.
351 uart.uartimsc().write_clear(|w| w.0 = errs.0);
352 }
342} 353}
343 354
344impl<'d, T: Instance> UartRx<'d, T, Async> { 355impl<'d, T: Instance> UartRx<'d, T, Async> {
@@ -428,7 +439,17 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
428 config: Config, 439 config: Config,
429 ) -> Self { 440 ) -> Self {
430 into_ref!(tx, rx); 441 into_ref!(tx, rx);
431 Self::new_inner(uart, tx.map_into(), rx.map_into(), None, None, None, None, None, config) 442 Self::new_inner(
443 uart,
444 tx.map_into(),
445 rx.map_into(),
446 None,
447 None,
448 false,
449 None,
450 None,
451 config,
452 )
432 } 453 }
433 454
434 /// Create a new UART with hardware flow control (RTS/CTS) 455 /// Create a new UART with hardware flow control (RTS/CTS)
@@ -447,7 +468,7 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
447 rx.map_into(), 468 rx.map_into(),
448 Some(rts.map_into()), 469 Some(rts.map_into()),
449 Some(cts.map_into()), 470 Some(cts.map_into()),
450 None, 471 false,
451 None, 472 None,
452 None, 473 None,
453 config, 474 config,
@@ -457,12 +478,10 @@ impl<'d, T: Instance> Uart<'d, T, Blocking> {
457 #[cfg(feature = "nightly")] 478 #[cfg(feature = "nightly")]
458 pub fn into_buffered( 479 pub fn into_buffered(
459 self, 480 self,
460 irq: impl Peripheral<P = T::Interrupt> + 'd, 481 irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
461 tx_buffer: &'d mut [u8], 482 tx_buffer: &'d mut [u8],
462 rx_buffer: &'d mut [u8], 483 rx_buffer: &'d mut [u8],
463 ) -> BufferedUart<'d, T> { 484 ) -> BufferedUart<'d, T> {
464 into_ref!(irq);
465
466 buffered::init_buffers::<T>(irq, tx_buffer, rx_buffer); 485 buffered::init_buffers::<T>(irq, tx_buffer, rx_buffer);
467 486
468 BufferedUart { 487 BufferedUart {
@@ -478,19 +497,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
478 uart: impl Peripheral<P = T> + 'd, 497 uart: impl Peripheral<P = T> + 'd,
479 tx: impl Peripheral<P = impl TxPin<T>> + 'd, 498 tx: impl Peripheral<P = impl TxPin<T>> + 'd,
480 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 499 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
481 irq: impl Peripheral<P = T::Interrupt> + 'd, 500 _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
482 tx_dma: impl Peripheral<P = impl Channel> + 'd, 501 tx_dma: impl Peripheral<P = impl Channel> + 'd,
483 rx_dma: impl Peripheral<P = impl Channel> + 'd, 502 rx_dma: impl Peripheral<P = impl Channel> + 'd,
484 config: Config, 503 config: Config,
485 ) -> Self { 504 ) -> Self {
486 into_ref!(tx, rx, irq, tx_dma, rx_dma); 505 into_ref!(tx, rx, tx_dma, rx_dma);
487 Self::new_inner( 506 Self::new_inner(
488 uart, 507 uart,
489 tx.map_into(), 508 tx.map_into(),
490 rx.map_into(), 509 rx.map_into(),
491 None, 510 None,
492 None, 511 None,
493 Some(irq), 512 true,
494 Some(tx_dma.map_into()), 513 Some(tx_dma.map_into()),
495 Some(rx_dma.map_into()), 514 Some(rx_dma.map_into()),
496 config, 515 config,
@@ -504,19 +523,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
504 rx: impl Peripheral<P = impl RxPin<T>> + 'd, 523 rx: impl Peripheral<P = impl RxPin<T>> + 'd,
505 rts: impl Peripheral<P = impl RtsPin<T>> + 'd, 524 rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
506 cts: impl Peripheral<P = impl CtsPin<T>> + 'd, 525 cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
507 irq: impl Peripheral<P = T::Interrupt> + 'd, 526 _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
508 tx_dma: impl Peripheral<P = impl Channel> + 'd, 527 tx_dma: impl Peripheral<P = impl Channel> + 'd,
509 rx_dma: impl Peripheral<P = impl Channel> + 'd, 528 rx_dma: impl Peripheral<P = impl Channel> + 'd,
510 config: Config, 529 config: Config,
511 ) -> Self { 530 ) -> Self {
512 into_ref!(tx, rx, cts, rts, irq, tx_dma, rx_dma); 531 into_ref!(tx, rx, cts, rts, tx_dma, rx_dma);
513 Self::new_inner( 532 Self::new_inner(
514 uart, 533 uart,
515 tx.map_into(), 534 tx.map_into(),
516 rx.map_into(), 535 rx.map_into(),
517 Some(rts.map_into()), 536 Some(rts.map_into()),
518 Some(cts.map_into()), 537 Some(cts.map_into()),
519 Some(irq), 538 true,
520 Some(tx_dma.map_into()), 539 Some(tx_dma.map_into()),
521 Some(rx_dma.map_into()), 540 Some(rx_dma.map_into()),
522 config, 541 config,
@@ -531,7 +550,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
531 mut rx: PeripheralRef<'d, AnyPin>, 550 mut rx: PeripheralRef<'d, AnyPin>,
532 mut rts: Option<PeripheralRef<'d, AnyPin>>, 551 mut rts: Option<PeripheralRef<'d, AnyPin>>,
533 mut cts: Option<PeripheralRef<'d, AnyPin>>, 552 mut cts: Option<PeripheralRef<'d, AnyPin>>,
534 irq: Option<PeripheralRef<'d, T::Interrupt>>, 553 has_irq: bool,
535 tx_dma: Option<PeripheralRef<'d, AnyChannel>>, 554 tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
536 rx_dma: Option<PeripheralRef<'d, AnyChannel>>, 555 rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
537 config: Config, 556 config: Config,
@@ -546,7 +565,7 @@ impl<'d, T: Instance + 'd, M: Mode> Uart<'d, T, M> {
546 565
547 Self { 566 Self {
548 tx: UartTx::new_inner(tx_dma), 567 tx: UartTx::new_inner(tx_dma),
549 rx: UartRx::new_inner(irq, rx_dma), 568 rx: UartRx::new_inner(has_irq, rx_dma),
550 } 569 }
551 } 570 }
552 571
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;
4use core::sync::atomic::{compiler_fence, Ordering}; 4use core::sync::atomic::{compiler_fence, Ordering};
5use core::task::Poll; 5use core::task::Poll;
6 6
7use embassy_hal_common::into_ref; 7use embassy_cortex_m::interrupt::{self, Binding};
8use embassy_sync::waitqueue::AtomicWaker; 8use embassy_sync::waitqueue::AtomicWaker;
9use embassy_usb_driver as driver; 9use embassy_usb_driver as driver;
10use embassy_usb_driver::{ 10use embassy_usb_driver::{
@@ -105,11 +105,11 @@ pub struct Driver<'d, T: Instance> {
105} 105}
106 106
107impl<'d, T: Instance> Driver<'d, T> { 107impl<'d, T: Instance> Driver<'d, T> {
108 pub fn new(_usb: impl Peripheral<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd) -> Self { 108 pub fn new(_usb: impl Peripheral<P = T> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> Self {
109 into_ref!(irq); 109 unsafe {
110 irq.set_handler(Self::on_interrupt); 110 T::Interrupt::steal().unpend();
111 irq.unpend(); 111 T::Interrupt::steal().enable();
112 irq.enable(); 112 }
113 113
114 let regs = T::regs(); 114 let regs = T::regs();
115 unsafe { 115 unsafe {
@@ -149,47 +149,6 @@ impl<'d, T: Instance> Driver<'d, T> {
149 } 149 }
150 } 150 }
151 151
152 fn on_interrupt(_: *mut ()) {
153 unsafe {
154 let regs = T::regs();
155 //let x = regs.istr().read().0;
156 //trace!("USB IRQ: {:08x}", x);
157
158 let ints = regs.ints().read();
159
160 if ints.bus_reset() {
161 regs.inte().write_clear(|w| w.set_bus_reset(true));
162 BUS_WAKER.wake();
163 }
164 if ints.dev_resume_from_host() {
165 regs.inte().write_clear(|w| w.set_dev_resume_from_host(true));
166 BUS_WAKER.wake();
167 }
168 if ints.dev_suspend() {
169 regs.inte().write_clear(|w| w.set_dev_suspend(true));
170 BUS_WAKER.wake();
171 }
172 if ints.setup_req() {
173 regs.inte().write_clear(|w| w.set_setup_req(true));
174 EP_OUT_WAKERS[0].wake();
175 }
176
177 if ints.buff_status() {
178 let s = regs.buff_status().read();
179 regs.buff_status().write_value(s);
180
181 for i in 0..EP_COUNT {
182 if s.ep_in(i) {
183 EP_IN_WAKERS[i].wake();
184 }
185 if s.ep_out(i) {
186 EP_OUT_WAKERS[i].wake();
187 }
188 }
189 }
190 }
191 }
192
193 fn alloc_endpoint<D: Dir>( 152 fn alloc_endpoint<D: Dir>(
194 &mut self, 153 &mut self,
195 ep_type: EndpointType, 154 ep_type: EndpointType,
@@ -288,6 +247,51 @@ impl<'d, T: Instance> Driver<'d, T> {
288 } 247 }
289} 248}
290 249
250pub struct InterruptHandler<T: Instance> {
251 _uart: PhantomData<T>,
252}
253
254impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
255 unsafe fn on_interrupt() {
256 let regs = T::regs();
257 //let x = regs.istr().read().0;
258 //trace!("USB IRQ: {:08x}", x);
259
260 let ints = regs.ints().read();
261
262 if ints.bus_reset() {
263 regs.inte().write_clear(|w| w.set_bus_reset(true));
264 BUS_WAKER.wake();
265 }
266 if ints.dev_resume_from_host() {
267 regs.inte().write_clear(|w| w.set_dev_resume_from_host(true));
268 BUS_WAKER.wake();
269 }
270 if ints.dev_suspend() {
271 regs.inte().write_clear(|w| w.set_dev_suspend(true));
272 BUS_WAKER.wake();
273 }
274 if ints.setup_req() {
275 regs.inte().write_clear(|w| w.set_setup_req(true));
276 EP_OUT_WAKERS[0].wake();
277 }
278
279 if ints.buff_status() {
280 let s = regs.buff_status().read();
281 regs.buff_status().write_value(s);
282
283 for i in 0..EP_COUNT {
284 if s.ep_in(i) {
285 EP_IN_WAKERS[i].wake();
286 }
287 if s.ep_out(i) {
288 EP_OUT_WAKERS[i].wake();
289 }
290 }
291 }
292 }
293}
294
291impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> { 295impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
292 type EndpointOut = Endpoint<'d, T, Out>; 296 type EndpointOut = Endpoint<'d, T, Out>;
293 type EndpointIn = Endpoint<'d, T, In>; 297 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 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::adc::{Adc, Config}; 7use embassy_rp::adc::{Adc, Config, InterruptHandler};
8use embassy_rp::interrupt; 8use embassy_rp::bind_interrupts;
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 ADC_IRQ_FIFO => InterruptHandler;
14});
15
12#[embassy_executor::main] 16#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 17async fn main(_spawner: Spawner) {
14 let p = embassy_rp::init(Default::default()); 18 let p = embassy_rp::init(Default::default());
15 let irq = interrupt::take!(ADC_IRQ_FIFO); 19 let mut adc = Adc::new(p.ADC, Irqs, Config::default());
16 let mut adc = Adc::new(p.ADC, irq, Config::default());
17 20
18 let mut p26 = p.PIN_26; 21 let mut p26 = p.PIN_26;
19 let mut p27 = p.PIN_27; 22 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 @@
4 4
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::i2c::{self, Config}; 7use embassy_rp::bind_interrupts;
8use embassy_rp::interrupt; 8use embassy_rp::i2c::{self, Config, InterruptHandler};
9use embassy_rp::peripherals::I2C1;
9use embassy_time::{Duration, Timer}; 10use embassy_time::{Duration, Timer};
10use embedded_hal_async::i2c::I2c; 11use embedded_hal_async::i2c::I2c;
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
12 13
14bind_interrupts!(struct Irqs {
15 I2C1_IRQ => InterruptHandler<I2C1>;
16});
17
13#[allow(dead_code)] 18#[allow(dead_code)]
14mod mcp23017 { 19mod mcp23017 {
15 pub const ADDR: u8 = 0x20; // default addr 20 pub const ADDR: u8 = 0x20; // default addr
@@ -64,10 +69,9 @@ async fn main(_spawner: Spawner) {
64 69
65 let sda = p.PIN_14; 70 let sda = p.PIN_14;
66 let scl = p.PIN_15; 71 let scl = p.PIN_15;
67 let irq = interrupt::take!(I2C1_IRQ);
68 72
69 info!("set up i2c "); 73 info!("set up i2c ");
70 let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, irq, Config::default()); 74 let mut i2c = i2c::I2c::new_async(p.I2C1, scl, sda, Irqs, Config::default());
71 75
72 use mcp23017::*; 76 use mcp23017::*;
73 77
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 @@
5use defmt::*; 5use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_executor::_export::StaticCell; 7use embassy_executor::_export::StaticCell;
8use embassy_rp::interrupt; 8use embassy_rp::bind_interrupts;
9use embassy_rp::peripherals::UART0; 9use embassy_rp::peripherals::UART0;
10use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config}; 10use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config};
11use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
12use embedded_io::asynch::{Read, Write}; 12use embedded_io::asynch::{Read, Write};
13use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
14 14
15bind_interrupts!(struct Irqs {
16 UART0_IRQ => BufferedInterruptHandler<UART0>;
17});
18
15macro_rules! singleton { 19macro_rules! singleton {
16 ($val:expr) => {{ 20 ($val:expr) => {{
17 type T = impl Sized; 21 type T = impl Sized;
@@ -26,10 +30,9 @@ async fn main(spawner: Spawner) {
26 let p = embassy_rp::init(Default::default()); 30 let p = embassy_rp::init(Default::default());
27 let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0); 31 let (tx_pin, rx_pin, uart) = (p.PIN_0, p.PIN_1, p.UART0);
28 32
29 let irq = interrupt::take!(UART0_IRQ);
30 let tx_buf = &mut singleton!([0u8; 16])[..]; 33 let tx_buf = &mut singleton!([0u8; 16])[..];
31 let rx_buf = &mut singleton!([0u8; 16])[..]; 34 let rx_buf = &mut singleton!([0u8; 16])[..];
32 let uart = BufferedUart::new(uart, irq, tx_pin, rx_pin, tx_buf, rx_buf, Config::default()); 35 let uart = BufferedUart::new(uart, Irqs, tx_pin, rx_pin, tx_buf, rx_buf, Config::default());
33 let (rx, mut tx) = uart.split(); 36 let (rx, mut tx) = uart.split();
34 37
35 unwrap!(spawner.spawn(reader(rx))); 38 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 @@
7 7
8use defmt::*; 8use defmt::*;
9use embassy_executor::Spawner; 9use embassy_executor::Spawner;
10use embassy_rp::interrupt; 10use embassy_rp::bind_interrupts;
11use embassy_rp::peripherals::UART1; 11use embassy_rp::peripherals::UART1;
12use embassy_rp::uart::{Async, Config, UartRx, UartTx}; 12use embassy_rp::uart::{Async, Config, InterruptHandler, UartRx, UartTx};
13use embassy_time::{Duration, Timer}; 13use embassy_time::{Duration, Timer};
14use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
15 15
16bind_interrupts!(struct Irqs {
17 UART1_IRQ => InterruptHandler<UART1>;
18});
19
16#[embassy_executor::main] 20#[embassy_executor::main]
17async fn main(spawner: Spawner) { 21async fn main(spawner: Spawner) {
18 let p = embassy_rp::init(Default::default()); 22 let p = embassy_rp::init(Default::default());
19 23
20 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default()); 24 let mut uart_tx = UartTx::new(p.UART0, p.PIN_0, p.DMA_CH0, Config::default());
21 let uart_rx = UartRx::new( 25 let uart_rx = UartRx::new(p.UART1, p.PIN_5, Irqs, p.DMA_CH1, Config::default());
22 p.UART1,
23 p.PIN_5,
24 interrupt::take!(UART1_IRQ),
25 p.DMA_CH1,
26 Config::default(),
27 );
28 26
29 unwrap!(spawner.spawn(reader(uart_rx))); 27 unwrap!(spawner.spawn(reader(uart_rx)));
30 28
diff --git a/examples/rp/src/bin/usb_ethernet.rs b/examples/rp/src/bin/usb_ethernet.rs
index 431db63eb..38ff1620d 100644
--- a/examples/rp/src/bin/usb_ethernet.rs
+++ b/examples/rp/src/bin/usb_ethernet.rs
@@ -6,8 +6,9 @@ use defmt::*;
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_net::tcp::TcpSocket; 7use embassy_net::tcp::TcpSocket;
8use embassy_net::{Stack, StackResources}; 8use embassy_net::{Stack, StackResources};
9use embassy_rp::usb::Driver; 9use embassy_rp::peripherals::USB;
10use embassy_rp::{interrupt, peripherals}; 10use embassy_rp::usb::{Driver, InterruptHandler};
11use embassy_rp::{bind_interrupts, peripherals};
11use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState}; 12use embassy_usb::class::cdc_ncm::embassy_net::{Device, Runner, State as NetState};
12use embassy_usb::class::cdc_ncm::{CdcNcmClass, State}; 13use embassy_usb::class::cdc_ncm::{CdcNcmClass, State};
13use embassy_usb::{Builder, Config, UsbDevice}; 14use embassy_usb::{Builder, Config, UsbDevice};
@@ -15,6 +16,10 @@ use embedded_io::asynch::Write;
15use static_cell::StaticCell; 16use static_cell::StaticCell;
16use {defmt_rtt as _, panic_probe as _}; 17use {defmt_rtt as _, panic_probe as _};
17 18
19bind_interrupts!(struct Irqs {
20 USBCTRL_IRQ => InterruptHandler<USB>;
21});
22
18type MyDriver = Driver<'static, peripherals::USB>; 23type MyDriver = Driver<'static, peripherals::USB>;
19 24
20macro_rules! singleton { 25macro_rules! singleton {
@@ -48,8 +53,7 @@ async fn main(spawner: Spawner) {
48 let p = embassy_rp::init(Default::default()); 53 let p = embassy_rp::init(Default::default());
49 54
50 // Create the driver, from the HAL. 55 // Create the driver, from the HAL.
51 let irq = interrupt::take!(USBCTRL_IRQ); 56 let driver = Driver::new(p.USB, Irqs);
52 let driver = Driver::new(p.USB, irq);
53 57
54 // Create embassy-usb Config 58 // Create embassy-usb Config
55 let mut config = Config::new(0xc0de, 0xcafe); 59 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 @@
3#![feature(type_alias_impl_trait)] 3#![feature(type_alias_impl_trait)]
4 4
5use embassy_executor::Spawner; 5use embassy_executor::Spawner;
6use embassy_rp::interrupt; 6use embassy_rp::bind_interrupts;
7use embassy_rp::peripherals::USB; 7use embassy_rp::peripherals::USB;
8use embassy_rp::usb::Driver; 8use embassy_rp::usb::{Driver, InterruptHandler};
9use embassy_time::{Duration, Timer}; 9use embassy_time::{Duration, Timer};
10use {defmt_rtt as _, panic_probe as _}; 10use {defmt_rtt as _, panic_probe as _};
11 11
12bind_interrupts!(struct Irqs {
13 USBCTRL_IRQ => InterruptHandler<USB>;
14});
15
12#[embassy_executor::task] 16#[embassy_executor::task]
13async fn logger_task(driver: Driver<'static, USB>) { 17async fn logger_task(driver: Driver<'static, USB>) {
14 embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver); 18 embassy_usb_logger::run!(1024, log::LevelFilter::Info, driver);
@@ -17,8 +21,7 @@ async fn logger_task(driver: Driver<'static, USB>) {
17#[embassy_executor::main] 21#[embassy_executor::main]
18async fn main(spawner: Spawner) { 22async fn main(spawner: Spawner) {
19 let p = embassy_rp::init(Default::default()); 23 let p = embassy_rp::init(Default::default());
20 let irq = interrupt::take!(USBCTRL_IRQ); 24 let driver = Driver::new(p.USB, Irqs);
21 let driver = Driver::new(p.USB, irq);
22 spawner.spawn(logger_task(driver)).unwrap(); 25 spawner.spawn(logger_task(driver)).unwrap();
23 26
24 let mut counter = 0; 27 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 @@
5use defmt::{info, panic}; 5use defmt::{info, panic};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_futures::join::join; 7use embassy_futures::join::join;
8use embassy_rp::interrupt; 8use embassy_rp::bind_interrupts;
9use embassy_rp::usb::{Driver, Instance}; 9use embassy_rp::peripherals::USB;
10use embassy_rp::usb::{Driver, Instance, InterruptHandler};
10use embassy_usb::class::cdc_acm::{CdcAcmClass, State}; 11use embassy_usb::class::cdc_acm::{CdcAcmClass, State};
11use embassy_usb::driver::EndpointError; 12use embassy_usb::driver::EndpointError;
12use embassy_usb::{Builder, Config}; 13use embassy_usb::{Builder, Config};
13use {defmt_rtt as _, panic_probe as _}; 14use {defmt_rtt as _, panic_probe as _};
14 15
16bind_interrupts!(struct Irqs {
17 USBCTRL_IRQ => InterruptHandler<USB>;
18});
19
15#[embassy_executor::main] 20#[embassy_executor::main]
16async fn main(_spawner: Spawner) { 21async fn main(_spawner: Spawner) {
17 info!("Hello there!"); 22 info!("Hello there!");
@@ -19,8 +24,7 @@ async fn main(_spawner: Spawner) {
19 let p = embassy_rp::init(Default::default()); 24 let p = embassy_rp::init(Default::default());
20 25
21 // Create the driver, from the HAL. 26 // Create the driver, from the HAL.
22 let irq = interrupt::take!(USBCTRL_IRQ); 27 let driver = Driver::new(p.USB, Irqs);
23 let driver = Driver::new(p.USB, irq);
24 28
25 // Create embassy-usb Config 29 // Create embassy-usb Config
26 let mut config = Config::new(0xc0de, 0xcafe); 30 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 @@
4 4
5use defmt::{assert_eq, panic, *}; 5use defmt::{assert_eq, panic, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::bind_interrupts;
7use embassy_rp::gpio::{Level, Output}; 8use embassy_rp::gpio::{Level, Output};
8use embassy_rp::interrupt; 9use embassy_rp::peripherals::UART0;
9use embassy_rp::uart::{BufferedUart, BufferedUartRx, Config, Error, Instance, Parity}; 10use embassy_rp::uart::{BufferedInterruptHandler, BufferedUart, BufferedUartRx, Config, Error, Instance, Parity};
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
11use embedded_io::asynch::{Read, ReadExactError, Write}; 12use embedded_io::asynch::{Read, ReadExactError, Write};
12use {defmt_rtt as _, panic_probe as _}; 13use {defmt_rtt as _, panic_probe as _};
13 14
15bind_interrupts!(struct Irqs {
16 UART0_IRQ => BufferedInterruptHandler<UART0>;
17});
18
14async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> { 19async fn read<const N: usize>(uart: &mut BufferedUart<'_, impl Instance>) -> Result<[u8; N], Error> {
15 let mut buf = [255; N]; 20 let mut buf = [255; N];
16 match uart.read_exact(&mut buf).await { 21 match uart.read_exact(&mut buf).await {
@@ -60,13 +65,12 @@ async fn main(_spawner: Spawner) {
60 info!("Hello World!"); 65 info!("Hello World!");
61 66
62 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); 67 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
63 let mut irq = interrupt::take!(UART0_IRQ);
64 68
65 { 69 {
66 let config = Config::default(); 70 let config = Config::default();
67 let tx_buf = &mut [0u8; 16]; 71 let tx_buf = &mut [0u8; 16];
68 let rx_buf = &mut [0u8; 16]; 72 let rx_buf = &mut [0u8; 16];
69 let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); 73 let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
70 74
71 // Make sure we send more bytes than fits in the FIFO, to test the actual 75 // Make sure we send more bytes than fits in the FIFO, to test the actual
72 // bufferedUart. 76 // bufferedUart.
@@ -86,7 +90,7 @@ async fn main(_spawner: Spawner) {
86 let config = Config::default(); 90 let config = Config::default();
87 let tx_buf = &mut [0u8; 16]; 91 let tx_buf = &mut [0u8; 16];
88 let rx_buf = &mut [0u8; 16]; 92 let rx_buf = &mut [0u8; 16];
89 let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); 93 let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
90 94
91 // Make sure we send more bytes than fits in the FIFO, to test the actual 95 // Make sure we send more bytes than fits in the FIFO, to test the actual
92 // bufferedUart. 96 // bufferedUart.
@@ -121,7 +125,7 @@ async fn main(_spawner: Spawner) {
121 config.baudrate = 1000; 125 config.baudrate = 1000;
122 let tx_buf = &mut [0u8; 16]; 126 let tx_buf = &mut [0u8; 16];
123 let rx_buf = &mut [0u8; 16]; 127 let rx_buf = &mut [0u8; 16];
124 let mut uart = BufferedUart::new(&mut uart, &mut irq, &mut tx, &mut rx, tx_buf, rx_buf, config); 128 let mut uart = BufferedUart::new(&mut uart, Irqs, &mut tx, &mut rx, tx_buf, rx_buf, config);
125 129
126 // break on empty buffer 130 // break on empty buffer
127 uart.send_break(20).await; 131 uart.send_break(20).await;
@@ -155,7 +159,7 @@ async fn main(_spawner: Spawner) {
155 config.baudrate = 1000; 159 config.baudrate = 1000;
156 config.parity = Parity::ParityEven; 160 config.parity = Parity::ParityEven;
157 let rx_buf = &mut [0u8; 16]; 161 let rx_buf = &mut [0u8; 16];
158 let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config); 162 let mut uart = BufferedUartRx::new(&mut uart, Irqs, &mut rx, rx_buf, config);
159 163
160 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) { 164 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
161 send(pin, v, Some(parity != 0)).await; 165 send(pin, v, Some(parity != 0)).await;
@@ -202,7 +206,7 @@ async fn main(_spawner: Spawner) {
202 let mut config = Config::default(); 206 let mut config = Config::default();
203 config.baudrate = 1000; 207 config.baudrate = 1000;
204 let rx_buf = &mut [0u8; 16]; 208 let rx_buf = &mut [0u8; 16];
205 let mut uart = BufferedUartRx::new(&mut uart, &mut irq, &mut rx, rx_buf, config); 209 let mut uart = BufferedUartRx::new(&mut uart, Irqs, &mut rx, rx_buf, config);
206 210
207 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { 211 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
208 if good { 212 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 @@
4 4
5use defmt::{assert_eq, *}; 5use defmt::{assert_eq, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::bind_interrupts;
7use embassy_rp::gpio::{Level, Output}; 8use embassy_rp::gpio::{Level, Output};
8use embassy_rp::interrupt; 9use embassy_rp::peripherals::UART0;
9use embassy_rp::uart::{Async, Config, Error, Instance, Parity, Uart, UartRx}; 10use embassy_rp::uart::{Async, Config, Error, Instance, InterruptHandler, Parity, Uart, UartRx};
10use embassy_time::{Duration, Timer}; 11use embassy_time::{Duration, Timer};
11use {defmt_rtt as _, panic_probe as _}; 12use {defmt_rtt as _, panic_probe as _};
12 13
14bind_interrupts!(struct Irqs {
15 UART0_IRQ => InterruptHandler<UART0>;
16});
17
13async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> { 18async fn read<const N: usize>(uart: &mut Uart<'_, impl Instance, Async>) -> Result<[u8; N], Error> {
14 let mut buf = [255; N]; 19 let mut buf = [255; N];
15 uart.read(&mut buf).await?; 20 uart.read(&mut buf).await?;
@@ -51,7 +56,6 @@ async fn main(_spawner: Spawner) {
51 info!("Hello World!"); 56 info!("Hello World!");
52 57
53 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0); 58 let (mut tx, mut rx, mut uart) = (p.PIN_0, p.PIN_1, p.UART0);
54 let mut irq = interrupt::take!(UART0_IRQ);
55 59
56 // We can't send too many bytes, they have to fit in the FIFO. 60 // We can't send too many bytes, they have to fit in the FIFO.
57 // This is because we aren't sending+receiving at the same time. 61 // This is because we aren't sending+receiving at the same time.
@@ -61,7 +65,7 @@ async fn main(_spawner: Spawner) {
61 &mut uart, 65 &mut uart,
62 &mut tx, 66 &mut tx,
63 &mut rx, 67 &mut rx,
64 &mut irq, 68 Irqs,
65 &mut p.DMA_CH0, 69 &mut p.DMA_CH0,
66 &mut p.DMA_CH1, 70 &mut p.DMA_CH1,
67 config, 71 config,
@@ -82,7 +86,7 @@ async fn main(_spawner: Spawner) {
82 &mut uart, 86 &mut uart,
83 &mut tx, 87 &mut tx,
84 &mut rx, 88 &mut rx,
85 &mut irq, 89 Irqs,
86 &mut p.DMA_CH0, 90 &mut p.DMA_CH0,
87 &mut p.DMA_CH1, 91 &mut p.DMA_CH1,
88 config, 92 config,
@@ -111,7 +115,7 @@ async fn main(_spawner: Spawner) {
111 &mut uart, 115 &mut uart,
112 &mut tx, 116 &mut tx,
113 &mut rx, 117 &mut rx,
114 &mut irq, 118 Irqs,
115 &mut p.DMA_CH0, 119 &mut p.DMA_CH0,
116 &mut p.DMA_CH1, 120 &mut p.DMA_CH1,
117 config, 121 config,
@@ -154,7 +158,7 @@ async fn main(_spawner: Spawner) {
154 let mut config = Config::default(); 158 let mut config = Config::default();
155 config.baudrate = 1000; 159 config.baudrate = 1000;
156 config.parity = Parity::ParityEven; 160 config.parity = Parity::ParityEven;
157 let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config); 161 let mut uart = UartRx::new(&mut uart, &mut rx, Irqs, &mut p.DMA_CH0, config);
158 162
159 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) { 163 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, parity: u32) {
160 send(pin, v, Some(parity != 0)).await; 164 send(pin, v, Some(parity != 0)).await;
@@ -199,7 +203,7 @@ async fn main(_spawner: Spawner) {
199 // choose a very slow baud rate to make tests reliable even with O0 203 // choose a very slow baud rate to make tests reliable even with O0
200 let mut config = Config::default(); 204 let mut config = Config::default();
201 config.baudrate = 1000; 205 config.baudrate = 1000;
202 let mut uart = UartRx::new(&mut uart, &mut rx, &mut irq, &mut p.DMA_CH0, config); 206 let mut uart = UartRx::new(&mut uart, &mut rx, Irqs, &mut p.DMA_CH0, config);
203 207
204 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) { 208 async fn chr(pin: &mut Output<'_, impl embassy_rp::gpio::Pin>, v: u8, good: bool) {
205 if good { 209 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 @@
4 4
5use defmt::{assert_eq, *}; 5use defmt::{assert_eq, *};
6use embassy_executor::Spawner; 6use embassy_executor::Spawner;
7use embassy_rp::interrupt; 7use embassy_rp::bind_interrupts;
8use embassy_rp::uart::{Config, Uart}; 8use embassy_rp::peripherals::UART0;
9use embassy_rp::uart::{BufferedInterruptHandler, Config, Uart};
9use embedded_io::asynch::{Read, Write}; 10use embedded_io::asynch::{Read, Write};
10use {defmt_rtt as _, panic_probe as _}; 11use {defmt_rtt as _, panic_probe as _};
11 12
13bind_interrupts!(struct Irqs {
14 UART0_IRQ => BufferedInterruptHandler<UART0>;
15});
16
12#[embassy_executor::main] 17#[embassy_executor::main]
13async fn main(_spawner: Spawner) { 18async fn main(_spawner: Spawner) {
14 let p = embassy_rp::init(Default::default()); 19 let p = embassy_rp::init(Default::default());
@@ -29,11 +34,10 @@ async fn main(_spawner: Spawner) {
29 uart.blocking_read(&mut buf).unwrap(); 34 uart.blocking_read(&mut buf).unwrap();
30 assert_eq!(buf, data); 35 assert_eq!(buf, data);
31 36
32 let irq = interrupt::take!(UART0_IRQ);
33 let tx_buf = &mut [0u8; 16]; 37 let tx_buf = &mut [0u8; 16];
34 let rx_buf = &mut [0u8; 16]; 38 let rx_buf = &mut [0u8; 16];
35 39
36 let mut uart = uart.into_buffered(irq, tx_buf, rx_buf); 40 let mut uart = uart.into_buffered(Irqs, tx_buf, rx_buf);
37 41
38 // Make sure we send more bytes than fits in the FIFO, to test the actual 42 // Make sure we send more bytes than fits in the FIFO, to test the actual
39 // bufferedUart. 43 // bufferedUart.