Skip to content

Commit

Permalink
fix: uart auto oversampling calculation (#5319)
Browse files Browse the repository at this point in the history
  • Loading branch information
richardclli authored Jul 30, 2024
1 parent 7fb3888 commit 56b3d5b
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 69 deletions.
4 changes: 0 additions & 4 deletions radio/src/hal/module_port.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,10 +69,6 @@ static bool _init_serial_driver(etx_module_driver_t* d, const etx_module_port_t*

// S.PORT specific HW settings
if (port->port == ETX_MOD_PORT_SPORT && params->baudrate >= 400000) {

// enable over-sampling by 8
if (drv->setHWOption) drv->setHWOption(d->ctx, ETX_HWOption_OVER8);

// one-bit
if (g_eeGeneral.uartSampleMode == UART_SAMPLE_MODE_ONEBIT) {
if (drv->setHWOption) drv->setHWOption(d->ctx, ETX_HWOption_ONEBIT);
Expand Down
1 change: 0 additions & 1 deletion radio/src/hal/serial_driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@ struct etx_serial_callbacks_t {
};

enum SerialHWOption {
ETX_HWOption_OVER8, // oversampling by 8
ETX_HWOption_ONEBIT, // one-bit sampling
};

Expand Down
129 changes: 65 additions & 64 deletions radio/src/targets/common/arm/stm32/stm32_usart_driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,68 @@ static gpio_af_t _get_usart_af(USART_TypeDef* USARTx)
return _AF7_USART(USARTx) ? GPIO_AF7 : GPIO_AF8;
}

// from stm32f4xx_ll_usart.c
static uint32_t _get_usart_periph_clock(USART_TypeDef* USARTx)
{
uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO;
LL_RCC_ClocksTypeDef rcc_clocks;

LL_RCC_GetSystemClocksFreq(&rcc_clocks);
if (USARTx == USART1) {
periphclk = rcc_clocks.PCLK2_Frequency;
} else if (USARTx == USART2) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#if defined(USART3)
else if (USARTx == USART3) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* USART3 */
#if defined(USART6)
else if (USARTx == USART6) {
periphclk = rcc_clocks.PCLK2_Frequency;
}
#endif /* USART6 */
#if defined(UART4)
else if (USARTx == UART4) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART4 */
#if defined(UART5)
else if (USARTx == UART5) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART5 */
#if defined(UART7)
else if (USARTx == UART7) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART7 */
#if defined(UART8)
else if (USARTx == UART8) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART8 */
#if defined(UART9)
else if (USARTx == UART9) {
periphclk = rcc_clocks.PCLK2_Frequency;
}
#endif /* UART9 */
#if defined(UART10)
else if (USARTx == UART10) {
periphclk = rcc_clocks.PCLK2_Frequency;
}
#endif /* UART10 */

return periphclk;
}

static uint32_t _calc_best_oversampling(USART_TypeDef* USARTx, uint32_t baudrate)
{
auto periphclk = _get_usart_periph_clock(USARTx);
return (periphclk < (baudrate << 4)) ? LL_USART_OVERSAMPLING_8 : LL_USART_OVERSAMPLING_16;
}

void stm32_usart_init_rx_dma(const stm32_usart_t* usart, const void* buffer, uint32_t length)
{
if (!usart->rxDMA) return;
Expand Down Expand Up @@ -283,6 +345,7 @@ bool stm32_usart_init(const stm32_usart_t* usart, const etx_serial_init* params)
LL_USART_InitTypeDef usartInit;
LL_USART_StructInit(&usartInit);

usartInit.OverSampling = _calc_best_oversampling(usart->USARTx, params->baudrate);
usartInit.BaudRate = params->baudrate;
usartInit.Parity = LL_USART_PARITY_NONE;
usartInit.DataWidth = LL_USART_DATAWIDTH_8B;
Expand Down Expand Up @@ -490,62 +553,6 @@ void stm32_usart_enable_rx(const stm32_usart_t* usart)
_half_duplex_input(usart);
}

// from stm32f4xx_ll_usart.c
static uint32_t _get_usart_periph_clock(USART_TypeDef* USARTx)
{
uint32_t periphclk = LL_RCC_PERIPH_FREQUENCY_NO;
LL_RCC_ClocksTypeDef rcc_clocks;

LL_RCC_GetSystemClocksFreq(&rcc_clocks);
if (USARTx == USART1) {
periphclk = rcc_clocks.PCLK2_Frequency;
} else if (USARTx == USART2) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#if defined(USART3)
else if (USARTx == USART3) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* USART3 */
#if defined(USART6)
else if (USARTx == USART6) {
periphclk = rcc_clocks.PCLK2_Frequency;
}
#endif /* USART6 */
#if defined(UART4)
else if (USARTx == UART4) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART4 */
#if defined(UART5)
else if (USARTx == UART5) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART5 */
#if defined(UART7)
else if (USARTx == UART7) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART7 */
#if defined(UART8)
else if (USARTx == UART8) {
periphclk = rcc_clocks.PCLK1_Frequency;
}
#endif /* UART8 */
#if defined(UART9)
else if (USARTx == UART9) {
periphclk = rcc_clocks.PCLK2_Frequency;
}
#endif /* UART9 */
#if defined(UART10)
else if (USARTx == UART10) {
periphclk = rcc_clocks.PCLK2_Frequency;
}
#endif /* UART10 */

return periphclk;
}

uint32_t stm32_usart_get_baudrate(const stm32_usart_t* usart)
{
auto periphclk = _get_usart_periph_clock(usart->USARTx);
Expand All @@ -560,7 +567,8 @@ uint32_t stm32_usart_get_baudrate(const stm32_usart_t* usart)
void stm32_usart_set_baudrate(const stm32_usart_t* usart, uint32_t baudrate)
{
auto periphclk = _get_usart_periph_clock(usart->USARTx);
auto oversampling = LL_USART_GetOverSampling(usart->USARTx);
auto oversampling = _calc_best_oversampling(usart->USARTx, baudrate);
LL_USART_SetOverSampling(usart->USARTx, oversampling);
#if defined(LL_USART_PRESCALER_DIV1)
LL_USART_SetBaudRate(usart->USARTx, periphclk, LL_USART_PRESCALER_DIV1, oversampling, baudrate);
#else
Expand All @@ -571,13 +579,6 @@ void stm32_usart_set_baudrate(const stm32_usart_t* usart, uint32_t baudrate)
void stm32_usart_set_hw_option(const stm32_usart_t* usart, uint32_t option)
{
switch(option) {
case ETX_HWOption_OVER8: {
// BRR depends on oversampling as well, so we must
// re-compute the baudrate as well.
auto baudrate = stm32_usart_get_baudrate(usart);
LL_USART_SetOverSampling(usart->USARTx, LL_USART_OVERSAMPLING_8);
stm32_usart_set_baudrate(usart, baudrate);
} break;
case ETX_HWOption_ONEBIT:
LL_USART_EnableOneBitSamp(usart->USARTx);
break;
Expand Down

0 comments on commit 56b3d5b

Please sign in to comment.