diff --git a/dma_gpio/src/bin/main.rs b/dma_gpio/src/bin/main.rs index 0e3472e..a944aac 100644 --- a/dma_gpio/src/bin/main.rs +++ b/dma_gpio/src/bin/main.rs @@ -9,10 +9,13 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe}; use embassy_time::{Duration, Timer}; use dma_gpio::software_uart::{ dma_timer::{init_tim6_for_uart, init_tim7_for_uart}, - gpio_dma_uart_tx::{write_uart_frames_to_pipe, UartConfig, Parity, StopBits}, - runtime::{rx_dma_task, tx_dma_task}, + gpio_dma_uart_tx::{ + write_uart_frames_to_ring, Parity, StopBits, UartConfig, TIM6_UP_REQ, + }, + runtime::rx_dma_task, debug::dump_tim6_regs, }; +use embassy_stm32::dma::{TransferOptions, WritableRingBuffer}; use static_cell::StaticCell; use {defmt_rtt as _, panic_probe as _}; @@ -23,12 +26,11 @@ 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_TX_SIZE: usize = 256; const PIPE_RX_SIZE: usize = 256; -static PIPE_TX: Pipe = Pipe::new(); static PIPE_RX: Pipe = Pipe::new(); static RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new(); static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new(); @@ -38,21 +40,41 @@ async fn main(spawner: Spawner) { let p = embassy_stm32::init(Default::default()); info!("Hehe"); - let rx = Input::new(p.PA3, Pull::Up); - let tx = Output::new(p.PA2, Level::High, Speed::VeryHigh); + let _rx = Input::new(p.PA3, Pull::Up); + let _tx = Output::new(p.PA2, Level::High, Speed::VeryHigh); init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE); init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE); + dump_tim6_regs(); // Safe one-time init from StaticCell let rx_ring: &mut [u8; RX_RING_BYTES] = RX_RING.init([0; RX_RING_BYTES]); - let tx_ring: &mut [u32; TX_RING_BYTES] = TX_RING.init([0; TX_RING_BYTES]); + let tx_ring_mem: &mut [u32; TX_RING_BYTES] = + TX_RING.init([0; TX_RING_BYTES]); // Spawn tasks - spawner.spawn(tx_dma_task(p.GPDMA1_CH0, tx_ring).unwrap()); spawner.spawn(rx_dma_task(p.GPDMA1_CH1, &PIPE_RX, rx_ring).unwrap()); + // Create and start the TX DMA ring in main. + let bsrr_ptr = embassy_stm32::pac::GPIOA.bsrr().as_ptr() as *mut u32; + let mut tx_opts = TransferOptions::default(); + tx_opts.half_transfer_ir = true; + tx_opts.complete_transfer_ir = true; + + // SAFETY: tx_ring_mem is exclusive, bsrr_ptr points to GPIOA BSRR, paced by TIM6. + let mut tx_ring = unsafe { + WritableRingBuffer::new( + p.GPDMA1_CH0, + TIM6_UP_REQ, + bsrr_ptr, + tx_ring_mem, + tx_opts, + ) + }; + tx_ring.start(); + info!("TX DMA ring started"); + let uart_cfg = UartConfig { data_bits: 8, parity: Parity::None, @@ -60,7 +82,13 @@ async fn main(spawner: Spawner) { }; loop { - write_uart_frames_to_pipe(&PIPE_TX, TX_PIN_BIT, b"Hello marshmallow\r\n", &uart_cfg).await; + write_uart_frames_to_ring( + &mut tx_ring, + TX_PIN_BIT, + b"Hello marshmallow\r\n", + &uart_cfg, + ) + .await; Timer::after(Duration::from_secs(2)).await; } } diff --git a/dma_gpio/src/software_uart/gpio_dma_uart_tx.rs b/dma_gpio/src/software_uart/gpio_dma_uart_tx.rs index f1b6fc2..69adcd2 100644 --- a/dma_gpio/src/software_uart/gpio_dma_uart_tx.rs +++ b/dma_gpio/src/software_uart/gpio_dma_uart_tx.rs @@ -4,7 +4,7 @@ use embassy_stm32::{ peripherals::GPDMA1_CH0, Peri, }; -use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe}; +use embassy_stm32::dma::WritableRingBuffer; // kapitola 17.4.11 - 2 casovace pre 2 DMA pub const TIM6_UP_REQ: Request = 4; // Table 137: tim6_upd_dma, strana 687 STM32U5xx datasheet @@ -138,9 +138,10 @@ pub fn encode_uart_byte_cfg( idx } -// Push UART frames for a whole byte slice into a Pipe. -pub async fn write_uart_frames_to_pipe( - pipe: &Pipe, +/// Push UART frames into the DMA-backed TX ring non-blockingly. +/// Automatically waits for free space when ring is full. +pub async fn write_uart_frames_to_ring( + ring: &mut WritableRingBuffer<'static, u32>, pin_bit: u8, bytes: &[u8], cfg: &UartConfig, @@ -148,21 +149,8 @@ pub async fn write_uart_frames_to_pipe( for &b in bytes { let mut frame = [0u32; 12]; let used = encode_uart_byte_cfg(pin_bit, b, cfg, &mut frame); - for w in &frame[..used] { - pipe.write(&w.to_le_bytes()).await; - } - } -} -// Optional: emit a BREAK (line LOW for 'bits' bit-times). -pub async fn write_break_to_pipe( - pipe: &Pipe, - pin_bit: u8, - bits: usize, -) { - let set_low = |bit: u8| -> u32 { 1u32 << (bit as u32 + 16) }; - let word = set_low(pin_bit); - for _ in 0..bits { - pipe.write(&word.to_le_bytes()).await; + // Will wait until all words are written + ring.write_exact(&frame[..used]).await.unwrap(); } } diff --git a/dma_gpio/src/software_uart/runtime.rs b/dma_gpio/src/software_uart/runtime.rs index c439db0..48fbe36 100644 --- a/dma_gpio/src/software_uart/runtime.rs +++ b/dma_gpio/src/software_uart/runtime.rs @@ -1,16 +1,13 @@ // src/software_uart/runtime.rs use embassy_executor::task; -use embassy_stm32::pac::GPIOA; use embassy_stm32::{ - peripherals::{GPDMA1_CH0, GPDMA1_CH1}, + peripherals::GPDMA1_CH1, Peri, }; use embassy_stm32::dma::{ ReadableRingBuffer as DmaRingRx, - WritableRingBuffer as DmaRingTx, TransferOptions, }; -use crate::software_uart::gpio_dma_uart_tx::TIM6_UP_REQ; use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe}; use crate::software_uart::gpio_dma_uart_rx::TIM7_UP_REQ; @@ -37,29 +34,3 @@ pub async fn rx_dma_task( pipe_rx.write(&chunk).await; } } - -/// TX DMA ring task: streams u32 BSRR words paced by TIM6. -#[task] -pub async fn tx_dma_task( - ch: Peri<'static, GPDMA1_CH0>, - ring_mem: &'static mut [u32], -) { - let bsrr_ptr = GPIOA.bsrr().as_ptr() as *mut u32; - - let mut opts = TransferOptions::default(); - opts.half_transfer_ir = true; - opts.complete_transfer_ir = true; - - // SAFETY: ring_mem is exclusive here, bsrr_ptr valid, paced by TIM6 - let mut tx = unsafe { - DmaRingTx::::new(ch, TIM6_UP_REQ, bsrr_ptr, ring_mem, opts) - }; - - tx.start(); - defmt::info!("TX DMA ring started"); - - // The DMA now streams ring_mem. - loop { - // embassy_futures::yield_now().await; - } -}