finished and fully functional
This commit is contained in:
@@ -3,47 +3,46 @@
|
||||
#![no_main]
|
||||
|
||||
use defmt::*;
|
||||
use core::cell::RefCell;
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use embassy_executor::Spawner;
|
||||
use embassy_time::Instant;
|
||||
use embassy_stm32::dma::Request;
|
||||
use embassy_stm32::gpio::{Input, Output, Level, Pull, Speed};
|
||||
use embassy_futures::yield_now;
|
||||
use embassy_sync::{
|
||||
blocking_mutex::raw::CriticalSectionRawMutex,
|
||||
channel::Channel,
|
||||
pipe::Pipe,
|
||||
};
|
||||
use embassy_time::{Duration, Instant, Timer};
|
||||
use embassy_stm32::{
|
||||
bind_interrupts,
|
||||
dma::Request,
|
||||
gpio::{Input, Level, Output, Pull, Speed},
|
||||
interrupt,
|
||||
pac,
|
||||
peripherals,
|
||||
rcc::{self, Pll, PllDiv, PllMul, PllPreDiv, PllSource, Sysclk},
|
||||
usart::{BufferedInterruptHandler, BufferedUart, Config},
|
||||
Config as CPUConfig,
|
||||
};
|
||||
use static_cell::StaticCell;
|
||||
use dma_gpio::config::{
|
||||
BAUD, PIPE_HW_RX, PIPE_HW_TX, PIPE_INT_RX, PIPE_INT_TX, PIPE_SW_RX,
|
||||
PIPE_SW_TX, RX_OVERSAMPLE, RX_RING_BYTES, TX_OVERSAMPLE, TX_RING_BYTES,
|
||||
UART_CFG,
|
||||
};
|
||||
use dma_gpio::hw_uart_pc::{driver::uart_task, usart1};
|
||||
use dma_gpio::hw_uart_internal::{
|
||||
driver::uart_task as uart_task_internal,
|
||||
usart2,
|
||||
};
|
||||
use dma_gpio::software_uart::{
|
||||
debug::dump_tim6_regs,
|
||||
decode_uart_samples,
|
||||
dma_timer::{init_tim6_for_uart, init_tim7_for_uart},
|
||||
gpio_dma_uart_rx::rx_dma_task,
|
||||
debug::dump_tim6_regs,
|
||||
gpio_dma_uart_tx::tx_dma_task,
|
||||
};
|
||||
use dma_gpio::config::{BAUD, RX_OVERSAMPLE, TX_OVERSAMPLE};
|
||||
use dma_gpio::config::{TX_RING_BYTES, RX_RING_BYTES};
|
||||
use dma_gpio::software_uart::gpio_dma_uart_tx::tx_dma_task;
|
||||
use static_cell::StaticCell;
|
||||
use embassy_futures::yield_now;
|
||||
use dma_gpio::hw_uart_pc::usart1;
|
||||
use dma_gpio::hw_uart_pc::driver::uart_task;
|
||||
use embassy_stm32::usart::{BufferedUart, Config, BufferedInterruptHandler};
|
||||
use embassy_stm32::peripherals;
|
||||
use embassy_stm32::bind_interrupts;
|
||||
use embassy_stm32::Config as CPUConfig;
|
||||
use dma_gpio::config::{PIPE_HW_TX, PIPE_HW_RX, PIPE_SW_TX, PIPE_SW_RX};
|
||||
use embassy_sync::{blocking_mutex::raw::CriticalSectionRawMutex, pipe::Pipe};
|
||||
use dma_gpio::hw_uart_internal::usart2;
|
||||
use dma_gpio::hw_uart_internal::driver::uart_task as uart_task_internal;
|
||||
use dma_gpio::software_uart::decode_uart_samples;
|
||||
use dma_gpio::config::UART_CFG;
|
||||
use dma_gpio::config::{PIPE_INT_TX, PIPE_INT_RX};
|
||||
use embassy_time::{Duration, Timer};
|
||||
use embassy_stm32::pac;
|
||||
use embassy_stm32::interrupt;
|
||||
use {defmt_rtt as _, panic_probe as _};
|
||||
use embassy_stm32::{
|
||||
rcc::{self, Pll, PllSource},
|
||||
};
|
||||
use embassy_stm32::rcc::PllMul;
|
||||
use embassy_stm32::rcc::PllDiv;
|
||||
use embassy_stm32::rcc::PllPreDiv;
|
||||
use embassy_stm32::rcc::Sysclk;
|
||||
use cortex_m::interrupt::Mutex;
|
||||
use core::cell::RefCell;
|
||||
use embassy_sync::channel::Channel;
|
||||
|
||||
static PD6_BITS: Channel<CriticalSectionRawMutex, u8, 16384> = Channel::new();
|
||||
|
||||
@@ -81,6 +80,8 @@ async fn main(spawner: Spawner) {
|
||||
let p = embassy_stm32::init(config);
|
||||
let f_tim7 = rcc::frequency::<embassy_stm32::peripherals::TIM7>().0;
|
||||
info!("TIM7 clock after PLL config = {} Hz", f_tim7);
|
||||
let f_tim6 = rcc::frequency::<embassy_stm32::peripherals::TIM6>().0;
|
||||
info!("TIM6 clock after PLL config = {} Hz", f_tim6);
|
||||
|
||||
// HARDWARE UART to the PC
|
||||
let mut cfg = Config::default();
|
||||
@@ -115,7 +116,7 @@ async fn main(spawner: Spawner) {
|
||||
Irqs2,
|
||||
cfg2,
|
||||
).unwrap();
|
||||
let _ = usart2::setup_and_spawn(BAUD);
|
||||
let yield_period2 = usart2::setup_and_spawn(BAUD);
|
||||
spawner.spawn(uart_task_internal(uart2, &PIPE_INT_TX, &PIPE_INT_RX).unwrap());
|
||||
info!("USART2 ready");
|
||||
// END OF INTERNAL HARDWARE UART (USART2)
|
||||
@@ -127,7 +128,6 @@ async fn main(spawner: Spawner) {
|
||||
// END OF USART1 <-> USART2 bridge
|
||||
|
||||
// SOFTWARE UART
|
||||
// let _rx = Input::new(p.PD6, Pull::Up);
|
||||
let rx_pin = Input::new(p.PD6, Pull::Up);
|
||||
unsafe { RX_PIN = Some(rx_pin) };
|
||||
|
||||
@@ -137,18 +137,15 @@ async fn main(spawner: Spawner) {
|
||||
init_tim7_for_uart(p.TIM7, BAUD, RX_OVERSAMPLE);
|
||||
|
||||
dump_tim6_regs();
|
||||
let bsrr_ptr = embassy_stm32::pac::GPIOB.bsrr().as_ptr() as *mut u32; // POZOR B REGISTER
|
||||
|
||||
spawner.spawn(tx_dma_task(p.GPDMA1_CH0, bsrr_ptr, SW_TX_RING.init([0; TX_RING_BYTES]), &PIPE_SW_TX).unwrap());
|
||||
// EDN OF SOFTWARE UART
|
||||
|
||||
|
||||
// Allocate DMA RX ring buffer
|
||||
let rx_ring = SW_RX_RING.init([0u8; RX_RING_BYTES]);
|
||||
|
||||
// Pointer to GPIOD Input Data Register (IDR)
|
||||
let gpio_idr = embassy_stm32::pac::GPIOD.idr().as_ptr() as *mut u8;
|
||||
|
||||
// Spawn software UART RX DMA task
|
||||
spawner.spawn(rx_dma_task(p.GPDMA1_CH1, gpio_idr, rx_ring, &PIPE_SW_RX).unwrap());
|
||||
|
||||
info!("SW UART RX DMA started");
|
||||
|
||||
// Process decoded bytes coming from PIPE_SW_RX
|
||||
@@ -156,7 +153,8 @@ async fn main(spawner: Spawner) {
|
||||
loop {
|
||||
let n = PIPE_SW_RX.read(&mut buf).await;
|
||||
if n > 0 {
|
||||
info!("SW UART decoded: {:a}", &buf[..n]);
|
||||
let _ = PIPE_SW_TX.write(&buf[..n]).await;
|
||||
// info!("SW UART decoded: {:a}", &buf[..n]);
|
||||
}
|
||||
yield_now().await;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// src/software_uart/gpio_dma_uart_tx.rs
|
||||
use embassy_executor::task;
|
||||
use embassy_stm32::{
|
||||
dma::{Request, TransferOptions, WritableRingBuffer},
|
||||
dma::{Request, Transfer, TransferOptions},
|
||||
peripherals::GPDMA1_CH0,
|
||||
Peri,
|
||||
};
|
||||
@@ -32,40 +32,23 @@ pub async fn encode_uart_frames<'a>(
|
||||
break;
|
||||
}
|
||||
|
||||
// cooperative async yield
|
||||
yield_now().await;
|
||||
}
|
||||
offset
|
||||
}
|
||||
|
||||
/// TX DMA task: encodes UART frames and sends them via DMA at TIM6 rate
|
||||
#[task]
|
||||
pub async fn tx_dma_task(
|
||||
ch: Peri<'static, GPDMA1_CH0>,
|
||||
register: *mut u32, // Either odr or bsrr
|
||||
tx_ring_mem: &'static mut [u32],
|
||||
mut ch: Peri<'static, GPDMA1_CH0>,
|
||||
register: *mut u32, // GPIOx_BSRR
|
||||
_tx_ring_mem: &'static mut [u32],
|
||||
pipe_rx: &'static Pipe<CriticalSectionRawMutex, 1024>,
|
||||
) {
|
||||
let mut tx_opts = TransferOptions::default();
|
||||
tx_opts.half_transfer_ir = true;
|
||||
tx_opts.complete_transfer_ir = true;
|
||||
|
||||
// SAFETY: tx_ring is exclusive to this task
|
||||
let mut tx_ring = unsafe {
|
||||
WritableRingBuffer::new(
|
||||
ch,
|
||||
TIM6_UP_REQ,
|
||||
register,
|
||||
tx_ring_mem,
|
||||
tx_opts,
|
||||
)
|
||||
};
|
||||
|
||||
tx_ring.start();
|
||||
info!("TX DMA ring started");
|
||||
info!("TX DMA task ready (One‑shot)");
|
||||
|
||||
let mut frame_buf = [0u32; 4096];
|
||||
let mut rx_buf = [0u8; 256];
|
||||
let tim6 = embassy_stm32::pac::TIM6;
|
||||
|
||||
loop {
|
||||
let n = pipe_rx.read(&mut rx_buf).await;
|
||||
@@ -76,9 +59,33 @@ pub async fn tx_dma_task(
|
||||
|
||||
let used = encode_uart_frames(TX_PIN_BIT, &rx_buf[..n], &mut frame_buf).await;
|
||||
if used > 0 {
|
||||
let _ = tx_ring.write_exact(&frame_buf[..used]).await;
|
||||
// Align arming to a clean TIM6 update boundary:
|
||||
// 1) clear any pending UIF
|
||||
tim6.sr().write(|w| w.set_uif(false));
|
||||
// 2) wait for the next UIF (next bit tick)
|
||||
while !tim6.sr().read().uif() {
|
||||
yield_now().await;
|
||||
}
|
||||
info!("tx_dma_task wrote {} words", used);
|
||||
// 3) clear UIF so first DMA beat happens on the FOLLOWING tick
|
||||
tim6.sr().write(|w| w.set_uif(false));
|
||||
|
||||
let mut tx_opts = TransferOptions::default();
|
||||
tx_opts.half_transfer_ir = false;
|
||||
tx_opts.complete_transfer_ir = true;
|
||||
|
||||
unsafe {
|
||||
let transfer = Transfer::new_write(
|
||||
ch.reborrow(),
|
||||
TIM6_UP_REQ,
|
||||
&frame_buf[..used],
|
||||
register,
|
||||
tx_opts,
|
||||
);
|
||||
transfer.await;
|
||||
}
|
||||
}
|
||||
|
||||
// info!("tx_dma_task sent {} words", used);
|
||||
yield_now().await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,7 +104,7 @@ async fn main(spawner: Spawner) {
|
||||
).unwrap());
|
||||
// END OF SOFTWARE UART
|
||||
|
||||
let mut buf = [0u8; 32];
|
||||
// let mut buf = [0u8; 32];
|
||||
let mut counter: u32 = 0;
|
||||
|
||||
loop {
|
||||
|
||||
Reference in New Issue
Block a user