From 8de34e13d9eaf2cc9dc0b635236486421cddfeba Mon Sep 17 00:00:00 2001 From: Priec Date: Fri, 31 Oct 2025 13:00:21 +0100 Subject: [PATCH] solution detached from main for async buffered generalized2 --- dma_gpio/src/bin/main.rs | 4 +- dma_gpio/src/dma_timer.rs | 4 +- .../src/bin/main.rs | 100 +++++------------- usart_async_buffered_generalized2/src/lib.rs | 1 + .../src/uart/driver.rs | 65 ++++++++++++ .../src/uart/mod.rs | 3 + .../src/uart/usart1.rs | 25 +++++ 7 files changed, 125 insertions(+), 77 deletions(-) create mode 100644 usart_async_buffered_generalized2/src/uart/driver.rs create mode 100644 usart_async_buffered_generalized2/src/uart/mod.rs create mode 100644 usart_async_buffered_generalized2/src/uart/usart1.rs diff --git a/dma_gpio/src/bin/main.rs b/dma_gpio/src/bin/main.rs index 07b1a88..575ad42 100644 --- a/dma_gpio/src/bin/main.rs +++ b/dma_gpio/src/bin/main.rs @@ -25,7 +25,7 @@ static PIPE: Pipe = Pipe::new(); // Baud rate: one TIM6 update equals one UART bit-time const BAUD: u32 = 115_200; const TX_PIN_BIT: u8 = 2; // PA2 -const OVERSAMPLE: u16 = 6; +const OVERSAMPLE: u16 = 16; const UART_CFG: UartConfig = UartConfig { data_bits: 8, @@ -125,7 +125,7 @@ async fn dma_tx_task(ch: Peri<'static, GPDMA1_CH0>) { { Ok(()) => {} Err(_) => { - warn!("DMA timeout: no TIM6 request (wrong DMAMUX req?)"); + warn!("DMA timeout: no TIM6 request"); dump_tim6_regs(); dump_dma_ch0_regs(); } diff --git a/dma_gpio/src/dma_timer.rs b/dma_gpio/src/dma_timer.rs index bdd1663..b897dbc 100644 --- a/dma_gpio/src/dma_timer.rs +++ b/dma_gpio/src/dma_timer.rs @@ -28,7 +28,7 @@ pub fn init_tim6_for_uart<'d>(tim6: Peri<'d, TIM6>, baud: u32, oversample: u16) ll.regs_basic().cr1().write(|w| { w.set_cen(false); w.set_opm(false); - w.set_udis(false); // boolean field: false = allow UEV + w.set_udis(false); // boolean field: false = allow UEV w.set_urs(Urs::ANY_EVENT); // enum field: DMA+interrupts on any event }); @@ -47,5 +47,5 @@ pub fn init_tim6_for_uart<'d>(tim6: Peri<'d, TIM6>, baud: u32, oversample: u16) w.set_udis(false); w.set_urs(Urs::ANY_EVENT); }); - mem::forget(ll); + mem::forget(ll); // KEEP THE TIMER ALIVE } diff --git a/usart_async_buffered_generalized2/src/bin/main.rs b/usart_async_buffered_generalized2/src/bin/main.rs index c3788c6..f03eb3e 100644 --- a/usart_async_buffered_generalized2/src/bin/main.rs +++ b/usart_async_buffered_generalized2/src/bin/main.rs @@ -1,93 +1,51 @@ // src/bin/main.rs #![no_std] #![no_main] + use defmt::*; +use {defmt_rtt as _, panic_probe as _}; + use embassy_executor::Spawner; +use embassy_stm32::usart::{BufferedInterruptHandler, BufferedUart, Config}; use embassy_stm32::bind_interrupts; use embassy_stm32::peripherals; -use embassy_stm32::usart::{BufferedInterruptHandler, BufferedUart, Config}; -use embedded_io_async::{Read, Write}; -use embassy_time::{Timer, Duration, Instant}; +use embassy_time::Instant; use static_cell::StaticCell; -use embassy_futures::yield_now; -use {defmt_rtt as _, panic_probe as _}; -use embassy_futures::select::{select, Either}; -use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; -use embassy_sync::pipe::Pipe; -use async_uart::safety::{preflight_and_suggest_yield_period, RX_PIPE_CAP, TX_PIPE_CAP}; -static UART_TX: Pipe = Pipe::new(); -static UART_RX: Pipe = Pipe::new(); +use async_uart::uart::usart1; -bind_interrupts!( - struct Irqs { - USART1 => BufferedInterruptHandler; - } -); - -#[embassy_executor::task] -async fn uart_task(mut uart: BufferedUart<'static>) { - let mut rx_byte = [0u8; 1]; - let mut tx_buf = [0u8; 64]; - loop { - // Wait for either RX or TX events. - let rx_fut = uart.read(&mut rx_byte); - let tx_fut = async { - // Until there's outgoing data in TX pipe - let n = UART_TX.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 - let _ = UART_RX.write(&rx_byte).await; - let _ = UART_TX.try_write(&rx_byte); - } - } - // Outgoing data waiting in TX pipe - Either::Second(n) => { - unwrap!(uart.write(&tx_buf[..n]).await); - } - } - } -} +bind_interrupts!(struct Irqs { + USART1 => BufferedInterruptHandler; +}); #[embassy_executor::main] async fn main(spawner: Spawner) { - info!("tititititi"); + info!("boot"); let p = embassy_stm32::init(Default::default()); - static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); - static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); - let tx_buf = TX_BUF.init([0; 256]); - let rx_buf = RX_BUF.init([0; 256]); + let mut cfg = Config::default(); cfg.baudrate = 230_400; - // Call preflight and get the computed yield period - let yield_period = preflight_and_suggest_yield_period(cfg.baudrate); + static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); + static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new(); - let usart = BufferedUart::new( - p.USART1, - p.PA10, // RX - p.PA9, // TX - tx_buf, - rx_buf, - Irqs, - cfg, - ).unwrap(); - info!("starting uart task"); - spawner.spawn(uart_task(usart)).unwrap(); + let uart = + BufferedUart::new( + p.USART1, + p.PA10, + p.PA9, + TX_BUF.init([0; 256]), + RX_BUF.init([0; 256]), + Irqs, + cfg, + ).unwrap(); + let handle = usart1::setup_and_spawn(&spawner, uart, cfg.baudrate); - let mut counter: u32 = 0; let mut rx_buf = [0u8; 64]; let mut last_yield = Instant::now(); loop { - counter = counter.wrapping_add(1); - // Poll RX pipe for new data (non-blocking) - if let Ok(n) = UART_RX.try_read(&mut rx_buf) { + if let Ok(n) = handle.rx.try_read(&mut rx_buf) { if n > 0 { if let Ok(s) = core::str::from_utf8(&rx_buf[..n]) { info!("RX got: {}", s); @@ -97,13 +55,9 @@ async fn main(spawner: Spawner) { } } - // Guaranteed to yield before ISR RX buffer can overflow - if Instant::now().duration_since(last_yield) >= yield_period { - yield_now().await; + if Instant::now().duration_since(last_yield) >= handle.yield_period { + embassy_futures::yield_now().await; last_yield = Instant::now(); - // info!("Yield mf {}", counter); } - // Timer::after(Duration::from_micros(1)).await; - // Timer::after(Duration::from_secs(5)).await; } } diff --git a/usart_async_buffered_generalized2/src/lib.rs b/usart_async_buffered_generalized2/src/lib.rs index 3c7c842..9f593ed 100644 --- a/usart_async_buffered_generalized2/src/lib.rs +++ b/usart_async_buffered_generalized2/src/lib.rs @@ -1,2 +1,3 @@ #![no_std] pub mod safety; +pub mod uart; diff --git a/usart_async_buffered_generalized2/src/uart/driver.rs b/usart_async_buffered_generalized2/src/uart/driver.rs new file mode 100644 index 0000000..8a6cc36 --- /dev/null +++ b/usart_async_buffered_generalized2/src/uart/driver.rs @@ -0,0 +1,65 @@ +// 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::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, + } +} diff --git a/usart_async_buffered_generalized2/src/uart/mod.rs b/usart_async_buffered_generalized2/src/uart/mod.rs new file mode 100644 index 0000000..e0d6d58 --- /dev/null +++ b/usart_async_buffered_generalized2/src/uart/mod.rs @@ -0,0 +1,3 @@ +// src/uart/mod.rs +pub mod driver; +pub mod usart1; diff --git a/usart_async_buffered_generalized2/src/uart/usart1.rs b/usart_async_buffered_generalized2/src/uart/usart1.rs new file mode 100644 index 0000000..864b258 --- /dev/null +++ b/usart_async_buffered_generalized2/src/uart/usart1.rs @@ -0,0 +1,25 @@ +// src/uart/usart1.rs +use defmt::info; +use embassy_executor::Spawner; +use embassy_stm32::bind_interrupts; +use embassy_stm32::usart::BufferedInterruptHandler; +use embassy_sync::blocking_mutex::raw::CriticalSectionRawMutex; +use embassy_sync::pipe::Pipe; +use embassy_time::Duration; + +use crate::safety::{preflight_and_suggest_yield_period, RX_PIPE_CAP, TX_PIPE_CAP}; +use crate::uart::driver::{spawn_for, UartHandle}; + +// Static pipes and buffers +static UART1_TX_PIPE: Pipe = Pipe::new(); +static UART1_RX_PIPE: Pipe = Pipe::new(); + +pub fn setup_and_spawn( + spawner: &Spawner, + uart: embassy_stm32::usart::BufferedUart<'static>, + baudrate: u32, +) -> UartHandle { + let yield_period: Duration = preflight_and_suggest_yield_period(baudrate); + info!("USART1 initialized"); + spawn_for(spawner, uart, &UART1_TX_PIPE, &UART1_RX_PIPE, yield_period) +}