Skip to content

Commit 336f5a6

Browse files
baftiifpistm
authored andcommitted
fix(uart): uart clock prescaler configuration
uartPCLK getter function added. Signed-off-by: Bartu Özcan <[email protected]>
1 parent 2095f53 commit 336f5a6

File tree

2 files changed

+177
-0
lines changed

2 files changed

+177
-0
lines changed

libraries/SrcWrapper/inc/uart.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,11 @@ void uart_enable_rx(serial_t *obj);
272272

273273
size_t uart_debug_write(uint8_t *data, uint32_t size);
274274

275+
#if defined(UART_PRESCALER_DIV1)
276+
uint32_t uart_compute_prescaler(UART_HandleTypeDef *huart);
277+
uint32_t uart_get_clock_source_freq(UART_HandleTypeDef *huart);
278+
#endif
279+
275280
#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */
276281
#ifdef __cplusplus
277282
}

libraries/SrcWrapper/src/stm32/uart.c

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,18 @@ bool uart_init(serial_t *obj, uint32_t baudrate, uint32_t databits, uint32_t par
413413
huart->Init.Mode = UART_MODE_TX_RX;
414414
huart->Init.HwFlowCtl = flow_control;
415415
huart->Init.OverSampling = UART_OVERSAMPLING_16;
416+
417+
/* Configure UART Clock Prescaler */
418+
#if defined(UART_PRESCALER_DIV1)
419+
huart->Init.ClockPrescaler = uart_compute_prescaler(huart);
420+
if (!IS_UART_PRESCALER(huart->Init.ClockPrescaler)) {
421+
if (obj != &serial_debug) {
422+
core_debug("WARNING: [U(S)ART] wrong prescaler, reset to UART_PRESCALER_DIV1!\n");
423+
}
424+
huart->Init.ClockPrescaler = UART_PRESCALER_DIV1;
425+
}
426+
#endif
427+
416428
#if defined(UART_ADVFEATURE_NO_INIT)
417429
// Default value
418430
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
@@ -1415,6 +1427,166 @@ void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
14151427
serial_t *obj = get_serial_obj(huart);
14161428
HAL_UART_Receive_IT(huart, &(obj->recv), 1);
14171429
}
1430+
1431+
/**
1432+
* @brief Function called to set the uart clock prescaler
1433+
* @param huart : uart handle structure
1434+
* @retval uint32_t clock prescaler
1435+
*/
1436+
#if defined(UART_PRESCALER_DIV1)
1437+
uint32_t uart_compute_prescaler(UART_HandleTypeDef *huart)
1438+
{
1439+
uint32_t prescaler = UART_PRESCALER_DIV1;
1440+
static const uint16_t presc_div[12] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};
1441+
uint32_t freq = uart_get_clock_source_freq(huart);
1442+
1443+
uint32_t condition = 0;
1444+
if (huart->Init.OverSampling == UART_OVERSAMPLING_16) {
1445+
condition = 16U;
1446+
} else {
1447+
condition = 8U;
1448+
}
1449+
1450+
for (uint32_t idx = 0; idx < 12; idx++) {
1451+
uint32_t uartclk = freq / presc_div[idx];
1452+
uint32_t brr = 0;
1453+
if (huart->Init.OverSampling == UART_OVERSAMPLING_16) {
1454+
brr = (uartclk + (huart->Init.BaudRate / 2U)) / huart->Init.BaudRate;
1455+
} else {
1456+
brr = ((2U * uartclk) + (huart->Init.BaudRate / 2U)) / huart->Init.BaudRate;
1457+
}
1458+
1459+
if (brr >= condition && brr <= 0xFFFU) {
1460+
prescaler = UART_PRESCALER_DIV1 + idx;
1461+
break;
1462+
}
1463+
}
1464+
return prescaler;
1465+
}
1466+
1467+
/**
1468+
* @brief Function called to get the clock source frequency of the uart
1469+
* @param huart : uart handle structure
1470+
* @retval uint32_t clock source frequency
1471+
*/
1472+
uint32_t uart_get_clock_source_freq(UART_HandleTypeDef *huart)
1473+
{
1474+
#if defined(LPUART1)
1475+
if (huart->Instance == LPUART1) {
1476+
#if defined(STM32H5) || defined(STM32U3) || defined(STM32U5)
1477+
return HAL_RCC_GetPCLK3Freq();
1478+
#elif defined(STM32H7)
1479+
uint32_t sysclk = HAL_RCC_GetSysClockFreq();
1480+
#if defined(STM32H7A3xx) || defined (STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || defined(STM32H7B0xx) || defined(STM32H7B0xxQ)
1481+
uint32_t prescaler = (RCC->SRDCFGR & RCC_SRDCFGR_SRDPPRE) >> RCC_SRDCFGR_SRDPPRE_Pos;
1482+
#else
1483+
uint32_t prescaler = (RCC->D3CFGR & RCC_D3CFGR_D3PPRE) >> RCC_D3CFGR_D3PPRE_Pos;
1484+
#endif
1485+
1486+
uint32_t apb4 = 1;
1487+
1488+
switch (prescaler) {
1489+
case 0b000: prescaler = 1; break;
1490+
case 0b100: prescaler = 2; break;
1491+
case 0b101: prescaler = 4; break;
1492+
case 0b110: prescaler = 8; break;
1493+
case 0b111: prescaler = 16; break;
1494+
default: break;
1495+
}
1496+
1497+
return (sysclk / prescaler);
1498+
#elif defined(STM32G4) || defined(STM32L4) || defined(STM32L5) || defined(STM32WB)
1499+
return HAL_RCC_GetPCLK1Freq();
1500+
#elif defined(STM32WL)
1501+
return HAL_RCC_GetPCLK2Freq();
1502+
#elif defined(STM32WBA)
1503+
return HAL_RCC_GetPCLK7Freq();
1504+
#endif
1505+
}
1506+
#endif
1507+
1508+
#if defined(LPUART2)
1509+
if (huart->Instance == LPUART2) {
1510+
return HAL_RCC_GetPCLK1Freq();
1511+
}
1512+
#endif
1513+
1514+
#if defined(LPUART3)
1515+
if (huart->Instance == LPUART3) {
1516+
return HAL_RCC_GetPCLK1Freq();
1517+
}
1518+
#endif
1519+
1520+
#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32C0) \
1521+
|| defined(STM32WB)
1522+
return HAL_RCC_GetPCLK1Freq();
1523+
#endif
1524+
1525+
#if defined(STM32WB0)
1526+
uint32_t sysclk = HAL_RCC_GetSysClockFreq();
1527+
uint32_t ppre2 = (RCC->CFGR & RCC_CFGR_CLKSYSDIV) >> RCC_CFGR_CLKSYSDIV_Pos;
1528+
uint32_t apb2_div = 1;
1529+
1530+
switch (ppre2) {
1531+
case 0b000: apb2_div = 1; break;
1532+
case 0b100: apb2_div = 2; break;
1533+
case 0b101: apb2_div = 4; break;
1534+
case 0b110: apb2_div = 8; break;
1535+
case 0b111: apb2_div = 16; break;
1536+
default: break;
1537+
}
1538+
return (sysclk / apb2_div);
1539+
#endif
1540+
1541+
#if defined(STM32WL)
1542+
return HAL_RCC_GetPCLK2Freq();
1543+
#endif
1544+
1545+
#if defined(STM32H7)
1546+
if (huart->Instance == USART1
1547+
#if defined(USART10)
1548+
|| huart->Instance == USART10
1549+
#endif
1550+
#if defined(USART6)
1551+
|| huart->Instance == USART6
1552+
#endif
1553+
#if defined(UART9)
1554+
|| huart->Instance == UART9
1555+
#endif
1556+
) {
1557+
return HAL_RCC_GetPCLK2Freq();
1558+
}
1559+
return HAL_RCC_GetPCLK1Freq();
1560+
#endif
1561+
1562+
#if defined(STM32MP1)
1563+
if (huart->Instance == USART1) {
1564+
return HAL_RCC_GetPCLK5Freq();
1565+
} else if (huart->Instance == USART6) {
1566+
return HAL_RCC_GetPCLK2Freq();
1567+
} else {
1568+
return HAL_RCC_GetPCLK1Freq();
1569+
}
1570+
#endif
1571+
1572+
#if defined(STM32F7) || defined(STM32F2) || defined(STM32F4) || defined(STM32F1) \
1573+
|| defined(STM32U3) || defined(STM32F3) || defined(STM32H5) || defined(STM32G4) \
1574+
|| defined(STM32L4) || defined(STM32L5) || defined(STM32WBA) || defined(STM32U5) \
1575+
|| defined(STM32L1)
1576+
if (huart->Instance == USART1
1577+
#if defined(USART6) && !defined(STM32H5) && !defined(STM32U5)
1578+
|| huart->Instance == USART6
1579+
#endif
1580+
) {
1581+
return HAL_RCC_GetPCLK2Freq();
1582+
}
1583+
return HAL_RCC_GetPCLK1Freq();
1584+
#endif
1585+
1586+
return 0;
1587+
}
1588+
#endif /* UART_PRESCALER_DIV1 */
1589+
14181590
#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */
14191591

14201592
#ifdef __cplusplus

0 commit comments

Comments
 (0)