// src/uart/driver.rs use defmt::unwrap; use embassy_executor::Spawner; use embassy_futures::select::{select, Either}; use embassy_stm32::usart::BufferedUart; use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; use embassy_sync::pipe::Pipe; use embassy_time::Duration; use embedded_io_async::{Read, Write}; use crate::uart::safety::{RX_PIPE_CAP, TX_PIPE_CAP}; pub struct UartHandle { pub tx: &'static Pipe, pub rx: &'static Pipe, pub yield_period: Duration, } #[embassy_executor::task] pub async fn uart_task( mut uart: BufferedUart<'static>, tx_pipe: &'static Pipe, rx_pipe: &'static Pipe, ) { let mut rx_byte = [0u8; 1]; let mut tx_buf = [0u8; 64]; loop { let rx_fut = uart.read(&mut rx_byte); let tx_fut = async { let n = tx_pipe.read(&mut tx_buf).await; n }; match select(rx_fut, tx_fut).await { // Incoming data from UART hardware Either::First(res) => { if let Ok(_) = res { // Forward to RX pipe and echo to TX pipe (same behavior as before) let _ = rx_pipe.write(&rx_byte).await; let _ = tx_pipe.try_write(&rx_byte); } } // Outgoing data waiting in TX pipe Either::Second(n) => { unwrap!(uart.write(&tx_buf[..n]).await); } } } } pub fn spawn_for( spawner: &Spawner, uart: BufferedUart<'static>, tx_pipe: &'static Pipe, rx_pipe: &'static Pipe, yield_period: Duration, ) -> UartHandle { spawner.spawn(uart_task(uart, tx_pipe, rx_pipe)).unwrap(); UartHandle { tx: tx_pipe, rx: rx_pipe, yield_period, } }