1 Commits

Author SHA1 Message Date
Priec
685067a75f jsut minor changes, UNTESTED DMA TIMER CHANGE 2025-11-20 13:28:09 +01:00
5 changed files with 21 additions and 26 deletions

View File

@@ -68,11 +68,11 @@ async fn main(spawner: Spawner) {
config.rcc.pll1 = Some(Pll { config.rcc.pll1 = Some(Pll {
source: PllSource::HSI, source: PllSource::HSI,
// 16 MHz / 1 × 20 / 2 = 160 MHz // 16 MHz / 1 × 20 / 2 = 160 MHz
prediv: PllPreDiv::DIV1, // or 1.into() prediv: PllPreDiv::DIV1,
mul: PllMul::MUL20, // or 20.into() mul: PllMul::MUL20,
divp: None, divp: None,
divq: None, divq: None,
divr: Some(PllDiv::DIV2), // or Some(2.into()) divr: Some(PllDiv::DIV2),
}); });
config.enable_independent_io_supply = true; config.enable_independent_io_supply = true;
config.enable_independent_analog_supply = true; config.enable_independent_analog_supply = true;
@@ -131,14 +131,12 @@ async fn main(spawner: Spawner) {
let rx_pin = Input::new(p.PD6, Pull::Up); let rx_pin = Input::new(p.PD6, Pull::Up);
unsafe { RX_PIN = Some(rx_pin) }; unsafe { RX_PIN = Some(rx_pin) };
// 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);
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE); init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE);
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE); init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE);
dump_tim6_regs(); dump_tim6_regs();
let bsrr_ptr = embassy_stm32::pac::GPIOB.bsrr().as_ptr() as *mut u32; // POZOR B REGISTER
let bsrr_ptr = embassy_stm32::pac::GPIOB.bsrr().as_ptr() as *mut u32; // POZOR B REGISTER
spawner.spawn(tx_dma_task(p.GPDMA1_CH0, bsrr_ptr, SW_TX_RING.init([0; TX_RING_BYTES]), &PIPE_SW_TX).unwrap()); spawner.spawn(tx_dma_task(p.GPDMA1_CH0, bsrr_ptr, SW_TX_RING.init([0; TX_RING_BYTES]), &PIPE_SW_TX).unwrap());
// EDN OF SOFTWARE UART // EDN OF SOFTWARE UART
@@ -148,7 +146,6 @@ async fn main(spawner: Spawner) {
spawner.spawn(rx_dma_task(p.GPDMA1_CH1, gpio_idr, rx_ring, &PIPE_SW_RX).unwrap()); spawner.spawn(rx_dma_task(p.GPDMA1_CH1, gpio_idr, rx_ring, &PIPE_SW_RX).unwrap());
info!("SW UART RX DMA started"); info!("SW UART RX DMA started");
// Process decoded bytes coming from PIPE_SW_RX
let mut buf = [0u8; 64]; let mut buf = [0u8; 64];
loop { loop {
let n = PIPE_SW_RX.read(&mut buf).await; let n = PIPE_SW_RX.read(&mut buf).await;

View File

@@ -39,7 +39,8 @@ fn configure_basic_timer<T: BasicInstance>(ll: &Timer<'_, T>, baud: u32, oversam
let target = baud.saturating_mul(oversample.max(1) as u32).max(1); let target = baud.saturating_mul(oversample.max(1) as u32).max(1);
// Compute ARR (prescaler = 0) // Compute ARR (prescaler = 0)
let mut arr = (f_timer / target).saturating_sub(1) as u16; // let mut arr = (f_timer / target).saturating_sub(1) as u16;
let mut arr = ((f_timer + target / 2) / target).saturating_sub(1) as u16;
if arr == 0 { arr = 1; } if arr == 0 { arr = 1; }
ll.regs_basic().cr1().write(|w| { ll.regs_basic().cr1().write(|w| {

View File

@@ -37,7 +37,7 @@ pub async fn rx_dma_task(
// We read into the second half of a buffer, keeping "leftovers" in the first half. // We read into the second half of a buffer, keeping "leftovers" in the first half.
const CHUNK_SIZE: usize = 4096; const CHUNK_SIZE: usize = 4096;
const HISTORY_SIZE: usize = 512; // Enough to hold a potential split frame const HISTORY_SIZE: usize = 512;
const TOTAL_BUF_SIZE: usize = HISTORY_SIZE + CHUNK_SIZE; const TOTAL_BUF_SIZE: usize = HISTORY_SIZE + CHUNK_SIZE;
// Logic level buffer // Logic level buffer
@@ -54,7 +54,6 @@ pub async fn rx_dma_task(
} }
let current_end = valid_len + CHUNK_SIZE; let current_end = valid_len + CHUNK_SIZE;
// 3. Decode everything we have
let (decoded, consumed) = decode_uart_samples( let (decoded, consumed) = decode_uart_samples(
&level_buf[..current_end], &level_buf[..current_end],
RX_OVERSAMPLE, RX_OVERSAMPLE,
@@ -69,13 +68,12 @@ pub async fn rx_dma_task(
} }
} }
// 4. Shift remaining data to front // Shift remaining data to front
// We processed 'consumed' samples. // We processed 'consumed' samples.
// We keep everything from 'consumed' up to 'current_end'. // We keep everything from 'consumed' up to 'current_end'.
let remaining = current_end - consumed; let remaining = current_end - consumed;
// Safety check: if remaining > HISTORY_SIZE, we are in trouble (buffer too small / decoder stuck). // SAFETY if remaining > HISTORY_SIZE, we are in trouble (buffer too small / decoder stuck).
// But for now, just shift.
if remaining > 0 { if remaining > 0 {
level_buf.copy_within(consumed..current_end, 0); level_buf.copy_within(consumed..current_end, 0);
} }

View File

@@ -59,14 +59,13 @@ pub async fn tx_dma_task(
let used = encode_uart_frames(TX_PIN_BIT, &rx_buf[..n], &mut frame_buf).await; let used = encode_uart_frames(TX_PIN_BIT, &rx_buf[..n], &mut frame_buf).await;
if used > 0 { if used > 0 {
// Align arming to a clean TIM6 update boundary: // Clear pending UIF
// 1) clear any pending UIF
tim6.sr().write(|w| w.set_uif(false)); tim6.sr().write(|w| w.set_uif(false));
// 2) wait for the next UIF (next bit tick) // Wait for the next UIF (next bit tick)
while !tim6.sr().read().uif() { while !tim6.sr().read().uif() {
yield_now().await; yield_now().await;
} }
// 3) clear UIF so first DMA beat happens on the FOLLOWING tick // Clear UIF so first DMA beat happens on the FOLLOWING tick
tim6.sr().write(|w| w.set_uif(false)); tim6.sr().write(|w| w.set_uif(false));
let mut tx_opts = TransferOptions::default(); let mut tx_opts = TransferOptions::default();

View File

@@ -115,7 +115,7 @@ pub fn decode_uart_samples(
let frame_bits = 1 + nbits + parity_bits + stop_bits_count; let frame_bits = 1 + nbits + parity_bits + stop_bits_count;
let frame_len = frame_bits * ovs; let frame_len = frame_bits * ovs;
// Helper: Majority vote over 3 samples centered at `i` // Majority vote over 3 samples centered at `i`
let get_bit = |i: usize| -> u8 { let get_bit = |i: usize| -> u8 {
let mut votes = 0; let mut votes = 0;
// Check i-1, i, i+1. Saturating sub/add handles boundaries roughly. // Check i-1, i, i+1. Saturating sub/add handles boundaries roughly.
@@ -136,7 +136,7 @@ pub fn decode_uart_samples(
} }
}; };
// We loop while we have enough remaining samples for a full frame // Loop while we have enough remaining samples for a full frame
while idx + frame_len <= samples.len() { while idx + frame_len <= samples.len() {
// Wait for falling edge (High -> Low) // Wait for falling edge (High -> Low)
// samples[idx] == 1 (Idle/Stop) && samples[idx+1] == 0 (Start) // samples[idx] == 1 (Idle/Stop) && samples[idx+1] == 0 (Start)
@@ -146,7 +146,7 @@ pub fn decode_uart_samples(
let center_offset = 1 + (ovs / 2); let center_offset = 1 + (ovs / 2);
let mut scan_idx = idx + center_offset; let mut scan_idx = idx + center_offset;
// 1. Validate Start Bit (Must be 0) // Validate Start Bit
if get_bit(scan_idx) != 0 { if get_bit(scan_idx) != 0 {
idx += 1; // False start (noise), move on idx += 1; // False start (noise), move on
continue; continue;
@@ -155,7 +155,7 @@ pub fn decode_uart_samples(
// Move to center of first data bit // Move to center of first data bit
scan_idx += ovs; scan_idx += ovs;
// 2. Read Data Bits // Read Data Bits
let mut data: u8 = 0; let mut data: u8 = 0;
for bit in 0..nbits { for bit in 0..nbits {
if get_bit(scan_idx) == 1 { if get_bit(scan_idx) == 1 {
@@ -164,22 +164,22 @@ pub fn decode_uart_samples(
scan_idx += ovs; scan_idx += ovs;
} }
// 3. Skip Parity (if any) // Skip Parity
if cfg.parity != Parity::None { if cfg.parity != Parity::None {
scan_idx += ovs; scan_idx += ovs;
} }
// 4. Validate Stop Bit (Must be 1) // Validate Stop Bit (Must be 1)
// If stop bit is 0, it's a framing error. We reject the whole byte. // If stop bit is 0, it's a framing error. We reject the whole byte.
if get_bit(scan_idx) == 0 { if get_bit(scan_idx) == 0 {
idx += 1; // Try to find a real start bit on the next sample idx += 1; // Next sample
continue; continue;
} }
// 5. Byte is valid // Byte is valid
let _ = out.push(data); let _ = out.push(data);
// 6. Active Resync: Fast-forward through the stop bit(s) and idle time // Active Resync: Fast-forward through the stop bit(s) and idle time
// scan_idx is currently at the center of the Stop bit. // scan_idx is currently at the center of the Stop bit.
idx = scan_idx; idx = scan_idx;
// Advance while we are reading High (1). // Advance while we are reading High (1).