working now pushing to the ring buffer
This commit is contained in:
@@ -9,10 +9,13 @@ use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
|||||||
use embassy_time::{Duration, Timer};
|
use embassy_time::{Duration, Timer};
|
||||||
use dma_gpio::software_uart::{
|
use dma_gpio::software_uart::{
|
||||||
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
||||||
gpio_dma_uart_tx::{write_uart_frames_to_pipe, UartConfig, Parity, StopBits},
|
gpio_dma_uart_tx::{
|
||||||
runtime::{rx_dma_task, tx_dma_task},
|
write_uart_frames_to_ring, Parity, StopBits, UartConfig, TIM6_UP_REQ,
|
||||||
|
},
|
||||||
|
runtime::rx_dma_task,
|
||||||
debug::dump_tim6_regs,
|
debug::dump_tim6_regs,
|
||||||
};
|
};
|
||||||
|
use embassy_stm32::dma::{TransferOptions, WritableRingBuffer};
|
||||||
use static_cell::StaticCell;
|
use static_cell::StaticCell;
|
||||||
use {defmt_rtt as _, panic_probe as _};
|
use {defmt_rtt as _, panic_probe as _};
|
||||||
|
|
||||||
@@ -23,12 +26,11 @@ const TX_OVERSAMPLE: u16 = 1;
|
|||||||
const RX_OVERSAMPLE: u16 = 16;
|
const RX_OVERSAMPLE: u16 = 16;
|
||||||
const RX_RING_BYTES: usize = 4096;
|
const RX_RING_BYTES: usize = 4096;
|
||||||
const TX_RING_BYTES: usize = 4096;
|
const TX_RING_BYTES: usize = 4096;
|
||||||
|
|
||||||
// Nemoze by generic, v taskoch treba manualne zmenit
|
// Nemoze by generic, v taskoch treba manualne zmenit
|
||||||
// Compiler upozorni, takze ostava takto
|
// Compiler upozorni, takze ostava takto
|
||||||
const PIPE_TX_SIZE: usize = 256;
|
|
||||||
const PIPE_RX_SIZE: usize = 256;
|
const PIPE_RX_SIZE: usize = 256;
|
||||||
|
|
||||||
static PIPE_TX: Pipe<CriticalSectionRawMutex, PIPE_TX_SIZE> = Pipe::new();
|
|
||||||
static PIPE_RX: Pipe<CriticalSectionRawMutex, PIPE_RX_SIZE> = Pipe::new();
|
static PIPE_RX: Pipe<CriticalSectionRawMutex, PIPE_RX_SIZE> = Pipe::new();
|
||||||
static RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
|
static RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
|
||||||
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
static TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
|
||||||
@@ -38,21 +40,41 @@ 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, 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);
|
||||||
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE);
|
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE);
|
||||||
|
|
||||||
dump_tim6_regs();
|
dump_tim6_regs();
|
||||||
|
|
||||||
// Safe one-time init from StaticCell
|
// Safe one-time init from StaticCell
|
||||||
let rx_ring: &mut [u8; RX_RING_BYTES] = RX_RING.init([0; RX_RING_BYTES]);
|
let rx_ring: &mut [u8; RX_RING_BYTES] = RX_RING.init([0; RX_RING_BYTES]);
|
||||||
let tx_ring: &mut [u32; TX_RING_BYTES] = TX_RING.init([0; TX_RING_BYTES]);
|
let tx_ring_mem: &mut [u32; TX_RING_BYTES] =
|
||||||
|
TX_RING.init([0; TX_RING_BYTES]);
|
||||||
|
|
||||||
// Spawn tasks
|
// Spawn tasks
|
||||||
spawner.spawn(tx_dma_task(p.GPDMA1_CH0, tx_ring).unwrap());
|
|
||||||
spawner.spawn(rx_dma_task(p.GPDMA1_CH1, &PIPE_RX, rx_ring).unwrap());
|
spawner.spawn(rx_dma_task(p.GPDMA1_CH1, &PIPE_RX, rx_ring).unwrap());
|
||||||
|
|
||||||
|
// Create and start the TX DMA ring in main.
|
||||||
|
let bsrr_ptr = embassy_stm32::pac::GPIOA.bsrr().as_ptr() as *mut u32;
|
||||||
|
let mut tx_opts = TransferOptions::default();
|
||||||
|
tx_opts.half_transfer_ir = true;
|
||||||
|
tx_opts.complete_transfer_ir = true;
|
||||||
|
|
||||||
|
// SAFETY: tx_ring_mem is exclusive, bsrr_ptr points to GPIOA BSRR, paced by TIM6.
|
||||||
|
let mut tx_ring = unsafe {
|
||||||
|
WritableRingBuffer::new(
|
||||||
|
p.GPDMA1_CH0,
|
||||||
|
TIM6_UP_REQ,
|
||||||
|
bsrr_ptr,
|
||||||
|
tx_ring_mem,
|
||||||
|
tx_opts,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
tx_ring.start();
|
||||||
|
info!("TX DMA ring started");
|
||||||
|
|
||||||
let uart_cfg = UartConfig {
|
let uart_cfg = UartConfig {
|
||||||
data_bits: 8,
|
data_bits: 8,
|
||||||
parity: Parity::None,
|
parity: Parity::None,
|
||||||
@@ -60,7 +82,13 @@ async fn main(spawner: Spawner) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
write_uart_frames_to_pipe(&PIPE_TX, TX_PIN_BIT, b"Hello marshmallow\r\n", &uart_cfg).await;
|
write_uart_frames_to_ring(
|
||||||
|
&mut tx_ring,
|
||||||
|
TX_PIN_BIT,
|
||||||
|
b"Hello marshmallow\r\n",
|
||||||
|
&uart_cfg,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
Timer::after(Duration::from_secs(2)).await;
|
Timer::after(Duration::from_secs(2)).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ use embassy_stm32::{
|
|||||||
peripherals::GPDMA1_CH0,
|
peripherals::GPDMA1_CH0,
|
||||||
Peri,
|
Peri,
|
||||||
};
|
};
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
use embassy_stm32::dma::WritableRingBuffer;
|
||||||
|
|
||||||
// kapitola 17.4.11 - 2 casovace pre 2 DMA
|
// kapitola 17.4.11 - 2 casovace pre 2 DMA
|
||||||
pub const TIM6_UP_REQ: Request = 4; // Table 137: tim6_upd_dma, strana 687 STM32U5xx datasheet
|
pub const TIM6_UP_REQ: Request = 4; // Table 137: tim6_upd_dma, strana 687 STM32U5xx datasheet
|
||||||
@@ -138,9 +138,10 @@ pub fn encode_uart_byte_cfg(
|
|||||||
idx
|
idx
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push UART frames for a whole byte slice into a Pipe.
|
/// Push UART frames into the DMA-backed TX ring non-blockingly.
|
||||||
pub async fn write_uart_frames_to_pipe<const N: usize>(
|
/// Automatically waits for free space when ring is full.
|
||||||
pipe: &Pipe<CriticalSectionRawMutex, N>,
|
pub async fn write_uart_frames_to_ring(
|
||||||
|
ring: &mut WritableRingBuffer<'static, u32>,
|
||||||
pin_bit: u8,
|
pin_bit: u8,
|
||||||
bytes: &[u8],
|
bytes: &[u8],
|
||||||
cfg: &UartConfig,
|
cfg: &UartConfig,
|
||||||
@@ -148,21 +149,8 @@ pub async fn write_uart_frames_to_pipe<const N: usize>(
|
|||||||
for &b in bytes {
|
for &b in bytes {
|
||||||
let mut frame = [0u32; 12];
|
let mut frame = [0u32; 12];
|
||||||
let used = encode_uart_byte_cfg(pin_bit, b, cfg, &mut frame);
|
let used = encode_uart_byte_cfg(pin_bit, b, cfg, &mut frame);
|
||||||
for w in &frame[..used] {
|
|
||||||
pipe.write(&w.to_le_bytes()).await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optional: emit a BREAK (line LOW for 'bits' bit-times).
|
// Will wait until all words are written
|
||||||
pub async fn write_break_to_pipe<const N: usize>(
|
ring.write_exact(&frame[..used]).await.unwrap();
|
||||||
pipe: &Pipe<CriticalSectionRawMutex, N>,
|
|
||||||
pin_bit: u8,
|
|
||||||
bits: usize,
|
|
||||||
) {
|
|
||||||
let set_low = |bit: u8| -> u32 { 1u32 << (bit as u32 + 16) };
|
|
||||||
let word = set_low(pin_bit);
|
|
||||||
for _ in 0..bits {
|
|
||||||
pipe.write(&word.to_le_bytes()).await;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,16 +1,13 @@
|
|||||||
// src/software_uart/runtime.rs
|
// src/software_uart/runtime.rs
|
||||||
use embassy_executor::task;
|
use embassy_executor::task;
|
||||||
use embassy_stm32::pac::GPIOA;
|
|
||||||
use embassy_stm32::{
|
use embassy_stm32::{
|
||||||
peripherals::{GPDMA1_CH0, GPDMA1_CH1},
|
peripherals::GPDMA1_CH1,
|
||||||
Peri,
|
Peri,
|
||||||
};
|
};
|
||||||
use embassy_stm32::dma::{
|
use embassy_stm32::dma::{
|
||||||
ReadableRingBuffer as DmaRingRx,
|
ReadableRingBuffer as DmaRingRx,
|
||||||
WritableRingBuffer as DmaRingTx,
|
|
||||||
TransferOptions,
|
TransferOptions,
|
||||||
};
|
};
|
||||||
use crate::software_uart::gpio_dma_uart_tx::TIM6_UP_REQ;
|
|
||||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
||||||
use crate::software_uart::gpio_dma_uart_rx::TIM7_UP_REQ;
|
use crate::software_uart::gpio_dma_uart_rx::TIM7_UP_REQ;
|
||||||
|
|
||||||
@@ -37,29 +34,3 @@ pub async fn rx_dma_task(
|
|||||||
pipe_rx.write(&chunk).await;
|
pipe_rx.write(&chunk).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// TX DMA ring task: streams u32 BSRR words paced by TIM6.
|
|
||||||
#[task]
|
|
||||||
pub async fn tx_dma_task(
|
|
||||||
ch: Peri<'static, GPDMA1_CH0>,
|
|
||||||
ring_mem: &'static mut [u32],
|
|
||||||
) {
|
|
||||||
let bsrr_ptr = GPIOA.bsrr().as_ptr() as *mut u32;
|
|
||||||
|
|
||||||
let mut opts = TransferOptions::default();
|
|
||||||
opts.half_transfer_ir = true;
|
|
||||||
opts.complete_transfer_ir = true;
|
|
||||||
|
|
||||||
// SAFETY: ring_mem is exclusive here, bsrr_ptr valid, paced by TIM6
|
|
||||||
let mut tx = unsafe {
|
|
||||||
DmaRingTx::<u32>::new(ch, TIM6_UP_REQ, bsrr_ptr, ring_mem, opts)
|
|
||||||
};
|
|
||||||
|
|
||||||
tx.start();
|
|
||||||
defmt::info!("TX DMA ring started");
|
|
||||||
|
|
||||||
// The DMA now streams ring_mem.
|
|
||||||
loop {
|
|
||||||
// embassy_futures::yield_now().await;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
Reference in New Issue
Block a user