rp: remove take!, add bind_interrupts!
This commit is contained in:
		@@ -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<P = ADC> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = interrupt::ADC_IRQ_FIFO> + 'd,
 | 
			
		||||
        _irq: impl Binding<ADC_IRQ_FIFO, InterruptHandler>,
 | 
			
		||||
        _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<ADC_IRQ_FIFO> for InterruptHandler {
 | 
			
		||||
    unsafe fn on_interrupt() {
 | 
			
		||||
        let r = Adc::regs();
 | 
			
		||||
        r.inte().write(|w| w.set_fifo(false));
 | 
			
		||||
        WAKER.wake();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl_pin!(PIN_26, 0);
 | 
			
		||||
impl_pin!(PIN_27, 1);
 | 
			
		||||
impl_pin!(PIN_28, 2);
 | 
			
		||||
 
 | 
			
		||||
@@ -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<P = T> + 'd,
 | 
			
		||||
        scl: impl Peripheral<P = impl SclPin<T>> + 'd,
 | 
			
		||||
        sda: impl Peripheral<P = impl SdaPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
 | 
			
		||||
        config: Config,
 | 
			
		||||
    ) -> 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<T: Instance> {
 | 
			
		||||
    _uart: PhantomData<T>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
 | 
			
		||||
    // Mask interrupts and wake any task waiting for this interrupt
 | 
			
		||||
    unsafe fn on_interrupt() {
 | 
			
		||||
        let i2c = T::regs();
 | 
			
		||||
        i2c.ic_intr_mask().write_value(pac::i2c::regs::IcIntrMask::default());
 | 
			
		||||
 | 
			
		||||
        T::waker().wake();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'d, T: Instance + 'd, M: Mode> I2c<'d, T, M> {
 | 
			
		||||
    fn new_inner(
 | 
			
		||||
        _peri: impl Peripheral<P = T> + 'd,
 | 
			
		||||
 
 | 
			
		||||
@@ -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 {}
 | 
			
		||||
            )*
 | 
			
		||||
        )*
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
    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::<T>);
 | 
			
		||||
    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<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + '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::<T>(irq, tx_buffer, rx_buffer);
 | 
			
		||||
@@ -109,7 +108,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
 | 
			
		||||
 | 
			
		||||
    pub fn new_with_rtscts(
 | 
			
		||||
        _uart: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
 | 
			
		||||
@@ -118,7 +117,7 @@ impl<'d, T: Instance> BufferedUart<'d, T> {
 | 
			
		||||
        rx_buffer: &'d mut [u8],
 | 
			
		||||
        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<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        rx_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::<T>(irq, &mut [], rx_buffer);
 | 
			
		||||
@@ -178,13 +177,13 @@ impl<'d, T: Instance> BufferedUartRx<'d, T> {
 | 
			
		||||
 | 
			
		||||
    pub fn new_with_rts(
 | 
			
		||||
        _uart: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        rts: impl Peripheral<P = impl RtsPin<T>> + '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::<T>(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<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        tx_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::<T>(irq, tx_buffer, &mut []);
 | 
			
		||||
@@ -327,13 +326,13 @@ impl<'d, T: Instance> BufferedUartTx<'d, T> {
 | 
			
		||||
 | 
			
		||||
    pub fn new_with_cts(
 | 
			
		||||
        _uart: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        cts: impl Peripheral<P = impl CtsPin<T>> + '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::<T>(irq, tx_buffer, &mut []);
 | 
			
		||||
@@ -482,97 +481,107 @@ impl<'d, T: Instance> Drop for BufferedUartTx<'d, T> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub(crate) unsafe fn on_interrupt<T: Instance>(_: *mut ()) {
 | 
			
		||||
    let r = T::regs();
 | 
			
		||||
    let s = T::buffered_state();
 | 
			
		||||
pub struct BufferedInterruptHandler<T: Instance> {
 | 
			
		||||
    _uart: PhantomData<T>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
    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<T: Instance> interrupt::Handler<T::Interrupt> for BufferedInterruptHandler<T> {
 | 
			
		||||
    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.
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        tx_buffer: &'d mut [u8],
 | 
			
		||||
    ) -> BufferedUartTx<'d, T> {
 | 
			
		||||
        into_ref!(irq);
 | 
			
		||||
 | 
			
		||||
        buffered::init_buffers::<T>(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<P = T> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
 | 
			
		||||
        rx_dma: impl Peripheral<P = impl Channel> + 'd,
 | 
			
		||||
        config: Config,
 | 
			
		||||
    ) -> Self {
 | 
			
		||||
        into_ref!(rx, irq, rx_dma);
 | 
			
		||||
        into_ref!(rx, rx_dma);
 | 
			
		||||
        Uart::<T, M>::init(None, Some(rx.map_into()), None, None, config);
 | 
			
		||||
        Self::new_inner(Some(irq), Some(rx_dma.map_into()))
 | 
			
		||||
        Self::new_inner(true, Some(rx_dma.map_into()))
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn new_inner(irq: Option<PeripheralRef<'d, T::Interrupt>>, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> Self {
 | 
			
		||||
        debug_assert_eq!(irq.is_some(), rx_dma.is_some());
 | 
			
		||||
        if let Some(irq) = irq {
 | 
			
		||||
    fn new_inner(has_irq: bool, rx_dma: Option<PeripheralRef<'d, AnyChannel>>) -> 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::<T>);
 | 
			
		||||
            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::<T, Blocking>::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<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        rx_buffer: &'d mut [u8],
 | 
			
		||||
    ) -> BufferedUartRx<'d, T> {
 | 
			
		||||
        into_ref!(irq);
 | 
			
		||||
 | 
			
		||||
        buffered::init_buffers::<T>(irq, &mut [], rx_buffer);
 | 
			
		||||
 | 
			
		||||
        BufferedUartRx { phantom: PhantomData }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsafe fn on_interrupt<T: Instance>(_: *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<T: Instance> {
 | 
			
		||||
    _uart: PhantomData<T>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
 | 
			
		||||
    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<P = T::Interrupt> + 'd,
 | 
			
		||||
        irq: impl Binding<T::Interrupt, BufferedInterruptHandler<T>>,
 | 
			
		||||
        tx_buffer: &'d mut [u8],
 | 
			
		||||
        rx_buffer: &'d mut [u8],
 | 
			
		||||
    ) -> BufferedUart<'d, T> {
 | 
			
		||||
        into_ref!(irq);
 | 
			
		||||
 | 
			
		||||
        buffered::init_buffers::<T>(irq, tx_buffer, rx_buffer);
 | 
			
		||||
 | 
			
		||||
        BufferedUart {
 | 
			
		||||
@@ -478,19 +497,19 @@ impl<'d, T: Instance> Uart<'d, T, Async> {
 | 
			
		||||
        uart: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
 | 
			
		||||
        tx_dma: impl Peripheral<P = impl Channel> + 'd,
 | 
			
		||||
        rx_dma: impl Peripheral<P = impl Channel> + '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<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
 | 
			
		||||
        cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        _irq: impl Binding<T::Interrupt, InterruptHandler<T>>,
 | 
			
		||||
        tx_dma: impl Peripheral<P = impl Channel> + 'd,
 | 
			
		||||
        rx_dma: impl Peripheral<P = impl Channel> + '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<PeripheralRef<'d, AnyPin>>,
 | 
			
		||||
        mut cts: Option<PeripheralRef<'d, AnyPin>>,
 | 
			
		||||
        irq: Option<PeripheralRef<'d, T::Interrupt>>,
 | 
			
		||||
        has_irq: bool,
 | 
			
		||||
        tx_dma: Option<PeripheralRef<'d, AnyChannel>>,
 | 
			
		||||
        rx_dma: Option<PeripheralRef<'d, AnyChannel>>,
 | 
			
		||||
        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),
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<P = T> + 'd, irq: impl Peripheral<P = T::Interrupt> + 'd) -> Self {
 | 
			
		||||
        into_ref!(irq);
 | 
			
		||||
        irq.set_handler(Self::on_interrupt);
 | 
			
		||||
        irq.unpend();
 | 
			
		||||
        irq.enable();
 | 
			
		||||
    pub fn new(_usb: impl Peripheral<P = T> + 'd, _irq: impl Binding<T::Interrupt, InterruptHandler<T>>) -> 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<D: Dir>(
 | 
			
		||||
        &mut self,
 | 
			
		||||
        ep_type: EndpointType,
 | 
			
		||||
@@ -288,6 +247,51 @@ impl<'d, T: Instance> Driver<'d, T> {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
pub struct InterruptHandler<T: Instance> {
 | 
			
		||||
    _uart: PhantomData<T>,
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<T: Instance> interrupt::Handler<T::Interrupt> for InterruptHandler<T> {
 | 
			
		||||
    unsafe fn on_interrupt() {
 | 
			
		||||
        let regs = T::regs();
 | 
			
		||||
        //let x = regs.istr().read().0;
 | 
			
		||||
        //trace!("USB IRQ: {:08x}", x);
 | 
			
		||||
 | 
			
		||||
        let ints = regs.ints().read();
 | 
			
		||||
 | 
			
		||||
        if ints.bus_reset() {
 | 
			
		||||
            regs.inte().write_clear(|w| w.set_bus_reset(true));
 | 
			
		||||
            BUS_WAKER.wake();
 | 
			
		||||
        }
 | 
			
		||||
        if ints.dev_resume_from_host() {
 | 
			
		||||
            regs.inte().write_clear(|w| w.set_dev_resume_from_host(true));
 | 
			
		||||
            BUS_WAKER.wake();
 | 
			
		||||
        }
 | 
			
		||||
        if ints.dev_suspend() {
 | 
			
		||||
            regs.inte().write_clear(|w| w.set_dev_suspend(true));
 | 
			
		||||
            BUS_WAKER.wake();
 | 
			
		||||
        }
 | 
			
		||||
        if ints.setup_req() {
 | 
			
		||||
            regs.inte().write_clear(|w| w.set_setup_req(true));
 | 
			
		||||
            EP_OUT_WAKERS[0].wake();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if ints.buff_status() {
 | 
			
		||||
            let s = regs.buff_status().read();
 | 
			
		||||
            regs.buff_status().write_value(s);
 | 
			
		||||
 | 
			
		||||
            for i in 0..EP_COUNT {
 | 
			
		||||
                if s.ep_in(i) {
 | 
			
		||||
                    EP_IN_WAKERS[i].wake();
 | 
			
		||||
                }
 | 
			
		||||
                if s.ep_out(i) {
 | 
			
		||||
                    EP_OUT_WAKERS[i].wake();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
impl<'d, T: Instance> driver::Driver<'d> for Driver<'d, T> {
 | 
			
		||||
    type EndpointOut = Endpoint<'d, T, Out>;
 | 
			
		||||
    type EndpointIn = Endpoint<'d, T, In>;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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<I2C1>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
#[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::*;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<UART0>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
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)));
 | 
			
		||||
 
 | 
			
		||||
@@ -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<UART1>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
#[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)));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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<USB>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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<USB>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
#[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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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<USB>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
#[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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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<UART0>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
async fn read<const N: usize>(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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<UART0>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
async fn read<const N: usize>(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 {
 | 
			
		||||
 
 | 
			
		||||
@@ -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<UART0>;
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
#[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.
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user