66 lines
1.9 KiB
Rust
66 lines
1.9 KiB
Rust
// 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<CriticalSectionRawMutex, TX_PIPE_CAP>,
|
|
pub rx: &'static Pipe<CriticalSectionRawMutex, RX_PIPE_CAP>,
|
|
pub yield_period: Duration,
|
|
}
|
|
|
|
#[embassy_executor::task]
|
|
pub async fn uart_task(
|
|
mut uart: BufferedUart<'static>,
|
|
tx_pipe: &'static Pipe<CriticalSectionRawMutex, TX_PIPE_CAP>,
|
|
rx_pipe: &'static Pipe<CriticalSectionRawMutex, RX_PIPE_CAP>,
|
|
) {
|
|
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<CriticalSectionRawMutex, TX_PIPE_CAP>,
|
|
rx_pipe: &'static Pipe<CriticalSectionRawMutex, RX_PIPE_CAP>,
|
|
yield_period: Duration,
|
|
) -> UartHandle {
|
|
spawner.spawn(uart_task(uart, tx_pipe, rx_pipe)).unwrap();
|
|
UartHandle {
|
|
tx: tx_pipe,
|
|
rx: rx_pipe,
|
|
yield_period,
|
|
}
|
|
}
|