Skip to content

Commit d35fec3

Browse files
baftiifpistm
andauthored
fix(uart): HardwareSerial begin() causes Infinite Loop (#2785)
* fix(uart): uart clock prescaler configuration Signed-off-by: Bartu Özcan <[email protected]> Co-authored-by: Frederic Pillon <[email protected]>
1 parent e96c3a1 commit d35fec3

File tree

2 files changed

+155
-0
lines changed

2 files changed

+155
-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: 150 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,144 @@ 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+
uint32_t usartdiv = 0;
1443+
1444+
#if defined(UART_INSTANCE_LOWPOWER)
1445+
if (UART_INSTANCE_LOWPOWER(huart)) {
1446+
for (uint32_t idx = 0; idx < 12; idx++) {
1447+
/* Check computed UsartDiv value is in allocated range
1448+
(it is forbidden to write values lower than 0x300 in the LPUART_BRR register) */
1449+
usartdiv = (uint32_t)(UART_DIV_LPUART(freq, huart->Init.BaudRate, presc_div[idx]));
1450+
if ((usartdiv >= 0x00000300U) && (usartdiv <= 0x000FFFFFU)) {
1451+
prescaler = UART_PRESCALER_DIV1 + idx;
1452+
break;
1453+
}
1454+
}
1455+
} else
1456+
#endif /* UART_INSTANCE_LOWPOWER */
1457+
{
1458+
for (uint32_t idx = 0; idx < 12; idx++) {
1459+
if (huart->Init.OverSampling == UART_OVERSAMPLING_8) {
1460+
usartdiv = (uint32_t)(UART_DIV_SAMPLING8(freq, huart->Init.BaudRate, presc_div[idx]));
1461+
} else {
1462+
usartdiv = (uint32_t)(UART_DIV_SAMPLING16(freq, huart->Init.BaudRate, presc_div[idx]));
1463+
}
1464+
if ((usartdiv >= 0x10U) && (usartdiv <= 0x0000FFFFU)) {
1465+
prescaler = UART_PRESCALER_DIV1 + idx;
1466+
break;
1467+
}
1468+
}
1469+
}
1470+
return prescaler;
1471+
}
1472+
1473+
/**
1474+
* @brief Function called to get the clock source frequency of the uart
1475+
* @param huart : uart handle structure
1476+
* @retval uint32_t clock source frequency
1477+
*/
1478+
uint32_t uart_get_clock_source_freq(UART_HandleTypeDef *huart)
1479+
{
1480+
uint32_t freq = 0;
1481+
#if defined(STM32WB0)
1482+
freq = UART_PERIPHCLK;
1483+
if (UART_INSTANCE_LOWPOWER(huart)) {
1484+
#if defined(RCC_CFGR_LPUCLKSEL)
1485+
freq = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_LPUART1);
1486+
#endif /* RCC_CFGR_LPUCLKSEL */
1487+
}
1488+
#else /* !STM32WB0 */
1489+
uint32_t clocksource;
1490+
UART_GETCLOCKSOURCE(huart, clocksource);
1491+
#if defined(STM32H5) || defined(STM32MP1) || defined(STM32U0) ||\
1492+
defined(STM32U3) || defined(STM32U5)
1493+
freq = HAL_RCCEx_GetPeriphCLKFreq(clocksource);
1494+
#else
1495+
switch (clocksource) {
1496+
#if defined(UART_CLOCKSOURCE_D2PCLK1) || defined(UART_CLOCKSOURCE_PCLK1)
1497+
#if defined(UART_CLOCKSOURCE_D2PCLK1)
1498+
case UART_CLOCKSOURCE_D2PCLK1:
1499+
#endif /* UART_CLOCKSOURCE_D2PCLK1*/
1500+
#if defined(UART_CLOCKSOURCE_PCLK1)
1501+
case UART_CLOCKSOURCE_PCLK1:
1502+
#endif /* UART_CLOCKSOURCE_PCLK1 */
1503+
freq = HAL_RCC_GetPCLK1Freq();
1504+
break;
1505+
#endif /* UART_CLOCKSOURCE_D2PCLK1 || UART_CLOCKSOURCE_PCLK1*/
1506+
#if defined(UART_CLOCKSOURCE_D2PCLK2) || defined(UART_CLOCKSOURCE_PCLK2)
1507+
#if defined(UART_CLOCKSOURCE_D2PCLK2)
1508+
case UART_CLOCKSOURCE_D2PCLK2:
1509+
#endif /* UART_CLOCKSOURCE_D2PCLK2*/
1510+
#if defined(UART_CLOCKSOURCE_PCLK2)
1511+
case UART_CLOCKSOURCE_PCLK2:
1512+
#endif /* UART_CLOCKSOURCE_PCLK2 */
1513+
freq = HAL_RCC_GetPCLK2Freq();
1514+
break;
1515+
#endif /* UART_CLOCKSOURCE_D2PCLK2 || UART_CLOCKSOURCE_PCLK2*/
1516+
#if defined(UART_CLOCKSOURCE_PCLK7)
1517+
case UART_CLOCKSOURCE_PCLK7:
1518+
freq = HAL_RCC_GetPCLK7Freq();
1519+
break;
1520+
#endif /* UART_CLOCKSOURCE_PCLK7 */
1521+
#if defined(UART_CLOCKSOURCE_PLL2)
1522+
case UART_CLOCKSOURCE_PLL2:
1523+
HAL_RCCEx_GetPLL2ClockFreq(&pll2_clocks);
1524+
freq = pll2_clocks.PLL2_Q_Frequency;
1525+
break;
1526+
case UART_CLOCKSOURCE_PLL3:
1527+
HAL_RCCEx_GetPLL3ClockFreq(&pll3_clocks);
1528+
freq = pll3_clocks.PLL3_Q_Frequency;
1529+
break;
1530+
#endif /* UART_CLOCKSOURCE_PLL2 */
1531+
case UART_CLOCKSOURCE_HSI:
1532+
#if defined(__HAL_RCC_GET_HSIKER_DIVIDER)
1533+
freq = (HSI_VALUE / ((__HAL_RCC_GET_HSIKER_DIVIDER() >> RCC_CR_HSIKERDIV_Pos) + 1U));
1534+
#else
1535+
#if defined(RCC_FLAG_HSIDIV)
1536+
if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U) {
1537+
freq = (uint32_t)(HSI_VALUE >> (__HAL_RCC_GET_HSI_DIVIDER() >> 3U));
1538+
} else
1539+
#endif /* RCC_FLAG_HSIDIV */
1540+
{
1541+
freq = (uint32_t) HSI_VALUE;
1542+
}
1543+
#endif
1544+
break;
1545+
#if defined(UART_CLOCKSOURCE_CSI)
1546+
case UART_CLOCKSOURCE_CSI:
1547+
freq = (uint32_t) CSI_VALUE;
1548+
break;
1549+
#endif /* UART_CLOCKSOURCE_CSI */
1550+
#if defined(UART_CLOCKSOURCE_SYSCLK)
1551+
case UART_CLOCKSOURCE_SYSCLK:
1552+
freq = HAL_RCC_GetSysClockFreq();
1553+
break;
1554+
#endif /* UART_CLOCKSOURCE_SYSCLK */
1555+
case UART_CLOCKSOURCE_LSE:
1556+
freq = (uint32_t) LSE_VALUE;
1557+
break;
1558+
default:
1559+
freq = 0U;
1560+
break;
1561+
}
1562+
#endif /* STM32H5 */
1563+
#endif /* STM32WB0 */
1564+
return freq;
1565+
}
1566+
#endif /* UART_PRESCALER_DIV1 */
1567+
14181568
#endif /* HAL_UART_MODULE_ENABLED && !HAL_UART_MODULE_ONLY */
14191569

14201570
#ifdef __cplusplus

0 commit comments

Comments
 (0)