diff --git a/include/libopencm3/stm32/common/usart_common_all.h b/include/libopencm3/stm32/common/usart_common_all.h index 455746a0..5daf6fbc 100644 --- a/include/libopencm3/stm32/common/usart_common_all.h +++ b/include/libopencm3/stm32/common/usart_common_all.h @@ -99,6 +99,7 @@ specific memorymap.h header before including this header file.*/ BEGIN_DECLS void usart_set_baudrate(uint32_t usart, uint32_t baud); +uint32_t usart_get_baudrate(uint32_t usart); void usart_set_databits(uint32_t usart, uint32_t bits); uint32_t usart_get_databits(uint32_t usart); void usart_set_stopbits(uint32_t usart, uint32_t stopbits); diff --git a/lib/stm32/common/usart_common_all.c b/lib/stm32/common/usart_common_all.c index 9c254df1..40c80e50 100644 --- a/lib/stm32/common/usart_common_all.c +++ b/lib/stm32/common/usart_common_all.c @@ -94,6 +94,43 @@ void usart_set_baudrate(uint32_t usart, uint32_t baud) #endif } +/*---------------------------------------------------------------------------*/ +/** @brief USART Get Baudrate. + +Note: For LPUART, baudrates over 2**24 (~16.7 Mbaud) may overflow +the calculation and are therefore not supported by this function. + +@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base +@returns baud unsigned 32 bit. Baud rate specified in Hz. +*/ + +uint32_t usart_get_baudrate(uint32_t usart) +{ + uint32_t clock = rcc_get_usart_clk_freq(usart); + const uint32_t reg_brr = USART_BRR(usart); + +#ifdef LPUART1 + if (usart == LPUART1) { + return (clock / reg_brr) * 256 + + ((clock % reg_brr) * 256) / reg_brr; + } +#endif + +#ifdef USART_CR1_OVER8 + if (USART_CR1(usart) & USART_CR1_OVER8) { + /* Need to shift BRR[2:0] up before using the simple formula of 2*clock/BRR (Q12.4) */ + const uint16_t div_mantissa = reg_brr & USART_BRR_UPPER_MASK; + const uint16_t div_fractional = (reg_brr & USART_BRR_LOWER_MASK) << 1U; + const uint16_t div_over8 = div_mantissa + div_fractional; + return (2U * clock) / div_over8; + } else { + return clock / reg_brr; + } +#else + return clock / reg_brr; +#endif +} + /*---------------------------------------------------------------------------*/ /** @brief USART Set Word Length.