working, overhead is down a bit

This commit is contained in:
Priec
2025-11-19 17:50:33 +01:00
parent 0cd40eb5e2
commit 110ddc0dcf
2 changed files with 43 additions and 37 deletions

View File

@@ -38,8 +38,7 @@ use cortex_m::interrupt::Mutex;
use core::cell::RefCell; use core::cell::RefCell;
use embassy_sync::channel::Channel; use embassy_sync::channel::Channel;
static RX_PIN_GLOBAL: Mutex<RefCell<Option<&'static Input<'static>>>> = Mutex::new(RefCell::new(None)); static PD6_BITS: Channel<CriticalSectionRawMutex, u8, 16384> = Channel::new();
static PD6_BITS: Channel<CriticalSectionRawMutex, u8, 4096> = Channel::new();
bind_interrupts!(struct Irqs { bind_interrupts!(struct Irqs {
USART1 => BufferedInterruptHandler<peripherals::USART1>; USART1 => BufferedInterruptHandler<peripherals::USART1>;
@@ -52,6 +51,7 @@ bind_interrupts!(struct Irqs2 {
pub const TIM6_UP_REQ: Request = 4; pub const TIM6_UP_REQ: Request = 4;
static SW_TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new(); static SW_TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
static SW_RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new(); static SW_RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
static mut RX_PIN: Option<Input<'static>> = None;
#[embassy_executor::main] #[embassy_executor::main]
async fn main(spawner: Spawner) { async fn main(spawner: Spawner) {
@@ -107,11 +107,7 @@ async fn main(spawner: Spawner) {
// SOFTWARE UART // SOFTWARE UART
// let _rx = Input::new(p.PD6, Pull::Up); // let _rx = Input::new(p.PD6, Pull::Up);
let rx_pin = Input::new(p.PD6, Pull::Up); let rx_pin = Input::new(p.PD6, Pull::Up);
unsafe { RX_PIN = Some(rx_pin) };
// Rx ready for the interrupt
use cortex_m::interrupt::free;
let rx_pin_ref: &'static Input<'static> = unsafe { core::mem::transmute(&rx_pin) };
free(|cs| RX_PIN_GLOBAL.borrow(cs).replace(Some(rx_pin_ref)));
// Configure TX as output (PB0) // Configure TX as output (PB0)
let mut tx_pin = Output::new(p.PB0, Level::High, Speed::VeryHigh); let mut tx_pin = Output::new(p.PB0, Level::High, Speed::VeryHigh);
@@ -123,46 +119,59 @@ async fn main(spawner: Spawner) {
unsafe { cortex_m::peripheral::NVIC::unmask(pac::Interrupt::TIM7); } unsafe { cortex_m::peripheral::NVIC::unmask(pac::Interrupt::TIM7); }
let mut rx_samples = [1u8; 1024]; let frame_samples = (10 * RX_OVERSAMPLE as usize); // 1 start + 8 data + 1 stop
let mut rx_samples = [0u8; 4096]; // plenty of space
let mut rx_count = 0usize; let mut rx_count = 0usize;
loop { loop {
// 1. Drain the channel into the local buffer // === 1. Drain channel into local buffer in bursts ===
let mut drained = 0;
while let Ok(bit) = PD6_BITS.try_receive() { while let Ok(bit) = PD6_BITS.try_receive() {
if rx_count < rx_samples.len() { if rx_count < rx_samples.len() {
rx_samples[rx_count] = bit; rx_samples[rx_count] = bit;
rx_count += 1; rx_count += 1;
} else { } else {
// Buffer full: discarding oldest data by rotating
// Simple naive strategy: just clear half
// Ideally we should prevent this by processing faster
warn!("RX Buffer overflow, resetting"); warn!("RX Buffer overflow, resetting");
rx_count = 0; rx_count = 0;
} }
drained += 1;
// Periodically yield while draining to avoid hogging CPU
if drained >= 512 {
yield_now().await;
drained = 0;
}
} }
// 2. Try to decode UART frames from the buffer // === 2. Process only when we have enough samples for a frame ===
if rx_count > 0 { if rx_count >= frame_samples {
// Try to decode
let (decoded, consumed) = decode_uart_samples( let (decoded, consumed) = decode_uart_samples(
&rx_samples[..rx_count], &rx_samples[..rx_count],
RX_OVERSAMPLE, RX_OVERSAMPLE,
&UART_CFG &UART_CFG,
); );
// Print received characters // Print decoded chars
for b in decoded { if !decoded.is_empty() {
info!("Received: {}", b as char); // For debugging: only print when you actually have data
for &b in &decoded {
info!("{}", b as char);
}
} }
// 3. Remove processed samples from the buffer // === 3. Remove processed samples ===
if consumed > 0 { if consumed > 0 {
// Shift remaining data to the front // Slide unprocessed samples to the start
// copy_within is efficient for slices
rx_samples.copy_within(consumed..rx_count, 0); rx_samples.copy_within(consumed..rx_count, 0);
rx_count -= consumed; rx_count -= consumed;
} }
}
// Yield briefly so other embassy tasks run
yield_now().await; yield_now().await;
} else {
// === 4. Buffer not yet full enough, short sleep ===
yield_now().await;
}
} }
} }
@@ -173,17 +182,14 @@ fn TIM7() {
if tim.sr().read().uif() { if tim.sr().read().uif() {
tim.sr().modify(|w| w.set_uif(false)); tim.sr().modify(|w| w.set_uif(false));
let bit = cortex_m::interrupt::free(|cs| { unsafe {
RX_PIN_GLOBAL if let Some(ref pin) = RX_PIN {
.borrow(cs) // one instruction read no locking needed
.borrow() let bit = pin.is_high() as u8;
.as_ref()
.map(|pin| pin.is_high())
.unwrap_or(false)
}) as u8;
let _ = PD6_BITS.try_send(bit); let _ = PD6_BITS.try_send(bit);
} }
}
}
} }
#[embassy_executor::task] #[embassy_executor::task]
@@ -196,7 +202,7 @@ pub async fn bridge_usart1_rx_to_usart2_tx(
let n = usart1_rx.read(&mut buf).await; let n = usart1_rx.read(&mut buf).await;
if n > 0 { if n > 0 {
let _ = usart2_tx.write(&buf[..n]).await; let _ = usart2_tx.write(&buf[..n]).await;
info!("bridge: USART1 -> USART2 sent {} bytes", n); // info!("bridge: USART1 -> USART2 sent {} bytes", n);
} }
yield_now().await; yield_now().await;
} }

View File

@@ -9,7 +9,7 @@ pub const BAUD: u32 = 600;
pub const TX_PIN_BIT: u8 = 0; // PB2 pub const TX_PIN_BIT: u8 = 0; // PB2
pub const RX_PIN_BIT: u8 = 3; // PC3 pub const RX_PIN_BIT: u8 = 3; // PC3
pub const TX_OVERSAMPLE: u16 = 1; pub const TX_OVERSAMPLE: u16 = 1;
pub const RX_OVERSAMPLE: u16 = 1; pub const RX_OVERSAMPLE: u16 = 2;
pub const RX_RING_BYTES: usize = 4096; pub const RX_RING_BYTES: usize = 4096;
pub const TX_RING_BYTES: usize = 4096; pub const TX_RING_BYTES: usize = 4096;