working, overhead is down a bit
This commit is contained in:
@@ -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,18 +182,15 @@ 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]
|
||||||
pub async fn bridge_usart1_rx_to_usart2_tx(
|
pub async fn bridge_usart1_rx_to_usart2_tx(
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user