fixing and working nonstop without timout

This commit is contained in:
Priec
2025-11-09 19:29:49 +01:00
parent 6620f9ad2b
commit ef98b7e4e9
2 changed files with 36 additions and 42 deletions

View File

@@ -16,7 +16,7 @@ embassy-sync = { path = "/home/filip/programs/embassy/embassy-sync" }
embassy-time = { path = "/home/filip/programs/embassy/embassy-time", features = ["tick-hz-32_768"] }
embassy-hal-internal = { path = "/home/filip/programs/embassy/embassy-hal-internal" }
embassy-usb = { path = "/home/filip/programs/embassy/embassy-usb" }
embassy-stm32 = { path = "/home/filip/programs/embassy/embassy-stm32", 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", "dma_debug"] }
embedded-hal = "1.0.0"
embedded-graphics = "0.8.1"

View File

@@ -3,6 +3,7 @@
#![no_main]
use defmt::*;
use embassy_stm32::dma::ringbuffer::Error;
use embassy_executor::Spawner;
use embassy_futures::yield_now;
use embassy_stm32::dma::Request;
@@ -22,29 +23,6 @@ pub const TIM6_UP_REQ: Request = 4;
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
use core::future::poll_fn;
use core::task::Poll;
// Wait until there is at least `needed` free space in the TX ring.
async fn wait_for_space<'a>(
ring: &mut WritableRingBuffer<'a, u32>,
needed: usize,
) {
poll_fn(|cx| {
let cap = ring.capacity();
let used = ring.len().unwrap_or(0);
let free = cap.saturating_sub(used);
if free >= needed {
Poll::Ready(())
} else {
ring.set_waker(cx.waker());
Poll::Pending
}
})
.await
}
#[embassy_executor::main]
async fn main(_spawner: Spawner) {
let p = embassy_stm32::init(Default::default());
@@ -59,7 +37,7 @@ async fn main(_spawner: Spawner) {
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([idle; TX_RING_BYTES]);
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;
@@ -77,6 +55,22 @@ async fn main(_spawner: Spawner) {
)
};
{
// 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={}",
@@ -120,17 +114,12 @@ async fn main(_spawner: Spawner) {
loop {
info!("tick start");
Timer::after(Duration::from_millis(400)).await;
info!("tick end");
// Prepare scratch buffer with idle.
for w in frame_buf.iter_mut() {
*w = idle;
}
//Timer::after(Duration::from_millis(400)).await;
//info!("tick end");
let used = encode_uart_frames(
TX_PIN_BIT,
b"Hello marshmallow\r\n",
b"Hihihi\r\n",
&mut frame_buf,
)
.await;
@@ -149,17 +138,13 @@ async fn main(_spawner: Spawner) {
&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)) => {
match tx_ring.write_exact(&frame_buf[..used]).await {
Ok(written) => {
let len = tx_ring.len().unwrap_or(0);
info!(
"write_immediate ok: written={} remaining={} ring_used={} ring_cap={}",
"write_exact ok: written={} ring_used={} ring_cap={}",
written,
remaining,
len,
tx_ring.capacity()
);
@@ -167,14 +152,23 @@ async fn main(_spawner: Spawner) {
Err(e) => {
let len = tx_ring.len().unwrap_or(0);
warn!(
"write_immediate error: {:?}, ring_used={} ring_cap={}",
"write_exact error: {:?}, ring_used={} ring_cap={}",
e,
len,
tx_ring.capacity()
);
}
Err(Error::Overrun) => {
warn!("XYZ");
// DMA lapped you. Must resync:
tx_ring.request_reset(); // Stop DMA
tx_ring.clear(); // Clear buffer
tx_ring.start(); // Restart
// Retry writing frame
}
}
info!("tick end");
yield_now().await;
}
}