@@ -66,6 +66,15 @@ LOG_MODULE_REGISTER(uart_stm32, CONFIG_UART_LOG_LEVEL);
66
66
#define HAS_DRIVER_ENABLE 0
67
67
#endif
68
68
69
+ /* Helper for checking if we can use hardware receive timeouts
70
+ * instead of the work queue on a given UART
71
+ */
72
+ #ifdef USART_RTOR_RTO
73
+ #define HAS_RTO 1
74
+ #else
75
+ #define HAS_RTO 0
76
+ #endif
77
+
69
78
#ifdef CONFIG_PM
70
79
/* Placeholder value when wakeup-line DT property is not defined */
71
80
#define STM32_WAKEUP_LINE_NONE 0xFFFFFFFF
@@ -1407,6 +1416,14 @@ static void uart_stm32_isr(const struct device *dev)
1407
1416
/* clear the RXNE by flushing the fifo, because Rx data was not read */
1408
1417
LL_USART_RequestRxDataFlush (usart );
1409
1418
#endif /* USART_SR_RXNE */
1419
+ #if HAS_RTO
1420
+ } else if (LL_USART_IsEnabledIT_RTO (usart ) && LL_USART_IsActiveFlag_RTO (usart )) {
1421
+
1422
+ LOG_DBG ("rx timeout interrupt occurred" );
1423
+
1424
+ LL_USART_ClearFlag_RTO (usart );
1425
+ uart_stm32_dma_rx_flush (dev , STM32_ASYNC_STATUS_TIMEOUT );
1426
+ #endif /* HAS_RTO */
1410
1427
}
1411
1428
1412
1429
/* Clear errors */
@@ -1490,7 +1507,15 @@ static int uart_stm32_async_rx_disable(const struct device *dev)
1490
1507
return - EFAULT ;
1491
1508
}
1492
1509
1510
+ #if HAS_RTO
1511
+ if (LL_USART_IsEnabledIT_RTO (usart )) {
1512
+ LL_USART_DisableIT_RTO (usart );
1513
+ } else {
1514
+ LL_USART_DisableIT_IDLE (usart );
1515
+ }
1516
+ #else /* HAS_RTO */
1493
1517
LL_USART_DisableIT_IDLE (usart );
1518
+ #endif /* HAS_RTO */
1494
1519
1495
1520
uart_stm32_dma_rx_flush (dev , STM32_ASYNC_STATUS_TIMEOUT );
1496
1521
@@ -1736,6 +1761,63 @@ static int uart_stm32_async_tx(const struct device *dev,
1736
1761
return 0 ;
1737
1762
}
1738
1763
1764
+ static void set_timeout_itr (USART_TypeDef * usart , uint32_t baudrate , int32_t timeout )
1765
+ {
1766
+ #if HAS_RTO
1767
+ #if HAS_LPUART
1768
+ if (IS_LPUART_INSTANCE (usart )) {
1769
+ goto enable_idle_itr ;
1770
+ }
1771
+ #endif
1772
+
1773
+ if (LL_USART_IsEnabledIT_RTO (usart )) {
1774
+ LL_USART_DisableRxTimeout (usart );
1775
+ LL_USART_DisableIT_RTO (usart );
1776
+ LL_USART_ClearFlag_RTO (usart );
1777
+ } else {
1778
+ LL_USART_DisableIT_IDLE (usart );
1779
+ LL_USART_ClearFlag_IDLE (usart );
1780
+ }
1781
+
1782
+ if (timeout == SYS_FOREVER_US ) {
1783
+ goto enable_idle_itr ;
1784
+ }
1785
+
1786
+ /* Cast to uint64_t to avoid overflowing before the division */
1787
+ uint64_t timeout_in_bits = ((uint64_t )timeout * baudrate ) / 1000000 ;
1788
+
1789
+ if (timeout_in_bits > UINT32_MAX ) {
1790
+ goto enable_idle_itr ;
1791
+ }
1792
+
1793
+ /* Not all UARTs support hardware RX timeouts.
1794
+ * Try to set the timeout anyway, and see if it gets set.
1795
+ * Ref RM, "USART receiver timeout register (USART_RTOR):
1796
+ * "This register is reserved and forced by hardware to "0x00000000"
1797
+ * when the Receiver timeout feature is not supported."
1798
+ * This also falls back to using the IDLE interrupt
1799
+ * if the timeout requested is too short or 0.
1800
+ */
1801
+ LL_USART_SetRxTimeout (usart , (uint32_t )timeout_in_bits );
1802
+ if (LL_USART_GetRxTimeout (usart ) == 0 ) {
1803
+ goto enable_idle_itr ;
1804
+ }
1805
+
1806
+ /* Use hardware RTO interrupt */
1807
+ LOG_DBG ("Set RTO timeout: %d us / %d bits" , timeout , (uint32_t )timeout_in_bits );
1808
+
1809
+ LL_USART_ClearFlag_RTO (usart );
1810
+ LL_USART_EnableIT_RTO (usart );
1811
+ LL_USART_EnableRxTimeout (usart );
1812
+ return ;
1813
+
1814
+ enable_idle_itr :
1815
+ #endif /* HAS_RTO */
1816
+
1817
+ LL_USART_ClearFlag_IDLE (usart );
1818
+ LL_USART_EnableIT_IDLE (usart );
1819
+ }
1820
+
1739
1821
static int uart_stm32_async_rx_enable (const struct device * dev ,
1740
1822
uint8_t * rx_buf , size_t buf_size , int32_t timeout )
1741
1823
{
@@ -1792,11 +1874,7 @@ static int uart_stm32_async_rx_enable(const struct device *dev,
1792
1874
/* Enable RX DMA requests */
1793
1875
uart_stm32_dma_rx_enable (dev );
1794
1876
1795
- /* Enable IRQ IDLE to define the end of a
1796
- * RX DMA transaction.
1797
- */
1798
- LL_USART_ClearFlag_IDLE (usart );
1799
- LL_USART_EnableIT_IDLE (usart );
1877
+ set_timeout_itr (usart , data -> uart_cfg -> baudrate , timeout );
1800
1878
1801
1879
LL_USART_EnableIT_ERROR (usart );
1802
1880
0 commit comments