compiled from main branch working with LLI DMA

This commit is contained in:
Priec
2025-10-31 23:04:48 +01:00
parent 1a4c071417
commit f24bd73c6b
3 changed files with 409 additions and 49 deletions

View File

@@ -11,7 +11,8 @@ use dma_gpio::dma_timer::init_tim6_for_uart;
use dma_gpio::dma_timer::init_tim7_for_uart;
use embassy_stm32::gpio::Input;
use embassy_stm32::gpio::Pull;
use dma_gpio::gpio_dma_uart_rx::GpioDmaRx;
use dma_gpio::gpio_dma_uart_rx::TIM7_UP_REQ;
use embassy_stm32::dma::{ReadableRingBuffer as DmaRingRx, TransferOptions};
use {defmt_rtt as _, panic_probe as _};
use embassy_stm32::{
@@ -33,13 +34,14 @@ 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 UART_CFG: UartConfig = UartConfig {
data_bits: 8,
parity: Parity::None,
stop_bits: StopBits::One,
};
static mut RX_DMA_BUF: [u32; 512] = [0; 512];
static mut RX_RING: [u8; RX_RING_BYTES] = [0; RX_RING_BYTES];
fn dump_tim6_regs() {
// PAC path for STM32U5: module `tim6`, type `Tim6` with ptr()
@@ -100,8 +102,8 @@ async fn main(spawner: Spawner) {
dump_tim6_regs();
// Start DMA consumer task
spawner.spawn(tx_dma_task(p.GPDMA1_CH0)).unwrap();
spawner.spawn(rx_dma_task(p.GPDMA1_CH1)).unwrap();
spawner.spawn(tx_dma_task(p.GPDMA1_CH0).unwrap());
spawner.spawn(rx_dma_task(p.GPDMA1_CH1).unwrap());
// Example: transmit a string as UART frames via the Pipe
loop {
@@ -117,10 +119,31 @@ async fn main(spawner: Spawner) {
#[embassy_executor::task]
async fn rx_dma_task(ch: Peri<'static, GPDMA1_CH1>) {
let buf_ptr = core::ptr::addr_of_mut!(RX_DMA_BUF);
let buf = unsafe { &mut *buf_ptr };
let mut rx = GpioDmaRx::new(ch, 3 /*PA3 bit*/, buf, &PIPE_RX);
rx.run().await;
// SAFETY: this task owns the ring buffer exclusively (Rust 2024: avoid &mut static directly).
let ring_ptr = core::ptr::addr_of_mut!(RX_RING);
let ring = unsafe { &mut *ring_ptr };
// Sample the low byte of GPIOA.IDR (PA0..PA7). PA3 is bit 3, so that's within this byte.
let idr_low_byte = embassy_stm32::pac::GPIOA.idr().as_ptr() as *mut u8;
let mut opts = TransferOptions::default();
// Enable HT/TC IRQ so read_exact can await naturally.
opts.half_transfer_ir = true;
opts.complete_transfer_ir = true;
// Start hardware-linked circular DMA into ring.
let mut rx = unsafe { DmaRingRx::new(ch, TIM7_UP_REQ, idr_low_byte, ring, opts) };
rx.start();
// Drain in fixed chunks when CPU has time; DMA keeps running regardless.
let mut chunk = [0u8; 256];
loop {
// Wait for a full chunk; wakes on half/full buffer events
let _ = rx.read_exact(&mut chunk).await;
// Forward raw samples to PIPE_RX (decode later if desired)
PIPE_RX.write(&chunk).await;
}
}
#[embassy_executor::task]