working write immidiate

This commit is contained in:
Priec
2025-11-07 21:23:31 +01:00
parent f2fda10c7a
commit 6620f9ad2b
3 changed files with 114 additions and 52 deletions

16
dma_gpio2/Cargo.lock generated
View File

@@ -295,7 +295,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-embedded-hal" name = "embassy-embedded-hal"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"defmt 1.0.1", "defmt 1.0.1",
"embassy-futures", "embassy-futures",
@@ -313,7 +312,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-executor" name = "embassy-executor"
version = "0.9.1" version = "0.9.1"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"cordyceps", "cordyceps",
"cortex-m", "cortex-m",
@@ -326,7 +324,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-executor-macros" name = "embassy-executor-macros"
version = "0.7.0" version = "0.7.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
@@ -337,17 +334,14 @@ dependencies = [
[[package]] [[package]]
name = "embassy-executor-timer-queue" name = "embassy-executor-timer-queue"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
[[package]] [[package]]
name = "embassy-futures" name = "embassy-futures"
version = "0.1.2" version = "0.1.2"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
[[package]] [[package]]
name = "embassy-hal-internal" name = "embassy-hal-internal"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"cortex-m", "cortex-m",
"critical-section", "critical-section",
@@ -358,7 +352,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-net-driver" name = "embassy-net-driver"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"defmt 1.0.1", "defmt 1.0.1",
] ]
@@ -366,7 +359,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-net-driver-channel" name = "embassy-net-driver-channel"
version = "0.3.2" version = "0.3.2"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"embassy-futures", "embassy-futures",
"embassy-net-driver", "embassy-net-driver",
@@ -376,7 +368,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-stm32" name = "embassy-stm32"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"aligned", "aligned",
"bit_field", "bit_field",
@@ -425,7 +416,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-sync" name = "embassy-sync"
version = "0.7.2" version = "0.7.2"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"critical-section", "critical-section",
@@ -439,7 +429,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-time" name = "embassy-time"
version = "0.5.0" version = "0.5.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"critical-section", "critical-section",
@@ -455,7 +444,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-time-driver" name = "embassy-time-driver"
version = "0.2.1" version = "0.2.1"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"document-features", "document-features",
] ]
@@ -463,7 +451,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-time-queue-utils" name = "embassy-time-queue-utils"
version = "0.3.0" version = "0.3.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"embassy-executor-timer-queue", "embassy-executor-timer-queue",
"heapless 0.8.0", "heapless 0.8.0",
@@ -472,7 +459,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-usb" name = "embassy-usb"
version = "0.5.1" version = "0.5.1"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"embassy-futures", "embassy-futures",
"embassy-net-driver-channel", "embassy-net-driver-channel",
@@ -487,7 +473,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-usb-driver" name = "embassy-usb-driver"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"defmt 1.0.1", "defmt 1.0.1",
"embedded-io-async", "embedded-io-async",
@@ -496,7 +481,6 @@ dependencies = [
[[package]] [[package]]
name = "embassy-usb-synopsys-otg" name = "embassy-usb-synopsys-otg"
version = "0.3.1" version = "0.3.1"
source = "git+https://github.com/embassy-rs/embassy.git?branch=main#9b1add3d83e98c6c9ae9230bf35cd89bba530a20"
dependencies = [ dependencies = [
"critical-section", "critical-section",
"defmt 1.0.1", "defmt 1.0.1",

View File

@@ -10,13 +10,13 @@ cortex-m = { version = "0.7.7", features = ["inline-asm", "critical-section-sing
cortex-m-rt = "0.7.5" cortex-m-rt = "0.7.5"
panic-halt = "1.0.0" panic-halt = "1.0.0"
embassy-executor = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["arch-cortex-m", "executor-thread"] } embassy-executor = { path = "/home/filip/programs/embassy/embassy-executor", features = ["arch-cortex-m", "executor-thread"] }
embassy-futures = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } embassy-futures = { path = "/home/filip/programs/embassy/embassy-futures" }
embassy-sync = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } embassy-sync = { path = "/home/filip/programs/embassy/embassy-sync" }
embassy-time = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["tick-hz-32_768"] } embassy-time = { path = "/home/filip/programs/embassy/embassy-time", features = ["tick-hz-32_768"] }
embassy-hal-internal = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } embassy-hal-internal = { path = "/home/filip/programs/embassy/embassy-hal-internal" }
embassy-usb = { git = "https://github.com/embassy-rs/embassy.git", branch = "main" } embassy-usb = { path = "/home/filip/programs/embassy/embassy-usb" }
embassy-stm32 = { git = "https://github.com/embassy-rs/embassy.git", branch = "main", features = ["unstable-pac", "stm32u575zi", "time-driver-tim2", "memory-x", "defmt"] } embassy-stm32 = { path = "/home/filip/programs/embassy/embassy-stm32", features = ["unstable-pac", "stm32u575zi", "time-driver-tim2", "memory-x", "defmt"] }
embedded-hal = "1.0.0" embedded-hal = "1.0.0"
embedded-graphics = "0.8.1" embedded-graphics = "0.8.1"

View File

@@ -7,7 +7,6 @@ use embassy_executor::Spawner;
use embassy_futures::yield_now; use embassy_futures::yield_now;
use embassy_stm32::dma::Request; use embassy_stm32::dma::Request;
use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed}; use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed};
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
use embassy_time::{Duration, Timer}; use embassy_time::{Duration, Timer};
use embassy_stm32::dma::{TransferOptions, WritableRingBuffer}; use embassy_stm32::dma::{TransferOptions, WritableRingBuffer};
use dma_gpio::software_uart::{ use dma_gpio::software_uart::{
@@ -15,57 +14,59 @@ use dma_gpio::software_uart::{
gpio_dma_uart_tx::encode_uart_frames, gpio_dma_uart_tx::encode_uart_frames,
debug::dump_tim6_regs, debug::dump_tim6_regs,
}; };
use dma_gpio::config::{BAUD, TX_PIN_BIT, RX_OVERSAMPLE, TX_OVERSAMPLE}; use dma_gpio::config::{BAUD, TX_PIN_BIT, TX_OVERSAMPLE, TX_RING_BYTES};
use dma_gpio::config::{TX_RING_BYTES, RX_RING_BYTES, PIPE_RX_SIZE};
use static_cell::StaticCell; use static_cell::StaticCell;
use {defmt_rtt as _, panic_probe as _}; use {defmt_rtt as _, panic_probe as _};
// kapitola 17.4.11 - 2 casovace pre 2 DMA pub const TIM6_UP_REQ: Request = 4;
pub const TIM6_UP_REQ: Request = 4; // Table 137: tim6_upd_dma, strana 687 STM32U5xx datasheet
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new(); static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
use core::future::poll_fn; use core::future::poll_fn;
use core::task::Poll; use core::task::Poll;
async fn wait_for_space<'a, W: embassy_stm32::dma::word::Word>( // Wait until there is at least `needed` free space in the TX ring.
ring: &mut embassy_stm32::dma::WritableRingBuffer<'a, W>, async fn wait_for_space<'a>(
min_free: usize, ring: &mut WritableRingBuffer<'a, u32>,
needed: usize,
) { ) {
poll_fn(|cx| { poll_fn(|cx| {
let used = ring.len().unwrap_or(0);
let cap = ring.capacity(); let cap = ring.capacity();
if cap - used > min_free { let used = ring.len().unwrap_or(0);
let free = cap.saturating_sub(used);
if free >= needed {
Poll::Ready(()) Poll::Ready(())
} else { } else {
ring.set_waker(cx.waker()); ring.set_waker(cx.waker());
Poll::Pending Poll::Pending
} }
}).await })
.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!("Hehe"); info!("Hehe");
let _rx = Input::new(p.PA3, Pull::Up); let _rx = Input::new(p.PA3, embassy_stm32::gpio::Pull::Up);
let _tx = Output::new(p.PA2, Level::High, Speed::VeryHigh); let _tx = Output::new(p.PA2, Level::High, Speed::VeryHigh);
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE); init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE);
dump_tim6_regs(); dump_tim6_regs();
// Safe one-time init from StaticCell let idle: u32 = 1u32 << TX_PIN_BIT;
let tx_ring_mem: &mut [u32; TX_RING_BYTES] = TX_RING.init([0; TX_RING_BYTES]);
// Ring initialized to idle (line high).
let tx_ring_mem: &mut [u32; TX_RING_BYTES] = TX_RING.init([idle; TX_RING_BYTES]);
// Create and start the TX DMA ring in main.
// let bsrr_ptr = embassy_stm32::pac::GPIOA.bsrr().as_ptr() as *mut u32;
let odr_ptr = embassy_stm32::pac::GPIOA.odr().as_ptr() as *mut u32; let odr_ptr = embassy_stm32::pac::GPIOA.odr().as_ptr() as *mut u32;
let mut tx_opts = TransferOptions::default(); let mut tx_opts = TransferOptions::default();
tx_opts.half_transfer_ir = true; tx_opts.half_transfer_ir = true;
tx_opts.complete_transfer_ir = true; tx_opts.complete_transfer_ir = true;
// SAFETY: tx_ring_mem is exclusive
let mut tx_ring = unsafe { let mut tx_ring = unsafe {
WritableRingBuffer::new( WritableRingBuffer::new(
p.GPDMA1_CH0, p.GPDMA1_CH0,
@@ -75,9 +76,45 @@ async fn main(spawner: Spawner) {
tx_opts, tx_opts,
) )
}; };
// Start DMA
tx_ring.start(); tx_ring.start();
info!("TX DMA ring started"); 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]; let mut frame_buf = [0u32; 4096];
@@ -86,17 +123,58 @@ async fn main(spawner: Spawner) {
Timer::after(Duration::from_millis(400)).await; Timer::after(Duration::from_millis(400)).await;
info!("tick end"); info!("tick end");
let used = encode_uart_frames(TX_PIN_BIT, b"Hello marshmallow\r\n", &mut frame_buf).await; // Prepare scratch buffer with idle.
for w in frame_buf.iter_mut() {
// Wait for DMA to free space, async style *w = idle;
wait_for_space(&mut tx_ring, used / 2).await;
if let Err(e) = tx_ring.write_exact(&frame_buf[..used]).await {
warn!("DMA ring write error: {:?}", e);
} else {
info!("Frame queued to DMA ring");
} }
let used = encode_uart_frames(
TX_PIN_BIT,
b"Hello marshmallow\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]
);
// Wait until the ring has room for this frame.
wait_for_space(&mut tx_ring, used).await;
// Now it is safe to call write_exact.
match tx_ring.write_immediate(&frame_buf[..used]) {
Ok((written, remaining)) => {
let len = tx_ring.len().unwrap_or(0);
info!(
"write_immediate ok: written={} remaining={} ring_used={} ring_cap={}",
written,
remaining,
len,
tx_ring.capacity()
);
}
Err(e) => {
let len = tx_ring.len().unwrap_or(0);
warn!(
"write_immediate error: {:?}, ring_used={} ring_cap={}",
e,
len,
tx_ring.capacity()
);
}
}
yield_now().await; yield_now().await;
} }
} }