stm32f3xx-hal
stm32f3xx-hal copied to clipboard
Serial Baud Rate setting sets half the desired baudrate
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::WouldBlockonserial.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()andserial.write()blocks in annb::block!(...), I get annb::Error::Other(crate::serial::Error::Overruninstead
- If I wrap all the
Perhaps the example does something wrong here? Maybe 2 tasks, one for receiving, one for sending, with a buffer in-between, might be better?
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.
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.
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
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)
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.
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 :(