For my STM32F411 DMA UART, could you please review my code style, especially the `button_click` method?

⚓ Rust    📅 2025-11-28    👤 surdeus    👁️ 5      

surdeus

#![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

Read full topic

🏷️ Rust_feed