compiled, config in src/config, but i get hardfault crash at runtime
This commit is contained in:
@@ -7,29 +7,18 @@ use embassy_executor::Spawner;
|
|||||||
use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed};
|
use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed};
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
|
use embassy_stm32::dma::{TransferOptions, WritableRingBuffer};
|
||||||
use dma_gpio::software_uart::{
|
use dma_gpio::software_uart::{
|
||||||
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
||||||
uart_emulation::{Parity, StopBits, UartConfig},
|
|
||||||
gpio_dma_uart_tx::{write_uart_frames_to_ring, TIM6_UP_REQ},
|
gpio_dma_uart_tx::{write_uart_frames_to_ring, TIM6_UP_REQ},
|
||||||
gpio_dma_uart_rx::rx_dma_task,
|
gpio_dma_uart_rx::rx_dma_task,
|
||||||
debug::dump_tim6_regs,
|
debug::dump_tim6_regs,
|
||||||
};
|
};
|
||||||
use embassy_stm32::dma::{TransferOptions, WritableRingBuffer};
|
use dma_gpio::config::{BAUD, TX_PIN_BIT, RX_OVERSAMPLE, TX_OVERSAMPLE, UART_CFG};
|
||||||
|
use dma_gpio::config::{TX_RING_BYTES, RX_RING_BYTES, PIPE_RX_SIZE};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
/// SOFTWARE UART CONFIGURATION
|
|
||||||
const BAUD: u32 = 115_200;
|
|
||||||
const TX_PIN_BIT: u8 = 2; // PA2
|
|
||||||
const TX_OVERSAMPLE: u16 = 1;
|
|
||||||
const RX_OVERSAMPLE: u16 = 16;
|
|
||||||
const RX_RING_BYTES: usize = 4096;
|
|
||||||
const TX_RING_BYTES: usize = 4096;
|
|
||||||
|
|
||||||
// Nemoze by generic, v taskoch treba manualne zmenit
|
|
||||||
// Compiler upozorni, takze ostava takto
|
|
||||||
const PIPE_RX_SIZE: usize = 256;
|
|
||||||
|
|
||||||
static PIPE_RX: Pipe<CriticalSectionRawMutex, PIPE_RX_SIZE> = Pipe::new();
|
static PIPE_RX: Pipe<CriticalSectionRawMutex, PIPE_RX_SIZE> = Pipe::new();
|
||||||
static RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
|
static RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
|
||||||
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
||||||
@@ -75,18 +64,12 @@ async fn main(spawner: Spawner) {
|
|||||||
tx_ring.start();
|
tx_ring.start();
|
||||||
info!("TX DMA ring started");
|
info!("TX DMA ring started");
|
||||||
|
|
||||||
let uart_cfg = UartConfig {
|
|
||||||
data_bits: 8,
|
|
||||||
parity: Parity::None,
|
|
||||||
stop_bits: StopBits::One,
|
|
||||||
};
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
write_uart_frames_to_ring(
|
write_uart_frames_to_ring(
|
||||||
&mut tx_ring,
|
&mut tx_ring,
|
||||||
TX_PIN_BIT,
|
TX_PIN_BIT,
|
||||||
b"Hello marshmallow\r\n",
|
b"Hello marshmallow\r\n",
|
||||||
&uart_cfg,
|
&UART_CFG,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
Timer::after(Duration::from_secs(2)).await;
|
Timer::after(Duration::from_secs(2)).await;
|
||||||
|
|||||||
16
dma_gpio/src/config.rs
Normal file
16
dma_gpio/src/config.rs
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
// src/config.rs
|
||||||
|
use crate::software_uart::uart_emulation::{Parity, StopBits, UartConfig};
|
||||||
|
|
||||||
|
pub const BAUD: u32 = 115_200;
|
||||||
|
pub const TX_PIN_BIT: u8 = 2; // PA2
|
||||||
|
pub const TX_OVERSAMPLE: u16 = 1;
|
||||||
|
pub const RX_OVERSAMPLE: u16 = 16;
|
||||||
|
pub const RX_RING_BYTES: usize = 4096;
|
||||||
|
pub const TX_RING_BYTES: usize = 4096;
|
||||||
|
pub const PIPE_RX_SIZE: usize = 256;
|
||||||
|
|
||||||
|
pub const UART_CFG: UartConfig = UartConfig {
|
||||||
|
data_bits: 8,
|
||||||
|
parity: Parity::None,
|
||||||
|
stop_bits: StopBits::One,
|
||||||
|
};
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
|
|
||||||
pub mod software_uart;
|
pub mod software_uart;
|
||||||
|
pub mod config;
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ use embassy_stm32::dma::{
|
|||||||
ReadableRingBuffer as DmaRingRx,
|
ReadableRingBuffer as DmaRingRx,
|
||||||
TransferOptions,
|
TransferOptions,
|
||||||
};
|
};
|
||||||
|
use crate::config::{RX_OVERSAMPLE, UART_CFG};
|
||||||
|
use crate::software_uart::decode_uart_samples;
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
||||||
|
|
||||||
// datasheet tabulka 137
|
// datasheet tabulka 137
|
||||||
@@ -34,6 +36,7 @@ pub async fn rx_dma_task(
|
|||||||
let mut chunk = [0u8; 256];
|
let mut chunk = [0u8; 256];
|
||||||
loop {
|
loop {
|
||||||
let _ = rx.read_exact(&mut chunk).await;
|
let _ = rx.read_exact(&mut chunk).await;
|
||||||
pipe_rx.write(&chunk).await;
|
let decoded = decode_uart_samples(&chunk, RX_OVERSAMPLE, &UART_CFG);
|
||||||
|
pipe_rx.write(&decoded).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
// src/software_uart/uart_emulation.rs
|
// src/software_uart/uart_emulation.rs
|
||||||
|
use heapless::Vec;
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
|
||||||
pub enum Parity {
|
pub enum Parity {
|
||||||
@@ -87,3 +88,63 @@ pub fn encode_uart_byte_cfg(
|
|||||||
|
|
||||||
idx
|
idx
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Decode an oversampled stream of logic levels into UART bytes.
|
||||||
|
pub fn decode_uart_samples(
|
||||||
|
samples: &[u8],
|
||||||
|
oversample: u16,
|
||||||
|
cfg: &UartConfig,
|
||||||
|
) -> heapless::Vec<u8, 256> {
|
||||||
|
|
||||||
|
let mut out = Vec::<u8, 256>::new();
|
||||||
|
let mut idx = 0usize;
|
||||||
|
let nbits = cfg.data_bits as usize;
|
||||||
|
|
||||||
|
while idx + (oversample as usize * (nbits + 3)) < samples.len() {
|
||||||
|
// Wait for start bit (falling edge: high -> low)
|
||||||
|
if samples[idx] != 0 && samples[idx + 1] == 0 {
|
||||||
|
// Align to middle of start bit
|
||||||
|
idx += (oversample / 2) as usize;
|
||||||
|
|
||||||
|
// Sanity check start bit really low
|
||||||
|
if samples.get(idx).copied().unwrap_or(1) != 0 {
|
||||||
|
idx += 1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sample data bits
|
||||||
|
let mut data: u8 = 0;
|
||||||
|
for bit in 0..nbits {
|
||||||
|
idx += oversample as usize;
|
||||||
|
let bit_val = samples
|
||||||
|
.get(idx)
|
||||||
|
.map(|&b| if b != 0 { 1u8 } else { 0u8 })
|
||||||
|
.unwrap_or(1);
|
||||||
|
data |= bit_val << bit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parity: skip / verify
|
||||||
|
match cfg.parity {
|
||||||
|
Parity::None => {}
|
||||||
|
Parity::Even | Parity::Odd => {
|
||||||
|
idx += oversample as usize;
|
||||||
|
// You can optionally add parity check here if needed
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Move past stop bits
|
||||||
|
let stop_skip = match cfg.stop_bits {
|
||||||
|
StopBits::One => oversample as usize,
|
||||||
|
StopBits::Two => (oversample * 2) as usize,
|
||||||
|
};
|
||||||
|
idx += stop_skip;
|
||||||
|
|
||||||
|
// Push decoded byte
|
||||||
|
let _ = out.push(data);
|
||||||
|
} else {
|
||||||
|
idx += 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
out
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user