58 lines
1.8 KiB
Rust
58 lines
1.8 KiB
Rust
// 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)
|
|
}
|