166 lines
4.5 KiB
Rust
166 lines
4.5 KiB
Rust
// src/bin/main.rs
|
|
#![no_std]
|
|
#![no_main]
|
|
|
|
use defmt::*;
|
|
use embassy_executor::Spawner;
|
|
use embassy_futures::yield_now;
|
|
use embassy_stm32::dma::Request;
|
|
use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed};
|
|
use embassy_time::{Duration, Timer};
|
|
use embassy_stm32::dma::{TransferOptions, WritableRingBuffer};
|
|
use dma_gpio::software_uart::{
|
|
dma_timer::init_tim6_for_uart,
|
|
gpio_dma_uart_tx::encode_uart_frames,
|
|
debug::dump_tim6_regs,
|
|
};
|
|
use dma_gpio::config::{BAUD, TX_PIN_BIT, TX_OVERSAMPLE, TX_RING_BYTES};
|
|
use static_cell::StaticCell;
|
|
use {defmt_rtt as _, panic_probe as _};
|
|
|
|
pub const TIM6_UP_REQ: Request = 4;
|
|
|
|
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
|
|
|
#[embassy_executor::main]
|
|
async fn main(_spawner: Spawner) {
|
|
let p = embassy_stm32::init(Default::default());
|
|
info!("Hehe");
|
|
|
|
let _rx = Input::new(p.PA3, embassy_stm32::gpio::Pull::Up);
|
|
let _tx = Output::new(p.PA2, Level::High, Speed::VeryHigh);
|
|
|
|
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE);
|
|
dump_tim6_regs();
|
|
|
|
let idle: u32 = 1u32 << TX_PIN_BIT;
|
|
|
|
// Ring initialized to idle (line high).
|
|
let tx_ring_mem: &mut [u32; TX_RING_BYTES] = TX_RING.init([0; TX_RING_BYTES]);
|
|
|
|
let odr_ptr = embassy_stm32::pac::GPIOA.odr().as_ptr() as *mut u32;
|
|
|
|
let mut tx_opts = TransferOptions::default();
|
|
tx_opts.half_transfer_ir = true;
|
|
tx_opts.complete_transfer_ir = true;
|
|
|
|
let mut tx_ring = unsafe {
|
|
WritableRingBuffer::new(
|
|
p.GPDMA1_CH0,
|
|
TIM6_UP_REQ,
|
|
odr_ptr,
|
|
tx_ring_mem,
|
|
tx_opts,
|
|
)
|
|
};
|
|
|
|
{
|
|
// Full idle buffer matching ring capacity.
|
|
let idle_buf = [idle; TX_RING_BYTES];
|
|
|
|
let written = tx_ring
|
|
.write_exact(&idle_buf)
|
|
.await
|
|
.expect("Failed to prefill TX ring with idle");
|
|
|
|
info!(
|
|
"TX ring prefilled with idle via write_exact: written={} cap={}",
|
|
written,
|
|
tx_ring.capacity()
|
|
);
|
|
}
|
|
|
|
tx_ring.start();
|
|
info!(
|
|
"TX DMA ring started: cap_words={}",
|
|
tx_ring.capacity()
|
|
);
|
|
unsafe {
|
|
use embassy_stm32::pac::gpdma::Gpdma;
|
|
let dma = Gpdma::from_ptr(0x4002_0000 as _); // GPDMA1 base for STM32U5
|
|
let ch = dma.ch(0); // Channel 0
|
|
|
|
let cr = ch.cr().read();
|
|
let tr1 = ch.tr1().read();
|
|
let tr2 = ch.tr2().read();
|
|
let br1 = ch.br1().read();
|
|
let sar = ch.sar().read();
|
|
let dar = ch.dar().read();
|
|
let llr = ch.llr().read();
|
|
let lbar = ch.lbar().read();
|
|
|
|
info!(
|
|
"GPDMA1_CH0: EN={} HTIE={} TCIE={} SDW={:?} DDW={:?} SINC={} DINC={} BNDT={} SAR=0x{:08x} DAR=0x{:08x}",
|
|
cr.en(),
|
|
cr.htie(),
|
|
cr.tcie(),
|
|
tr1.sdw(),
|
|
tr1.ddw(),
|
|
tr1.sinc(),
|
|
tr1.dinc(),
|
|
br1.bndt(),
|
|
sar, // already u32
|
|
dar, // already u32
|
|
);
|
|
info!(
|
|
"GPDMA1_CH0: LBAR=0x{:08x} LLR=0x{:08x}",
|
|
lbar.lba(),
|
|
llr.0
|
|
);
|
|
}
|
|
|
|
let mut frame_buf = [0u32; 4096];
|
|
|
|
loop {
|
|
info!("tick start");
|
|
Timer::after(Duration::from_millis(1021)).await;
|
|
//info!("tick end");
|
|
|
|
let used = encode_uart_frames(
|
|
TX_PIN_BIT,
|
|
b"H\r\n",
|
|
&mut frame_buf,
|
|
)
|
|
.await;
|
|
|
|
if used == 0 {
|
|
info!("encode_uart_frames() produced 0 words, skipping write");
|
|
yield_now().await;
|
|
continue;
|
|
}
|
|
|
|
// Debug: confirm encoded content.
|
|
let preview = core::cmp::min(used, 32);
|
|
info!(
|
|
"TX frame used={} words, head={=[?]}",
|
|
used,
|
|
&frame_buf[..preview]
|
|
);
|
|
|
|
// Now it is safe to call write_exact.
|
|
match tx_ring.write_exact(&frame_buf[..used]).await {
|
|
Ok(written) => {
|
|
let len = tx_ring.len().unwrap_or(0);
|
|
info!(
|
|
"write_exact ok: written={} ring_used={} ring_cap={}",
|
|
written,
|
|
len,
|
|
tx_ring.capacity()
|
|
);
|
|
}
|
|
Err(e) => {
|
|
let len = tx_ring.len().unwrap_or(0);
|
|
warn!(
|
|
"write_exact error: {:?}, ring_used={} ring_cap={}",
|
|
e,
|
|
len,
|
|
tx_ring.capacity()
|
|
);
|
|
}
|
|
}
|
|
|
|
info!("tick end");
|
|
yield_now().await;
|
|
}
|
|
}
|