For my STM32F411 DMA UART, could you please review my code style, especially the `button_click` method?
⚓ Rust 📅 2025-11-28 👤 surdeus 👁️ 5#![no_std]
#![no_main]
mod test;
use defmt::{self, info};
use hal::{
dma::{PeripheralToMemory, Stream5, Stream6, Transfer, config::DmaConfig},
pac::{DMA1, USART2},
prelude::*,
serial::{Config, Serial, Tx},
};
use rtic::app;
// HAL imports
use stm32f4xx_hal as hal;
const MSG_SIZE: usize = 16;
#[app(device = hal::pac, peripherals = true, dispatchers = [USART2])]
mod app {
use super::*;
use stm32f4xx_hal::dma::{DmaFlag, MemoryToPeripheral, StreamsTuple};
// use rtic_monotonics::stm32_tim2_monotonic;
use stm32f4xx_hal::gpio::{Edge, Input, PC13, Pull};
use stm32f4xx_hal::serial;
use stm32f4xx_hal::serial::config::DmaConfig::Rx;
use stm32f4xx_hal::serial::config::StopBits;
use panic_semihosting as _;
type TxTransfer =
Transfer<Stream6<DMA1>, 4, Tx<USART2>, MemoryToPeripheral, &'static mut [u8; MSG_SIZE]>;
type RxTransfer = Transfer<
Stream5<DMA1>,
4,
serial::Rx<USART2>,
PeripheralToMemory,
&'static mut [u8; MSG_SIZE],
>;
#[shared]
struct Shared {
tx: Option<TxTransfer>,
rx: RxTransfer,
}
#[local]
struct Local {
rx_buffer: Option<&'static mut [u8; MSG_SIZE]>,
// tx_buffer: Option<&'static mut [u8; MSG_SIZE]>,
command: u8,
button: PC13<Input>,
}
#[init]
fn init(ctx: init::Context) -> (Shared, Local) {
info!("init...");
let mut dp = ctx.device;
let mut rcc = dp.RCC.constrain();
// stm32_tim2_monotonic!(Mono, 1_000_000);
let gpioa = dp.GPIOA.split(&mut rcc);
let uart2_tx_pin = gpioa.pa2.into_alternate();
let uart2_rx_pin = gpioa.pa3.into_alternate();
let uart2 = Serial::new(
dp.USART2,
(uart2_tx_pin, uart2_rx_pin),
Config::default()
.baudrate(9600.bps())
.parity_none()
.stopbits(StopBits::STOP1)
.dma(Rx),
&mut rcc,
)
.unwrap();
let (tx, mut rx) = uart2.split();
rx.listen_idle();
let dma1 = StreamsTuple::new(dp.DMA1, &mut rcc);
let dma_rx_buffer = cortex_m::singleton!(: [u8; MSG_SIZE] = [0; MSG_SIZE]).unwrap();
let dma_tx_buffer = cortex_m::singleton!(: [u8; MSG_SIZE] = [0; MSG_SIZE]).unwrap();
let mut rx_transfer = Transfer::init_peripheral_to_memory(
dma1.5,
rx,
dma_rx_buffer,
None,
DmaConfig::default()
.memory_increment(true)
.fifo_enable(true)
.fifo_error_interrupt(true)
.transfer_complete_interrupt(true),
);
let mut tx_transfer = Transfer::init_memory_to_peripheral(
dma1.6,
tx,
dma_tx_buffer,
None,
DmaConfig::default()
.memory_increment(true)
.fifo_enable(true)
.fifo_error_interrupt(true)
.transfer_complete_interrupt(false),
);
tx_transfer.start(|_tx| {});
rx_transfer.start(|_rx| {});
let rx_buffer = cortex_m::singleton!(: [u8; MSG_SIZE] = [0; MSG_SIZE]).unwrap();
let mut sys_cfg = dp.SYSCFG.constrain(&mut rcc);
let gpioc = dp.GPIOC.split(&mut rcc);
let mut button = Input::new(gpioc.pc13, Pull::Up);
button.make_interrupt_source(&mut sys_cfg);
button.enable_interrupt(&mut dp.EXTI);
button.trigger_on_edge(&mut dp.EXTI, Edge::Falling);
(
Shared {
tx: Some(tx_transfer),
rx: rx_transfer,
},
Local {
rx_buffer: Some(rx_buffer),
button,
command: 0,
},
)
}
#[task(binds = DMA2_STREAM0, shared = [rx], local = [rx_buffer])]
fn recv(cx: recv::Context) {
let mut rx = cx.shared.rx;
let rx_buffer = cx.local.rx_buffer;
rx.lock(|transfer| {
let flags = transfer.flags();
transfer.clear_flags(DmaFlag::FifoError | DmaFlag::TransferComplete);
if flags.is_transfer_complete() {
let (filled_buffer, _) = transfer.next_transfer(rx_buffer.take().unwrap()).unwrap();
info!("recv buf: {}", filled_buffer);
*rx_buffer = Some(filled_buffer);
}
});
}
#[task(binds = EXTI0, shared = [tx], local = [button, command])]
fn button_click(mut ctx: button_click::Context) {
ctx.local.button.clear_interrupt_pending_bit();
ctx.shared.tx.lock(|transfer_opt| {
let mut transfer = transfer_opt.take().unwrap();
transfer.clear_flags(DmaFlag::FifoError | DmaFlag::TransferComplete);
let transfer = transfer.release();
let command = ctx.local.command;
*command = (*command + 1) % 3;
let buf = transfer.2;
match *command {
0 => {
buf[..15].copy_from_slice(&b"$spd:100,0,0,0#"[..]);
info!("send: spd 100");
}
1 => {
buf[..16].copy_from_slice(&b"$pwm:3000,0,0,0#"[..]);
info!("send: pwm 3000");
}
2 => {
buf[..13].copy_from_slice(&b"$spd:0,0,0,0#"[..]);
info!("send: spd 0");
}
_ => unreachable!(),
}
let mut new_transfer = Transfer::init_memory_to_peripheral(
transfer.0,
transfer.1,
buf,
None,
DmaConfig::default()
.memory_increment(true)
.fifo_enable(true)
.fifo_error_interrupt(true)
.transfer_complete_interrupt(false),
);
new_transfer.start(|_tx| {
info!("TX DMA start");
});
transfer_opt.replace(new_transfer)
});
}
}
1 post - 1 participant
🏷️ Rust_feed