stm32f3xx-hal icon indicating copy to clipboard operation
stm32f3xx-hal copied to clipboard

Serial Baud Rate setting sets half the desired baudrate

Open barafael opened this issue 3 years ago • 6 comments

I am testing the RTIC example from this HAL: https://github.com/stm32-rs/stm32f3xx-hal/blob/master/examples/serial_echo_rtic.rs

My hardware is a NUCLEO-32 with an STM32F303K8Tx.

I'm facing a few issues there:

  • The baudrate seems to be stuck on 9600Bps, not at 19200Bps as the code configures it.
  • Regularly, the serial reception code encounters an nb::Error::WouldBlock on serial.read(), resulting in not all characters being sent back and the serial task no longer reacting to received characters (probably the interrupt for character reception is not reenabled).
    • If I wrap all the serial.read() and serial.write() blocks in an nb::block!(...), I get an nb::Error::Other(crate::serial::Error::Overrun instead

Perhaps the example does something wrong here? Maybe 2 tasks, one for receiving, one for sending, with a buffer in-between, might be better?

barafael avatar Jul 31 '22 13:07 barafael

Upon further measurements, the baudrate seems to be exactly half of what I'd be expecting. Setting the baudrate to 9600Bps, the signal looks to be like 4800Bps, with a frequency of roughly 2240Hz, same for other frequencies. This explains also why a setting of 19200Bps while reading/writing at 9600Bps worked.

barafael avatar Jul 31 '22 14:07 barafael

Interesting. Upon looking into the source code, I could not immediatly see, where the bug is comming from.

Anyway here is the point, where the baudrate is converted to the BRR value

https://github.com/stm32-rs/stm32f3xx-hal/blob/4212122c3af1e32ed6d3105e64e3fc6eddeb8aa3/src/serial.rs#L485

And as far as I can see this should be correct per datasheet (ch 29.5.4)

But it could also be that the peripheral clock value is wrongly wired in the source code. (Usart::clock), e.g.

https://github.com/stm32-rs/stm32f3xx-hal/blob/4212122c3af1e32ed6d3105e64e3fc6eddeb8aa3/src/rcc/enable.rs#L81

And of course this bug can be easily missed. I've only tested the USART against itself, so that those miscalculations are not caught:

https://github.com/stm32-rs/stm32f3xx-hal/blob/4212122c3af1e32ed6d3105e64e3fc6eddeb8aa3/testsuite/tests/uart.rs#L36 https://github.com/stm32-rs/stm32f3xx-hal/blob/4212122c3af1e32ed6d3105e64e3fc6eddeb8aa3/testsuite/tests/uart.rs#L186

So either I'm reading the datasheet wrong (the BRR calculation is not correct) or the frequency of the peripheral clock is not correct.

If I get the hardware on hand again (I recently moved, and I still have not got my setup fully running yet) I'll try to find the cause / confirm the issue.

Sh3Rm4n avatar Aug 01 '22 07:08 Sh3Rm4n

Let me know if I can assist with anything. I have the nucleo I mentioned and also an F3 discovery board, I'll go ahead and test with that as well

barafael avatar Aug 01 '22 07:08 barafael

I just tested on my STM32F3DISCO. There, the baud rate setting is just fine (but the overrun errors still happen).

Here's the code that works with half the baudrate on the STM32F303K8Tx NUCLEO-32 board: https://gist.github.com/barafael/9de1de5e41026519d2a12a6aa3c78a3d

(this is simply instead of the HAL example, I also exchanged rprintln to defmt print)

barafael avatar Aug 03 '22 14:08 barafael

Interesting. Thanks for trying it outwith the discovery board. Maybe this bug is related to slightly different code paths.

Maybe the RCC initialization code is buggy (haven't checked that). The code paths are probably sightly different, as th eNUCLEO-32 board has the stm32f303x8 feature active:

https://github.com/stm32-rs/stm32f3xx-hal/blob/d30018e5eabeeb2fc2cef6113f6da7d1adc5c10d/Cargo.toml#L120

whilst the discovery board uses the stm32f303xc feature:

https://github.com/stm32-rs/stm32f3xx-hal/blob/d30018e5eabeeb2fc2cef6113f6da7d1adc5c10d/Cargo.toml#L122

I just tested on my STM32F3DISCO. There, the baud rate setting is just fine (but the overrun errors still happen).

Regarding overrun, could you check it with that https://github.com/stm32-rs/stm32f3xx-hal/pull/317. Maybe this solves the overrun errors.

Sh3Rm4n avatar Aug 04 '22 07:08 Sh3Rm4n

So I tried to reproduce the bug you described, but I'm not able to with the discovery board at least. I confirmed the correct baud rate with help of a logic analyzer and even configured the clock pin, with that patch in src/serial.rs

diff --git a/src/serial.rs b/src/serial.rs
index d41b2f1e..eaf5004e 100644
--- a/src/serial.rs
+++ b/src/serial.rs
@@ -507,6 +507,8 @@ where
             w.te().enabled() // enable transmitter
         });
 
+        usart.cr2.modify(|_, w| w.clken().enabled());
+
         // Finally enable the configured UART.
         usart.cr1.modify(|_, w| w.ue().enabled());

and

let ckpin: gpio::PA8<AF7<PushPull>> =gpioa.pa8.into_af_push_pull(&mut gpioa.moder, &mut gpioa.otyper, &mut gpioa.afrh);

The baud rate is correctly picked up as ~19200 Bd. Other baud rates or SysClock changes also take effect as expected.

So this must have something to do with slight differences between the x8 and the xc variant, if you are sure you clocked your STM32F303K8Tx correctly (which I assume).

I would suspect

https://github.com/stm32-rs/stm32f3xx-hal/blob/1410d31c251a19355e88964140e4a502233d3f6c/src/rcc.rs#L604-L608

calculating the system clock or bus clock wrong for the stm32f303x8, but as stm32f303xc is gpio-f303 and stm32f303x8 is gpio-f333 this function is the same for both. :thinking:

And the clock tree seem to be almost identical (RM0316 ch. 9.2 fig13 & fig 15)

So I have no idea where your problem is coming from :(

Sh3Rm4n avatar Sep 06 '22 20:09 Sh3Rm4n