Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions libraries/SrcWrapper/inc/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,12 @@ void uart_enable_rx(serial_t *obj);

size_t uart_debug_write(uint8_t *data, uint32_t size);

#if defined(UART_PRESCALER_DIV1)
uint32_t calculatePresc(uint32_t pclk, uint32_t baudrate, uint32_t oversampling);
#endif

uint32_t uart_getPCLK(UART_HandleTypeDef *huart);

#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */
#ifdef __cplusplus
}
Expand Down
168 changes: 168 additions & 0 deletions libraries/SrcWrapper/src/stm32/uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,17 @@ bool uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
huart->Init.Mode = UART_MODE_TX_RX;
huart->Init.HwFlowCtl = flow_control;
huart->Init.OverSampling = UART_OVERSAMPLING_16;

/* Configure UART Clock Prescaler */
#if defined(UART_PRESCALER_DIV1)
// Default Value
uint32_t clock_prescaler = UART_PRESCALER_DIV1;

uint32_t pclk = uart_getPCLK(huart);
clock_prescaler = calculatePresc(pclk, baudrate, huart->Init.OverSampling);
huart->Init.ClockPrescaler = clock_prescaler;
#endif

#if defined(UART_ADVFEATURE_NO_INIT)
// Default value
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
Expand Down Expand Up @@ -1415,6 +1426,163 @@ void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
serial_t *obj = get_serial_obj(huart);
HAL_UART_Receive_IT(huart, &(obj->recv), 1);
}

/**
* @brief Function called to set the uart clock prescaler
* @param pclk : supplied clock rate to related uart
* @retval uint32_t clock prescaler
*/
#if defined(UART_PRESCALER_DIV1)
uint32_t calculatePresc(uint32_t pclk, uint32_t baudrate, uint32_t oversampling)
{
static const uint16_t presc_div[12] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};

uint32_t condition = 0;
if (oversampling == UART_OVERSAMPLING_16) {
condition = 16U;
} else {
condition = 8U;
}

for (uint32_t idx = 0; idx < 8; idx++) {
uint32_t uartclk = pclk / presc_div[idx];
uint32_t brr = 0;
if (oversampling == UART_OVERSAMPLING_16) {
brr = (uartclk + (baudrate / 2U)) / baudrate;
} else {
brr = ((2U * uartclk) + (baudrate / 2U)) / baudrate;
}

if (brr >= condition && brr <= 0xFFFU) {
return UART_PRESCALER_DIV1 + idx;
}
}
return UART_PRESCALER_DIV1;
}
#endif

/**
* @brief Function called to get the clock source frequency of the uart
* @param huart : uart handle structure
* @retval uint32_t clock source frequency
*/
uint32_t uart_getPCLK(UART_HandleTypeDef *huart)
{
#if defined(LPUART1)
if (huart->Instance == LPUART1) {
#if defined(STM32H5) || defined(STM32U3) || defined(STM32U5)
return HAL_RCC_GetPCLK3Freq();
#elif defined(STM32H7)
uint32_t sysclk = HAL_RCC_GetSysClockFreq();
#if defined(STM32H7A3xx) || defined (STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || defined(STM32H7B0xx) || defined(STM32H7B0xxQ)
uint32_t prescaler = (RCC->SRDCFGR & RCC_SRDCFGR_SRDPPRE) >> RCC_SRDCFGR_SRDPPRE_Pos;
#else
uint32_t prescaler = (RCC->D3CFGR & RCC_D3CFGR_D3PPRE) >> RCC_D3CFGR_D3PPRE_Pos;
#endif

uint32_t apb4 = 1;

switch (prescaler) {
case 0b000: prescaler = 1; break;
case 0b100: prescaler = 2; break;
case 0b101: prescaler = 4; break;
case 0b110: prescaler = 8; break;
case 0b111: prescaler = 16; break;
default: break;
}

return (sysclk / prescaler);
#elif defined(STM32G4) || defined(STM32L4) || defined(STM32L5) || defined(STM32WB)
return HAL_RCC_GetPCLK1Freq();
#elif defined(STM32WL)
return HAL_RCC_GetPCLK2Freq();
#elif defined(STM32WBA)
return HAL_RCC_GetPCLK7Freq();
#endif
}
#endif

#if defined(LPUART2)
if (huart->Instance == LPUART2) {
return HAL_RCC_GetPCLK1Freq();
}
#endif

#if defined(LPUART3)
if (huart->Instance == LPUART3) {
return HAL_RCC_GetPCLK1Freq();
}
#endif

#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32C0) \
|| defined(STM32WB)
return HAL_RCC_GetPCLK1Freq();
#endif

#if defined(STM32WB0)
uint32_t sysclk = HAL_RCC_GetSysClockFreq();
uint32_t ppre2 = (RCC->CFGR & RCC_CFGR_CLKSYSDIV) >> RCC_CFGR_CLKSYSDIV_Pos;
uint32_t apb2_div = 1;

switch (ppre2) {
case 0b000: apb2_div = 1; break;
case 0b100: apb2_div = 2; break;
case 0b101: apb2_div = 4; break;
case 0b110: apb2_div = 8; break;
case 0b111: apb2_div = 16; break;
default: break;
}
return (sysclk / apb2_div);
#endif

#if defined(STM32WL)
return HAL_RCC_GetPCLK2Freq();
#endif

#if defined(STM32H7)
if (huart->Instance == USART1
#if defined(USART10)
|| huart->Instance == USART10
#endif
#if defined(USART6)
|| huart->Instance == USART6
#endif
#if defined(UART9)
|| huart->Instance == UART9
#endif
) {
return HAL_RCC_GetPCLK2Freq();
}
return HAL_RCC_GetPCLK1Freq();
#endif

#if defined(STM32MP1)
if (huart->Instance == USART1) {
return HAL_RCC_GetPCLK5Freq();
} else if (huart->Instance == USART6) {
return HAL_RCC_GetPCLK2Freq();
} else {
return HAL_RCC_GetPCLK1Freq();
}
#endif

#if defined(STM32F7) || defined(STM32F2) || defined(STM32F4) || defined(STM32F1) \
|| defined(STM32U3) || defined(STM32F3) || defined(STM32H5) || defined(STM32G4) \
|| defined(STM32L4) || defined(STM32L5) || defined(STM32WBA) || defined(STM32U5) \
|| defined(STM32L1)
if (huart->Instance == USART1
#if defined(USART6) && !defined(STM32H5) && !defined(STM32U5)
|| huart->Instance == USART6
#endif
) {
return HAL_RCC_GetPCLK2Freq();
}
return HAL_RCC_GetPCLK1Freq();
#endif

return 0;
}

#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */

#ifdef __cplusplus
Expand Down