156 lines
4.2 KiB
Rust
156 lines
4.2 KiB
Rust
// src/bin/main.rs
|
|
|
|
#![no_std]
|
|
#![no_main]
|
|
|
|
use defmt::*;
|
|
use embassy_executor::Spawner;
|
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
|
use embassy_time::{Duration, Timer};
|
|
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 {defmt_rtt as _, panic_probe as _};
|
|
|
|
use embassy_stm32::{
|
|
gpio::{Level, Output, Speed},
|
|
peripherals::GPDMA1_CH0,
|
|
peripherals::GPDMA1_CH1,
|
|
};
|
|
use embassy_stm32::Peri;
|
|
|
|
use dma_gpio::gpio_dma_uart_tx::{
|
|
write_uart_frames_to_pipe, GpioDmaBsrrTx, Parity, StopBits, UartConfig,
|
|
};
|
|
|
|
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
|
|
const BAUD: u32 = 115_200;
|
|
const TX_PIN_BIT: u8 = 2; // PA2
|
|
const TX_OVERSAMPLE: u16 = 1;
|
|
const RX_OVERSAMPLE: u16 = 16;
|
|
|
|
const UART_CFG: UartConfig = UartConfig {
|
|
data_bits: 8,
|
|
parity: Parity::None,
|
|
stop_bits: StopBits::One,
|
|
};
|
|
static mut RX_DMA_BUF: [u32; 512] = [0; 512];
|
|
|
|
fn dump_tim6_regs() {
|
|
// PAC path for STM32U5: module `tim6`, type `Tim6` with ptr()
|
|
use embassy_stm32::pac::timer::TimBasic;
|
|
let tim = unsafe { TimBasic::from_ptr(0x4000_1000usize as _) };
|
|
let sr = tim.sr().read();
|
|
let dier = tim.dier().read();
|
|
let cr1 = tim.cr1().read();
|
|
let arr = tim.arr().read().arr();
|
|
let psc = tim.psc().read();
|
|
info!(
|
|
"TIM6: CR1.CEN={} DIER.UDE={} SR.UIF={} PSC={} ARR={}",
|
|
cr1.cen(),
|
|
dier.ude(),
|
|
sr.uif(),
|
|
psc,
|
|
arr
|
|
);
|
|
}
|
|
|
|
fn dump_dma_ch0_regs() {
|
|
// PAC path for GPDMA1: module `gpdma1`, type `Gpdma1`
|
|
use embassy_stm32::pac::gpdma::Gpdma;
|
|
let dma = unsafe { Gpdma::from_ptr(0x4002_0000usize as _) };
|
|
let ch = dma.ch(0);
|
|
let cr = ch.cr().read();
|
|
let tr1 = ch.tr1().read();
|
|
let tr2 = ch.tr2().read();
|
|
let br1 = ch.br1().read();
|
|
info!(
|
|
"GPDMA1_CH0: EN={} PRIO={} SDW={} DDW={} SINC={} DINC={} REQSEL={} SWREQ={} DREQ={} BNDT={}",
|
|
cr.en(),
|
|
cr.prio(),
|
|
tr1.sdw(),
|
|
tr1.ddw(),
|
|
tr1.sinc(),
|
|
tr1.dinc(),
|
|
tr2.reqsel(),
|
|
tr2.swreq(),
|
|
tr2.dreq(),
|
|
br1.bndt()
|
|
);
|
|
}
|
|
|
|
#[embassy_executor::main]
|
|
async fn main(spawner: Spawner) {
|
|
let p = embassy_stm32::init(Default::default());
|
|
info!("Hehe");
|
|
|
|
// PA3 as Rx "wire"
|
|
let pa3_rx = Input::new(p.PA3, Pull::Up);
|
|
|
|
// PA2 is the TX "wire"
|
|
let _pa2 = Output::new(p.PA2, Level::High, Speed::VeryHigh);
|
|
// drop(_pa2);
|
|
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE); // TX
|
|
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE); // RX
|
|
dump_tim6_regs();
|
|
|
|
// Start DMA consumer task
|
|
spawner.spawn(dma_tx_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 {
|
|
write_uart_frames_to_pipe(
|
|
&PIPE_TX,
|
|
TX_PIN_BIT,
|
|
b"Hello marshmallow\r\n",
|
|
&UART_CFG,
|
|
).await;
|
|
Timer::after(Duration::from_secs(2)).await;
|
|
}
|
|
}
|
|
|
|
#[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;
|
|
}
|
|
|
|
#[embassy_executor::task]
|
|
async fn dma_tx_task(ch: Peri<'static, GPDMA1_CH0>) {
|
|
let mut tx = GpioDmaBsrrTx::new(ch);
|
|
|
|
info!("DMA task started, waiting for frames...");
|
|
loop {
|
|
// Read one 32-bit BSRR word (4 bytes) from the Pipe
|
|
let mut b = [0u8; 4];
|
|
let n = PIPE_TX.read(&mut b).await;
|
|
if n != 4 {
|
|
continue;
|
|
}
|
|
let w = u32::from_le_bytes(b);
|
|
|
|
info!("DMA write 0x{:08X} -> GPIOA.BSRR", w);
|
|
match embassy_time::with_timeout(
|
|
Duration::from_millis(20),
|
|
tx.write_word(w),
|
|
)
|
|
.await
|
|
{
|
|
Ok(()) => {}
|
|
Err(_) => {
|
|
warn!("DMA timeout: no TIM6 request");
|
|
dump_tim6_regs();
|
|
dump_dma_ch0_regs();
|
|
}
|
|
}
|
|
}
|
|
}
|