Fix interrupt handling so it is similar to before the rework, and fix examples
This commit is contained in:
		@@ -43,9 +43,9 @@ pub struct BufferedUartRx<'d, T: BasicInstance> {
 | 
			
		||||
impl<'d, T: BasicInstance> BufferedUart<'d, T> {
 | 
			
		||||
    pub fn new(
 | 
			
		||||
        peri: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        tx_buffer: &'d mut [u8],
 | 
			
		||||
        rx_buffer: &'d mut [u8],
 | 
			
		||||
        config: Config,
 | 
			
		||||
@@ -53,14 +53,14 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
 | 
			
		||||
        T::enable();
 | 
			
		||||
        T::reset();
 | 
			
		||||
 | 
			
		||||
        Self::new_inner(peri, rx, tx, irq, tx_buffer, rx_buffer, config)
 | 
			
		||||
        Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn new_with_rtscts(
 | 
			
		||||
        peri: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        rts: impl Peripheral<P = impl RtsPin<T>> + 'd,
 | 
			
		||||
        cts: impl Peripheral<P = impl CtsPin<T>> + 'd,
 | 
			
		||||
        tx_buffer: &'d mut [u8],
 | 
			
		||||
@@ -81,15 +81,15 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Self::new_inner(peri, rx, tx, irq, tx_buffer, rx_buffer, config)
 | 
			
		||||
        Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    #[cfg(not(usart_v1))]
 | 
			
		||||
    pub fn new_with_de(
 | 
			
		||||
        peri: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        de: impl Peripheral<P = impl DePin<T>> + 'd,
 | 
			
		||||
        tx_buffer: &'d mut [u8],
 | 
			
		||||
        rx_buffer: &'d mut [u8],
 | 
			
		||||
@@ -107,14 +107,14 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Self::new_inner(peri, rx, tx, irq, tx_buffer, rx_buffer, config)
 | 
			
		||||
        Self::new_inner(peri, irq, rx, tx, tx_buffer, rx_buffer, config)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn new_inner(
 | 
			
		||||
        _peri: impl Peripheral<P = T> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        rx: impl Peripheral<P = impl RxPin<T>> + 'd,
 | 
			
		||||
        tx: impl Peripheral<P = impl TxPin<T>> + 'd,
 | 
			
		||||
        irq: impl Peripheral<P = T::Interrupt> + 'd,
 | 
			
		||||
        tx_buffer: &'d mut [u8],
 | 
			
		||||
        rx_buffer: &'d mut [u8],
 | 
			
		||||
        config: Config,
 | 
			
		||||
@@ -155,8 +155,8 @@ impl<'d, T: BasicInstance> BufferedUart<'d, T> {
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    pub fn split(self) -> (BufferedUartRx<'d, T>, BufferedUartTx<'d, T>) {
 | 
			
		||||
        (self.rx, self.tx)
 | 
			
		||||
    pub fn split(self) -> (BufferedUartTx<'d, T>, BufferedUartRx<'d, T>) {
 | 
			
		||||
        (self.tx, self.rx)
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -165,85 +165,46 @@ impl<'d, T: BasicInstance> BufferedUartRx<'d, T> {
 | 
			
		||||
        poll_fn(move |cx| {
 | 
			
		||||
            let state = T::buffered_state();
 | 
			
		||||
            let mut rx_reader = unsafe { state.rx_buf.reader() };
 | 
			
		||||
            let n = rx_reader.pop(|data| {
 | 
			
		||||
                let n = data.len().min(buf.len());
 | 
			
		||||
                buf[..n].copy_from_slice(&data[..n]);
 | 
			
		||||
                n
 | 
			
		||||
            });
 | 
			
		||||
            if n == 0 {
 | 
			
		||||
                state.rx_waker.register(cx.waker());
 | 
			
		||||
                return Poll::Pending;
 | 
			
		||||
            let data = rx_reader.pop_slice();
 | 
			
		||||
 | 
			
		||||
            if !data.is_empty() {
 | 
			
		||||
                let len = data.len().min(buf.len());
 | 
			
		||||
                buf[..len].copy_from_slice(&data[..len]);
 | 
			
		||||
 | 
			
		||||
                let do_pend = state.rx_buf.is_full();
 | 
			
		||||
                rx_reader.pop_done(len);
 | 
			
		||||
 | 
			
		||||
                if do_pend {
 | 
			
		||||
                    unsafe { T::Interrupt::steal().pend() };
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            // FIXME:
 | 
			
		||||
            // (Re-)Enable the interrupt to receive more data in case it was
 | 
			
		||||
            // disabled because the buffer was full.
 | 
			
		||||
            // let regs = T::regs();
 | 
			
		||||
            // unsafe {
 | 
			
		||||
            //     regs.uartimsc().write_set(|w| {
 | 
			
		||||
            //         w.set_rxim(true);
 | 
			
		||||
            //         w.set_rtim(true);
 | 
			
		||||
            //     });
 | 
			
		||||
            // }
 | 
			
		||||
                return Poll::Ready(Ok(len));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Poll::Ready(Ok(n))
 | 
			
		||||
            state.rx_waker.register(cx.waker());
 | 
			
		||||
            Poll::Pending
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
 | 
			
		||||
        // poll_fn(move |cx| {
 | 
			
		||||
        //     let state = T::buffered_state();
 | 
			
		||||
 | 
			
		||||
        //     let mut do_pend = false;
 | 
			
		||||
        //     compiler_fence(Ordering::SeqCst);
 | 
			
		||||
 | 
			
		||||
        //     // We have data ready in buffer? Return it.
 | 
			
		||||
        //     let data = state.rx_buf.pop_buf();
 | 
			
		||||
        //     if !data.is_empty() {
 | 
			
		||||
        //         let len = data.len().min(buf.len());
 | 
			
		||||
        //         buf[..len].copy_from_slice(&data[..len]);
 | 
			
		||||
 | 
			
		||||
        //         if state.rx_buf.is_full() {
 | 
			
		||||
        //             do_pend = true;
 | 
			
		||||
        //         }
 | 
			
		||||
        //         state.rx_buf.pop(len);
 | 
			
		||||
 | 
			
		||||
        //         return Poll::Ready(Ok(len));
 | 
			
		||||
        //     }
 | 
			
		||||
 | 
			
		||||
        //     state.rx_waker.register(cx.waker());
 | 
			
		||||
 | 
			
		||||
        //     if do_pend {
 | 
			
		||||
        //         inner.pend();
 | 
			
		||||
        //     }
 | 
			
		||||
 | 
			
		||||
        //     Poll::Pending
 | 
			
		||||
        // })
 | 
			
		||||
        // .await
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fn blocking_read(&self, buf: &mut [u8]) -> Result<usize, Error> {
 | 
			
		||||
        loop {
 | 
			
		||||
            let state = T::buffered_state();
 | 
			
		||||
            let mut rx_reader = unsafe { state.rx_buf.reader() };
 | 
			
		||||
            let n = rx_reader.pop(|data| {
 | 
			
		||||
                let n = data.len().min(buf.len());
 | 
			
		||||
                buf[..n].copy_from_slice(&data[..n]);
 | 
			
		||||
                n
 | 
			
		||||
            });
 | 
			
		||||
            let data = rx_reader.pop_slice();
 | 
			
		||||
 | 
			
		||||
            if n > 0 {
 | 
			
		||||
                // FIXME:
 | 
			
		||||
                // (Re-)Enable the interrupt to receive more data in case it was
 | 
			
		||||
                // disabled because the buffer was full.
 | 
			
		||||
                // let regs = T::regs();
 | 
			
		||||
                // unsafe {
 | 
			
		||||
                //     regs.uartimsc().write_set(|w| {
 | 
			
		||||
                //         w.set_rxim(true);
 | 
			
		||||
                //         w.set_rtim(true);
 | 
			
		||||
                //     });
 | 
			
		||||
                // }
 | 
			
		||||
            if !data.is_empty() {
 | 
			
		||||
                let len = data.len().min(buf.len());
 | 
			
		||||
                buf[..len].copy_from_slice(&data[..len]);
 | 
			
		||||
 | 
			
		||||
                return Ok(n);
 | 
			
		||||
                let do_pend = state.rx_buf.is_full();
 | 
			
		||||
                rx_reader.pop_done(len);
 | 
			
		||||
 | 
			
		||||
                if do_pend {
 | 
			
		||||
                    unsafe { T::Interrupt::steal().pend() };
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return Ok(len);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -279,22 +240,23 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
 | 
			
		||||
    async fn write(&self, buf: &[u8]) -> Result<usize, Error> {
 | 
			
		||||
        poll_fn(move |cx| {
 | 
			
		||||
            let state = T::buffered_state();
 | 
			
		||||
            let empty = state.tx_buf.is_empty();
 | 
			
		||||
 | 
			
		||||
            let mut tx_writer = unsafe { state.tx_buf.writer() };
 | 
			
		||||
            let n = tx_writer.push(|data| {
 | 
			
		||||
                let n = data.len().min(buf.len());
 | 
			
		||||
                data[..n].copy_from_slice(&buf[..n]);
 | 
			
		||||
                n
 | 
			
		||||
            });
 | 
			
		||||
            if n == 0 {
 | 
			
		||||
            let data = tx_writer.push_slice();
 | 
			
		||||
            if data.is_empty() {
 | 
			
		||||
                state.tx_waker.register(cx.waker());
 | 
			
		||||
                return Poll::Pending;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // The TX interrupt only triggers when the there was data in the
 | 
			
		||||
            // FIFO and the number of bytes drops below a threshold. When the
 | 
			
		||||
            // FIFO was empty we have to manually pend the interrupt to shovel
 | 
			
		||||
            // TX data from the buffer into the FIFO.
 | 
			
		||||
            let n = data.len().min(buf.len());
 | 
			
		||||
            data[..n].copy_from_slice(&buf[..n]);
 | 
			
		||||
            tx_writer.push_done(n);
 | 
			
		||||
 | 
			
		||||
            if empty {
 | 
			
		||||
                unsafe { T::Interrupt::steal() }.pend();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            Poll::Ready(Ok(n))
 | 
			
		||||
        })
 | 
			
		||||
        .await
 | 
			
		||||
@@ -316,19 +278,19 @@ impl<'d, T: BasicInstance> BufferedUartTx<'d, T> {
 | 
			
		||||
    fn blocking_write(&self, buf: &[u8]) -> Result<usize, Error> {
 | 
			
		||||
        loop {
 | 
			
		||||
            let state = T::buffered_state();
 | 
			
		||||
            let empty = state.tx_buf.is_empty();
 | 
			
		||||
 | 
			
		||||
            let mut tx_writer = unsafe { state.tx_buf.writer() };
 | 
			
		||||
            let n = tx_writer.push(|data| {
 | 
			
		||||
            let data = tx_writer.push_slice();
 | 
			
		||||
            if !data.is_empty() {
 | 
			
		||||
                let n = data.len().min(buf.len());
 | 
			
		||||
                data[..n].copy_from_slice(&buf[..n]);
 | 
			
		||||
                n
 | 
			
		||||
            });
 | 
			
		||||
                tx_writer.push_done(n);
 | 
			
		||||
 | 
			
		||||
            if n != 0 {
 | 
			
		||||
                // The TX interrupt only triggers when the there was data in the
 | 
			
		||||
                // FIFO and the number of bytes drops below a threshold. When the
 | 
			
		||||
                // FIFO was empty we have to manually pend the interrupt to shovel
 | 
			
		||||
                // TX data from the buffer into the FIFO.
 | 
			
		||||
                if empty {
 | 
			
		||||
                    unsafe { T::Interrupt::steal() }.pend();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                return Ok(n);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
use defmt::*;
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
use embassy_stm32::interrupt;
 | 
			
		||||
use embassy_stm32::usart::{BufferedUart, Config, State};
 | 
			
		||||
use embassy_stm32::usart::{BufferedUart, Config};
 | 
			
		||||
use embedded_io::asynch::BufRead;
 | 
			
		||||
use {defmt_rtt as _, panic_probe as _};
 | 
			
		||||
 | 
			
		||||
@@ -16,20 +16,10 @@ async fn main(_spawner: Spawner) {
 | 
			
		||||
 | 
			
		||||
    let config = Config::default();
 | 
			
		||||
 | 
			
		||||
    let mut state = State::new();
 | 
			
		||||
    let irq = interrupt::take!(USART3);
 | 
			
		||||
    let mut tx_buf = [0u8; 32];
 | 
			
		||||
    let mut rx_buf = [0u8; 32];
 | 
			
		||||
    let mut buf_usart = BufferedUart::new(
 | 
			
		||||
        &mut state,
 | 
			
		||||
        p.USART3,
 | 
			
		||||
        p.PD9,
 | 
			
		||||
        p.PD8,
 | 
			
		||||
        irq,
 | 
			
		||||
        &mut tx_buf,
 | 
			
		||||
        &mut rx_buf,
 | 
			
		||||
        config,
 | 
			
		||||
    );
 | 
			
		||||
    let mut buf_usart = BufferedUart::new(p.USART3, irq, p.PD9, p.PD8, &mut tx_buf, &mut rx_buf, config);
 | 
			
		||||
 | 
			
		||||
    loop {
 | 
			
		||||
        let buf = buf_usart.fill_buf().await.unwrap();
 | 
			
		||||
 
 | 
			
		||||
@@ -5,7 +5,7 @@
 | 
			
		||||
use defmt::*;
 | 
			
		||||
use embassy_executor::Spawner;
 | 
			
		||||
use embassy_stm32::interrupt;
 | 
			
		||||
use embassy_stm32::usart::{BufferedUart, Config, State};
 | 
			
		||||
use embassy_stm32::usart::{BufferedUart, Config};
 | 
			
		||||
use embedded_io::asynch::{Read, Write};
 | 
			
		||||
use {defmt_rtt as _, panic_probe as _};
 | 
			
		||||
 | 
			
		||||
@@ -20,20 +20,8 @@ async fn main(_spawner: Spawner) {
 | 
			
		||||
    let mut config = Config::default();
 | 
			
		||||
    config.baudrate = 9600;
 | 
			
		||||
 | 
			
		||||
    let mut state = State::new();
 | 
			
		||||
    let irq = interrupt::take!(USART2);
 | 
			
		||||
    let mut usart = unsafe {
 | 
			
		||||
        BufferedUart::new(
 | 
			
		||||
            &mut state,
 | 
			
		||||
            p.USART2,
 | 
			
		||||
            p.PA3,
 | 
			
		||||
            p.PA2,
 | 
			
		||||
            irq,
 | 
			
		||||
            &mut TX_BUFFER,
 | 
			
		||||
            &mut RX_BUFFER,
 | 
			
		||||
            config,
 | 
			
		||||
        )
 | 
			
		||||
    };
 | 
			
		||||
    let mut usart = unsafe { BufferedUart::new(p.USART2, irq, p.PA3, p.PA2, &mut TX_BUFFER, &mut RX_BUFFER, config) };
 | 
			
		||||
 | 
			
		||||
    usart.write_all(b"Hello Embassy World!\r\n").await.unwrap();
 | 
			
		||||
    info!("wrote Hello, starting echo");
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user