// src/safety.rs use defmt::info; use embassy_time::Duration; // ISR RX ring capacity = RX_BUF len const ISR_RX_BUF_CAP: usize = 256; // Yield 1/2 the time it takes to fill ISR RX ring. const YIELD_MARGIN_NUM: u32 = 1; const YIELD_MARGIN_DEN: u32 = 2; // Ensure RX_PIPE_CAP can hold this. const WORST_MAIN_LATENCY_MS: u32 = 20; pub const TX_PIPE_CAP: usize = 1024; pub const RX_PIPE_CAP: usize = 1024; /// Perform safety checks and compute yield timing to avoid buffer overflow. /// /// # Panics /// Panics if pipe capacities are too small for the configured baud. pub fn preflight_and_suggest_yield_period(baud: u32) -> Duration { // Approx bytes per second for 8N1 (10 bits per byte on the wire) let bytes_per_sec = (baud / 10).max(1); // Time until ISR RX ring fills, in microseconds. let t_fill_us = (ISR_RX_BUF_CAP as u64) * 1_000_000u64 / (bytes_per_sec as u64); // Choose a yield period as a fraction of t_fill. let yield_us = (t_fill_us as u64) .saturating_mul(YIELD_MARGIN_NUM as u64) / (YIELD_MARGIN_DEN as u64); // Verify RX pipe can absorb a worst-case app latency so uart_task // can always forward without dropping when it runs. let required_rx_pipe = (bytes_per_sec as u64) * (WORST_MAIN_LATENCY_MS as u64) / 1000; if (RX_PIPE_CAP as u64) < required_rx_pipe { core::panic!( "RX pipe too small: have {}B, need >= {}B for {}ms at {} bps", RX_PIPE_CAP, required_rx_pipe, WORST_MAIN_LATENCY_MS, baud ); } info!( "Preflight: baud={}, rx_isr={}B, rx_pipe={}B, bytes/s={}, t_fill_us={}, yield_us={}", baud, ISR_RX_BUF_CAP, RX_PIPE_CAP, bytes_per_sec, t_fill_us, yield_us ); // Never choose zero. Duration::from_micros(yield_us.max(1) as u64) }