Rx is not using dma now
This commit is contained in:
@@ -8,6 +8,9 @@ use embassy_executor::Spawner;
|
|||||||
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 dma_gpio::dma_timer::init_tim6_for_uart;
|
use dma_gpio::dma_timer::init_tim6_for_uart;
|
||||||
|
use embassy_stm32::gpio::Input;
|
||||||
|
use embassy_stm32::gpio::Pull;
|
||||||
|
use dma_gpio::gpio_uart_rx::GpioUartRx;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
use embassy_stm32::{
|
use embassy_stm32::{
|
||||||
@@ -20,7 +23,8 @@ use dma_gpio::gpio_dma_uart::{
|
|||||||
write_uart_frames_to_pipe, GpioDmaBsrrTx, Parity, StopBits, UartConfig,
|
write_uart_frames_to_pipe, GpioDmaBsrrTx, Parity, StopBits, UartConfig,
|
||||||
};
|
};
|
||||||
|
|
||||||
static PIPE: Pipe<CriticalSectionRawMutex, 256> = Pipe::new();
|
static PIPE_TX: Pipe<CriticalSectionRawMutex, 256> = Pipe::new();
|
||||||
|
static PIPE_RX: Pipe<CriticalSectionRawMutex, 256> = Pipe::new();
|
||||||
|
|
||||||
// Baud rate: one TIM6 update equals one UART bit-time
|
// Baud rate: one TIM6 update equals one UART bit-time
|
||||||
const BAUD: u32 = 115_200;
|
const BAUD: u32 = 115_200;
|
||||||
@@ -76,11 +80,20 @@ fn dump_dma_ch0_regs() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[embassy_executor::task]
|
||||||
|
async fn rx_task(pin: Input<'static>) {
|
||||||
|
let mut rx = GpioUartRx::new(pin, BAUD, UART_CFG, &PIPE_RX);
|
||||||
|
rx.run().await;
|
||||||
|
}
|
||||||
|
|
||||||
#[embassy_executor::main]
|
#[embassy_executor::main]
|
||||||
async fn main(spawner: Spawner) {
|
async fn main(spawner: Spawner) {
|
||||||
let p = embassy_stm32::init(Default::default());
|
let p = embassy_stm32::init(Default::default());
|
||||||
info!("DMA Pipe -> GPIO UART-like TX");
|
info!("DMA Pipe -> GPIO UART-like TX");
|
||||||
|
|
||||||
|
let pa3_rx = Input::new(p.PA3, Pull::Up);
|
||||||
|
spawner.spawn(rx_task(pa3_rx)).unwrap();
|
||||||
|
|
||||||
// PA2 is the TX "wire"
|
// PA2 is the TX "wire"
|
||||||
let _pa2 = Output::new(p.PA2, Level::High, Speed::VeryHigh);
|
let _pa2 = Output::new(p.PA2, Level::High, Speed::VeryHigh);
|
||||||
// drop(_pa2);
|
// drop(_pa2);
|
||||||
@@ -93,7 +106,7 @@ async fn main(spawner: Spawner) {
|
|||||||
// Example: transmit a string as UART frames via the Pipe
|
// Example: transmit a string as UART frames via the Pipe
|
||||||
loop {
|
loop {
|
||||||
write_uart_frames_to_pipe(
|
write_uart_frames_to_pipe(
|
||||||
&PIPE,
|
&PIPE_TX,
|
||||||
TX_PIN_BIT,
|
TX_PIN_BIT,
|
||||||
b"Hello, DMA UART (configurable)!\r\n",
|
b"Hello, DMA UART (configurable)!\r\n",
|
||||||
&UART_CFG,
|
&UART_CFG,
|
||||||
@@ -110,7 +123,7 @@ async fn dma_tx_task(ch: Peri<'static, GPDMA1_CH0>) {
|
|||||||
loop {
|
loop {
|
||||||
// Read one 32-bit BSRR word (4 bytes) from the Pipe
|
// Read one 32-bit BSRR word (4 bytes) from the Pipe
|
||||||
let mut b = [0u8; 4];
|
let mut b = [0u8; 4];
|
||||||
let n = PIPE.read(&mut b).await;
|
let n = PIPE_TX.read(&mut b).await;
|
||||||
if n != 4 {
|
if n != 4 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|||||||
48
dma_gpio/src/gpio_uart_rx.rs
Normal file
48
dma_gpio/src/gpio_uart_rx.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// src/gpio_uart_rx.rs
|
||||||
|
|
||||||
|
use embassy_stm32::gpio::{Input, Level, Pull};
|
||||||
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
||||||
|
use embassy_time::{Timer, Duration};
|
||||||
|
use crate::gpio_dma_uart::UartConfig;
|
||||||
|
|
||||||
|
/// Simplified bit-banged UART RX using a timer for sampling.
|
||||||
|
/// Sample pin every bit-time once start bit is detected.
|
||||||
|
pub struct GpioUartRx<'d, const N: usize> {
|
||||||
|
pin: Input<'d>,
|
||||||
|
baud: u32,
|
||||||
|
cfg: UartConfig,
|
||||||
|
pipe: &'d Pipe<CriticalSectionRawMutex, N>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'d, const N: usize> GpioUartRx<'d, N> {
|
||||||
|
pub fn new(pin: Input<'d>, baud: u32, cfg: UartConfig, pipe: &'d Pipe<CriticalSectionRawMutex, N>) -> Self {
|
||||||
|
Self { pin, baud, cfg, pipe }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Async read loop: waits for start bit, samples bits, pushes received byte into pipe.
|
||||||
|
pub async fn run(&mut self) -> ! {
|
||||||
|
let bit_time = Duration::from_hz(self.baud.into());
|
||||||
|
|
||||||
|
loop {
|
||||||
|
// Wait for start bit edge
|
||||||
|
while self.pin.get_level() == Level::High {
|
||||||
|
Timer::after_micros(1).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Skip only 1 bit-time since you *don’t* want 1.5 bit delay
|
||||||
|
Timer::after(bit_time).await;
|
||||||
|
|
||||||
|
let nbits = self.cfg.data_bits.clamp(5, 8);
|
||||||
|
let mut data = 0u8;
|
||||||
|
for i in 0..nbits {
|
||||||
|
if self.pin.get_level() == Level::High {
|
||||||
|
data |= 1 << i;
|
||||||
|
}
|
||||||
|
Timer::after(bit_time).await;
|
||||||
|
}
|
||||||
|
|
||||||
|
// push into Pipe as soon as byte is complete
|
||||||
|
self.pipe.write(&[data]).await;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,3 +5,4 @@ pub use gpio_dma_uart::*;
|
|||||||
|
|
||||||
pub mod dma_timer;
|
pub mod dma_timer;
|
||||||
pub use dma_timer::*;
|
pub use dma_timer::*;
|
||||||
|
pub mod gpio_uart_rx;
|
||||||
|
|||||||
Reference in New Issue
Block a user