STM32F3 Discovery and using USART3

Hi there, I am attempting to leverage USART3 on the STM32F3 Discovery board to communicate with an Adafruit FONA GSM board using simple serial communications. I have not been able to get USART3 to work - at least from what I can tell (i.e. even just direct connected it to my laptop with a terminal program). I am using the stm32f3xx_hal crate.

Was able to get things to work (at least using a terminal app on my laptop) communicating between my laptop and STM32F3 over USART1 which is over the USB ST-LINK hardware interface. This validated that my coding strategy at least for USART1. I have since converted the code to leverage USART3 along with updating the DMA channel numbers and other things to enable USART3 versus USART1. However, I have not been able to get this type of test working with USART3. I'm wondering if I might be needing to configure something that was not necessary when I leveraged USART1 over the USB ST-Link interface. I was hopeful that by updating the appropriate pins, (i.e. pc10, pc11), dma channels (C2, C3) and changing everything from USART1 to USART3 would magically work :slight_smile:.

Here's the code (thank you @ kalkyl for the help!) . BTW, I felt this belongs in Embedded versus RTIC since the RTIC part of the design is working just fine.

//! main.rs
#![deny(unsafe_code)]
#![no_main]
#![no_std]

#[rtic::app(device = stm32f3xx_hal::pac, peripherals = true, dispatchers = [WWDG])]
mod app {
    use stm32f3xx_hal::{
        dma::{
            dma1::{C2, C3},
            Channel, Event, Transfer,
        },
        pac::USART3,
        prelude::*,
        serial::{Rx, Tx},
    };
    use panic_semihosting as _;

    const BUF_SIZE: usize = 12;

    pub enum TxTransfer {
        Running(Transfer<&'static mut [u8; BUF_SIZE], C2, Tx<USART3>>),
        Idle(&'static mut [u8; BUF_SIZE], C2, Tx<USART3>),
    }

    #[shared]
    struct Shared {
        #[lock_free]
        send: Option<TxTransfer>,
    }

    #[local]
    struct Local {
        recv: Option<Transfer<&'static mut [u8; BUF_SIZE], C3, Rx<USART3>>>,
        gpioe: stm32f3xx_hal::pac::GPIOE,
    }

    #[init(local = [tx_buf: [u8; BUF_SIZE] = [0; BUF_SIZE], rx_buf: [u8; BUF_SIZE] = [0; BUF_SIZE]])]
    fn init(ctx: init::Context) -> (Shared, Local, init::Monotonics) {
        
        ctx.device.RCC.ahbenr.modify(|_, w| w.dma1en().enabled());
        ctx.device.RCC.ahbenr.modify(|_, w| w.iopeen().set_bit());

        let mut rcc = ctx.device.RCC.constrain();
        let mut flash = ctx.device.FLASH.constrain();
        let clocks = rcc.cfgr.freeze(&mut flash.acr);
        
        // for serial port ops
        let mut gpioc = ctx.device.GPIOC.split(&mut rcc.ahb);

        // for relay ops
        let gpioe = ctx.device.GPIOE;
        gpioe.moder.modify(|_, w| {
            w.moder8().output();
            w.moder9().output();
            w.moder10().output();
            w.moder11().output();
            w.moder12().output();
            w.moder13().output();
            w.moder14().output();
            w.moder15().output()
        });

        // set the led to on
        gpioe.odr.modify(|_, w| {
            w.odr15().set_bit()
        });
        
        // setup for serial communications
        let pins = (
            gpioc.pc10.into_af7(&mut gpioc.moder, &mut gpioc.afrh),
            gpioc.pc11.into_af7(&mut gpioc.moder, &mut gpioc.afrh), 
        );

        let usart3 = stm32f3xx_hal::serial::Serial::usart3(
            ctx.device.USART3,
            pins,
            9_600.bps(),
            clocks,
            &mut rcc.apb1,
        );

        let (tx, rx) = usart3.split();
        let mut dma1 = ctx.device.DMA1.split(&mut rcc.ahb);
        dma1.ch4.listen(Event::TransferComplete);
        dma1.ch5.listen(Event::TransferComplete);
        (
            Shared {
                send: Some(TxTransfer::Idle(ctx.local.tx_buf, dma1.ch2, tx)),
            },
            Local {
                recv: Some(rx.read_exact(ctx.local.rx_buf, dma1.ch3)),
                gpioe,
            },
            init::Monotonics(),
        )
    }

    #[idle]
    fn idle(_: idle::Context) -> ! {
        loop {}
    }

    // Triggers on RX transfer completed
    #[task(binds = DMA1_CH5, local = [recv,gpioe], priority = 2)]
    fn on_rx(ctx: on_rx::Context) {
        let (rx_buf, rx_channel, rx) = ctx.local.recv.take().unwrap().wait();
        echo::spawn(*rx_buf).ok();

        // set the led to off
        ctx.local.gpioe.odr.modify(|r, w| {
            //w.odr15().clear_bit()
            let led = r.odr15().bit();
                if led {
                    w.odr15().clear_bit()
                } else {
                    w.odr15().set_bit()
                }     
        });


        ctx.local.recv.replace(rx.read_exact(rx_buf, rx_channel));
    }

    #[task(shared = [send], priority = 1, capacity = 4)]
    fn echo(ctx: echo::Context, data: [u8; BUF_SIZE]) {
        //defmt::info!("Received {:?}", data);
        let send = ctx.shared.send;
        let (tx_buf, tx_channel, tx) = match send.take().unwrap() {
            TxTransfer::Idle(buf, ch, tx) => (buf, ch, tx),
            TxTransfer::Running(transfer) => transfer.wait(),
        };
        tx_buf.copy_from_slice(&data[..]);
        send.replace(TxTransfer::Running(tx.write_all(tx_buf, tx_channel)));
    }

    // Triggers on TX transfer completed
    #[task(binds = DMA1_CH4, shared = [send], priority = 1)]
    fn on_tx(ctx: on_tx::Context) {
        let send = ctx.shared.send;
        let (tx_buf, tx_channel, tx) = match send.take().unwrap() {
            TxTransfer::Idle(buf, ch, tx) => (buf, ch, tx),
            TxTransfer::Running(transfer) => transfer.wait(),
        };
        //defmt::info!("Sent {:?}", tx_buf);
        send.replace(TxTransfer::Idle(tx_buf, tx_channel, tx));
    }
}

And here's a picture of my makeshift lab setup (haha):

I'm wondering:

  1. Is there something special that I might have to do with the hal configuration to use USART3 (i.e anything special with the clock config that I did not have to do with USART1)?
  2. Does the HAL even support USART3?
  3. Is my design/thought process all wrong?

Thank you for reading my long post!
Matt

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.