Skip to content

Commit 48b8e12

Browse files
baftiiBartu Özcan
authored andcommitted
fix(uart): uart clock prescaler configuration and uartPCLK getter function added.
Signed-off-by: Bartu Özcan <[email protected]>
1 parent 0e2a66b commit 48b8e12

File tree

2 files changed

+174
-0
lines changed

2 files changed

+174
-0
lines changed

libraries/SrcWrapper/inc/uart.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,6 +272,12 @@ 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 calculatePresc(uint32_t pclk, uint32_t baudrate, uint32_t oversampling);
277+
#endif
278+
279+
uint32_t uart_getPCLK(UART_HandleTypeDef *huart);
280+
275281
#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */
276282
#ifdef __cplusplus
277283
}

libraries/SrcWrapper/src/stm32/uart.c

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,17 @@ 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+
// Default Value
420+
uint32_t clock_prescaler = UART_PRESCALER_DIV1;
421+
422+
uint32_t pclk = uart_getPCLK(huart);
423+
clock_prescaler = calculatePresc(pclk, baudrate, huart->Init.OverSampling);
424+
huart->Init.ClockPrescaler = clock_prescaler;
425+
#endif
426+
416427
#if defined(UART_ADVFEATURE_NO_INIT)
417428
// Default value
418429
huart->AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
@@ -1415,6 +1426,163 @@ void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
14151426
serial_t *obj = get_serial_obj(huart);
14161427
HAL_UART_Receive_IT(huart, &(obj->recv), 1);
14171428
}
1429+
1430+
/**
1431+
* @brief Function called to set the uart clock prescaler
1432+
* @param pclk : supplied clock rate to related uart
1433+
* @retval uint32_t clock prescaler
1434+
*/
1435+
#if defined(UART_PRESCALER_DIV1)
1436+
uint32_t calculatePresc(uint32_t pclk, uint32_t baudrate, uint32_t oversampling)
1437+
{
1438+
static const uint16_t presc_div[12] = {1, 2, 4, 6, 8, 10, 12, 16, 32, 64, 128, 256};
1439+
1440+
uint32_t condition = 0;
1441+
if (oversampling == UART_OVERSAMPLING_16) {
1442+
condition = 16U;
1443+
} else {
1444+
condition = 8U;
1445+
}
1446+
1447+
for (uint32_t idx = 0; idx < 8; idx++) {
1448+
uint32_t uartclk = pclk / presc_div[idx];
1449+
uint32_t brr = 0;
1450+
if (oversampling == UART_OVERSAMPLING_16) {
1451+
brr = (uartclk + (baudrate / 2U)) / baudrate;
1452+
} else {
1453+
brr = ((2U * uartclk) + (baudrate / 2U)) / baudrate;
1454+
}
1455+
1456+
if (brr >= condition && brr <= 0xFFFU) {
1457+
return UART_PRESCALER_DIV1 + idx;
1458+
}
1459+
}
1460+
return UART_PRESCALER_DIV1;
1461+
}
1462+
#endif
1463+
1464+
/**
1465+
* @brief Function called to get the clock source frequency of the uart
1466+
* @param huart : uart handle structure
1467+
* @retval uint32_t clock source frequency
1468+
*/
1469+
uint32_t uart_getPCLK(UART_HandleTypeDef *huart)
1470+
{
1471+
#if defined(LPUART1)
1472+
if (huart->Instance == LPUART1) {
1473+
#if defined(STM32H5) || defined(STM32U3) || defined(STM32U5)
1474+
return HAL_RCC_GetPCLK3Freq();
1475+
#elif defined(STM32H7)
1476+
uint32_t sysclk = HAL_RCC_GetSysClockFreq();
1477+
#if defined(STM32H7A3xx) || defined (STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) || defined(STM32H7B0xx) || defined(STM32H7B0xxQ)
1478+
uint32_t prescaler = (RCC->CDCFGR2 & (0x7UL << 9U)) >> 9U;
1479+
#else
1480+
uint32_t prescaler = (RCC->D2CFGR & (0x7UL << 9U)) >> 9U;
1481+
#endif
1482+
1483+
uint32_t apb4 = 1;
1484+
1485+
switch (prescaler) {
1486+
case 0b000: prescaler = 1; break;
1487+
case 0b100: prescaler = 2; break;
1488+
case 0b101: prescaler = 4; break;
1489+
case 0b110: prescaler = 8; break;
1490+
case 0b111: prescaler = 16; break;
1491+
default: break;
1492+
}
1493+
1494+
return (sysclk / prescaler);
1495+
#elif defined(STM32G4) || defined(STM32L4) || defined(STM32L5) || defined(STM32WB)
1496+
return HAL_RCC_GetPCLK1Freq();
1497+
#elif defined(STM32WL)
1498+
return HAL_RCC_GetPCLK2Freq();
1499+
#elif defined(STM32WBA)
1500+
return HAL_RCC_GetPCLK7Freq();
1501+
#endif
1502+
}
1503+
#endif
1504+
1505+
#if defined(LPUART2)
1506+
if (huart->Instance == LPUART2) {
1507+
return HAL_RCC_GetPCLK1Freq();
1508+
}
1509+
#endif
1510+
1511+
#if defined(LPUART3)
1512+
if (huart->Instance == LPUART3) {
1513+
return HAL_RCC_GetPCLK1Freq();
1514+
}
1515+
#endif
1516+
1517+
#if defined(STM32F0) || defined(STM32G0) || defined(STM32L0) || defined(STM32C0) \
1518+
|| defined(STM32WB)
1519+
return HAL_RCC_GetPCLK1Freq();
1520+
#endif
1521+
1522+
#if defined(STM32WB0)
1523+
uint32_t sysclk = HAL_RCC_GetSysClockFreq();
1524+
uint32_t ppre2 = (RCC->CFGR & (0x7UL << 11U)) >> 11U;
1525+
uint32_t apb2_div = 1;
1526+
1527+
switch (ppre2) {
1528+
case 0b000: apb2_div = 1; break;
1529+
case 0b100: apb2_div = 2; break;
1530+
case 0b101: apb2_div = 4; break;
1531+
case 0b110: apb2_div = 8; break;
1532+
case 0b111: apb2_div = 16; break;
1533+
default: break;
1534+
}
1535+
return (sysclk / apb2_div);
1536+
#endif
1537+
1538+
#if defined(STM32WL)
1539+
return HAL_RCC_GetPCLK2Freq();
1540+
#endif
1541+
1542+
#if defined(STM32H7)
1543+
if (huart->Instance == USART1
1544+
#if defined(USART10)
1545+
|| huart->Instance == USART10
1546+
#endif
1547+
#if defined(USART6)
1548+
|| huart->Instance == USART6
1549+
#endif
1550+
#if defined(UART9)
1551+
|| huart->Instance == UART9
1552+
#endif
1553+
) {
1554+
return HAL_RCC_GetPCLK2Freq();
1555+
}
1556+
return HAL_RCC_GetPCLK1Freq();
1557+
#endif
1558+
1559+
#if defined(STM32MP1)
1560+
if (huart->Instance == USART1) {
1561+
return HAL_RCC_GetPCLK5Freq();
1562+
} else if (huart->Instance == USART6) {
1563+
return HAL_RCC_GetPCLK2Freq();
1564+
} else {
1565+
return HAL_RCC_GetPCLK1Freq();
1566+
}
1567+
#endif
1568+
1569+
#if defined(STM32F7) || defined(STM32F2) || defined(STM32F4) || defined(STM32F1) \
1570+
|| defined(STM32U3) || defined(STM32F3) || defined(STM32H5) || defined(STM32G4) \
1571+
|| defined(STM32L4) || defined(STM32L5) || defined(STM32WBA) || defined(STM32U5) \
1572+
|| defined(STM32L1)
1573+
if (huart->Instance == USART1
1574+
#if defined(USART6) && !defined(STM32H5) && !defined(STM32U5)
1575+
|| huart->Instance == USART6
1576+
#endif
1577+
) {
1578+
return HAL_RCC_GetPCLK2Freq();
1579+
}
1580+
return HAL_RCC_GetPCLK1Freq();
1581+
#endif
1582+
1583+
return 0;
1584+
}
1585+
14181586
#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */
14191587

14201588
#ifdef __cplusplus

0 commit comments

Comments
 (0)