Files
stm32_rust/semestralka_1_final_lib/src/bin/main.rs
2025-11-24 00:21:58 +01:00

206 lines
6.3 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// src/bin/main.rs
#![no_std]
#![no_main]
use defmt::*;
use core::cell::RefCell;
use cortex_m::interrupt::Mutex;
use embassy_executor::Spawner;
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 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,
gpio_dma_uart_tx::tx_dma_task,
};
use dma_gpio::config::{TX_PIN_BIT, RX_PIN_BIT};
use {defmt_rtt as _, panic_probe as _};
static PD6_BITS: Channel<CriticalSectionRawMutex, u8, 16384> = Channel::new();
bind_interrupts!(struct Irqs {
USART1 => BufferedInterruptHandler<peripherals::USART1>;
});
bind_interrupts!(struct Irqs2 {
USART2 => BufferedInterruptHandler<peripherals::USART2>;
});
// Software uart
pub const TIM6_UP_REQ: Request = 4;
static SW_TX_RING: StaticCell<[u32; TX_RING_BYTES]> = StaticCell::new();
static SW_RX_RING: StaticCell<[u8; RX_RING_BYTES]> = StaticCell::new();
static mut RX_PIN: Option<Input<'static>> = None;
#[embassy_executor::main]
async fn main(spawner: Spawner) {
info!("boot");
let mut config = CPUConfig::default();
config.rcc.hsi = true;
config.rcc.sys = Sysclk::PLL1_R;
config.rcc.pll1 = Some(Pll {
source: PllSource::HSI,
// 16 MHz / 1 × 20 / 2 = 160 MHz
prediv: PllPreDiv::DIV1,
mul: PllMul::MUL20,
divp: None,
divq: None,
divr: Some(PllDiv::DIV2),
});
config.enable_independent_io_supply = true;
config.enable_independent_analog_supply = true;
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();
cfg.baudrate = BAUD;
static TX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
static RX_BUF: StaticCell<[u8; 256]> = StaticCell::new();
let uart = BufferedUart::new(
p.USART1,
p.PA10, // RX pin
p.PA9, // TX pin
TX_BUF.init([0; 256]),
RX_BUF.init([0; 256]),
Irqs,
cfg,
).unwrap();
let yield_period = usart1::setup_and_spawn(BAUD);
spawner.spawn(uart_task(uart, &PIPE_HW_TX, &PIPE_HW_RX).unwrap());
// END OF HARDWARE UART to the PC
// INTERNAL HARDWARE UART (USART2)
let mut cfg2 = Config::default();
cfg2.baudrate = BAUD;
static TX_BUF2: StaticCell<[u8; 256]> = StaticCell::new();
static RX_BUF2: StaticCell<[u8; 256]> = StaticCell::new();
let uart2 = BufferedUart::new(
p.USART2,
p.PA3, // RX
p.PA2, // TX
TX_BUF2.init([0; 256]),
RX_BUF2.init([0; 256]),
Irqs2,
cfg2,
).unwrap();
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)
// USART1 <-> USART2 bridge
spawner.spawn(bridge_usart1_rx_to_usart2_tx(&PIPE_HW_RX, &PIPE_INT_TX).unwrap());
spawner.spawn(bridge_usart2_rx_to_usart1_tx(&PIPE_INT_RX, &PIPE_HW_TX).unwrap());
info!("USART1 <-> USART2 bridge active");
// END OF USART1 <-> USART2 bridge
// SOFTWARE UART
let rx_pin = Input::new(p.PD6, Pull::Up);
unsafe { RX_PIN = Some(rx_pin) };
let mut tx_pin = Output::new(p.PB0, Level::High, Speed::VeryHigh);
init_tim6_for_uart(p.TIM6, BAUD, TX_OVERSAMPLE);
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,
&PIPE_SW_TX,
TX_PIN_BIT,
&UART_CFG,
).unwrap());
// EDN OF SOFTWARE UART
let rx_ring = SW_RX_RING.init([0u8; RX_RING_BYTES]);
let gpio_idr = embassy_stm32::pac::GPIOD.idr().as_ptr() as *mut u8;
spawner.spawn(rx_dma_task(
p.GPDMA1_CH1,
gpio_idr,
rx_ring,
&PIPE_SW_RX,
RX_PIN_BIT,
RX_OVERSAMPLE,
&UART_CFG,
).unwrap());
info!("SW UART RX DMA started");
let mut buf = [0u8; 64];
loop {
let n = PIPE_SW_RX.read(&mut buf).await;
if n > 0 {
let _ = PIPE_SW_TX.write(&buf[..n]).await;
// info!("SW UART decoded: {:a}", &buf[..n]);
}
yield_now().await;
}
}
#[embassy_executor::task]
pub async fn bridge_usart1_rx_to_usart2_tx(
usart1_rx: &'static Pipe<CriticalSectionRawMutex, 1024>,
usart2_tx: &'static Pipe<CriticalSectionRawMutex, 1024>,
) {
let mut buf = [0u8; 64];
loop {
let n = usart1_rx.read(&mut buf).await;
if n > 0 {
let _ = usart2_tx.write(&buf[..n]).await;
// info!("bridge USART1 - USART2 sent:{} bytes: {}", n, &buf[..n]);
}
yield_now().await;
}
}
#[embassy_executor::task]
pub async fn bridge_usart2_rx_to_usart1_tx(
usart2_rx: &'static Pipe<CriticalSectionRawMutex, 1024>,
usart1_tx: &'static Pipe<CriticalSectionRawMutex, 1024>,
) {
let mut buf = [0u8; 64];
loop {
let n = usart2_rx.read(&mut buf).await;
if n > 0 {
let _ = usart1_tx.write(&buf[..n]).await;
// info!("bridge: USART2 -> USART1 sent {} bytes", n);
}
yield_now().await;
}
}