@@ -53,6 +53,28 @@ LOG_MODULE_REGISTER(uart_stm32);
5353
5454#define TIMEOUT 1000
5555
56+ #ifdef CONFIG_PM
57+ static void uart_stm32_pm_constraint_set (const struct device * dev )
58+ {
59+ struct uart_stm32_data * data = DEV_DATA (dev );
60+
61+ if (!data -> pm_constraint_on ) {
62+ data -> pm_constraint_on = true;
63+ pm_constraint_set (PM_STATE_SUSPEND_TO_IDLE );
64+ }
65+ }
66+
67+ static void uart_stm32_pm_constraint_release (const struct device * dev )
68+ {
69+ struct uart_stm32_data * data = DEV_DATA (dev );
70+
71+ if (data -> pm_constraint_on ) {
72+ data -> pm_constraint_on = false;
73+ pm_constraint_release (PM_STATE_SUSPEND_TO_IDLE );
74+ }
75+ }
76+ #endif /* CONFIG_PM */
77+
5678static inline void uart_stm32_set_baudrate (const struct device * dev ,
5779 uint32_t baud_rate )
5880{
@@ -456,8 +478,23 @@ static void uart_stm32_poll_out(const struct device *dev,
456478 while (!LL_USART_IsActiveFlag_TXE (UartInstance )) {
457479 }
458480
459- /* do not allow system to suspend until transmission has completed */
460- pm_constraint_set (PM_STATE_SUSPEND_TO_IDLE );
481+ #ifdef CONFIG_PM
482+ struct uart_stm32_data * data = DEV_DATA (dev );
483+
484+ if (!data -> tx_poll_stream_on ) {
485+ data -> tx_poll_stream_on = true;
486+
487+ /* Don't allow system to suspend until stream
488+ * transmission has completed
489+ */
490+ uart_stm32_pm_constraint_set (dev );
491+
492+ /* Enable TC interrupt so we can release suspend
493+ * constraint when done
494+ */
495+ LL_USART_EnableIT_TC (UartInstance );
496+ }
497+ #endif /* CONFIG_PM */
461498
462499 LL_USART_TransmitData8 (UartInstance , (uint8_t )c );
463500}
@@ -520,11 +557,6 @@ static int uart_stm32_fifo_fill(const struct device *dev,
520557 USART_TypeDef * UartInstance = UART_STRUCT (dev );
521558 uint8_t num_tx = 0U ;
522559
523- if ((size > 0 ) && LL_USART_IsActiveFlag_TXE (UartInstance )) {
524- /* do not allow system to suspend until transmission has completed */
525- pm_constraint_set (PM_STATE_SUSPEND_TO_IDLE );
526- }
527-
528560 while ((size - num_tx > 0 ) &&
529561 LL_USART_IsActiveFlag_TXE (UartInstance )) {
530562 /* TXE flag will be cleared with byte write to DR|RDR register */
@@ -563,13 +595,21 @@ static void uart_stm32_irq_tx_enable(const struct device *dev)
563595 USART_TypeDef * UartInstance = UART_STRUCT (dev );
564596
565597 LL_USART_EnableIT_TC (UartInstance );
598+
599+ #ifdef CONFIG_PM
600+ uart_stm32_pm_constraint_set (dev );
601+ #endif
566602}
567603
568604static void uart_stm32_irq_tx_disable (const struct device * dev )
569605{
570606 USART_TypeDef * UartInstance = UART_STRUCT (dev );
571607
572608 LL_USART_DisableIT_TC (UartInstance );
609+
610+ #ifdef CONFIG_PM
611+ uart_stm32_pm_constraint_release (dev );
612+ #endif
573613}
574614
575615static int uart_stm32_irq_tx_ready (const struct device * dev )
@@ -799,16 +839,30 @@ static void uart_stm32_dma_rx_flush(const struct device *dev)
799839static void uart_stm32_isr (const struct device * dev )
800840{
801841 struct uart_stm32_data * data = DEV_DATA (dev );
842+ #if defined(CONFIG_PM ) || defined(CONFIG_UART_ASYNC_API )
802843 USART_TypeDef * UartInstance = UART_STRUCT (dev );
844+ #endif
803845
804- #ifdef CONFIG_UART_INTERRUPT_DRIVEN
805- if (LL_USART_IsActiveFlag_TC (UartInstance )) {
806- LL_USART_ClearFlag_TC (UartInstance );
807-
808- /* allow system to suspend, UART has now finished */
809- pm_constraint_release (PM_STATE_SUSPEND_TO_IDLE );
846+ #ifdef CONFIG_PM
847+ if (LL_USART_IsEnabledIT_TC (UartInstance ) &&
848+ LL_USART_IsActiveFlag_TC (UartInstance )) {
849+
850+ if (data -> tx_poll_stream_on ) {
851+ /* A poll stream transmition just completed,
852+ * allow system to suspend
853+ */
854+ LL_USART_DisableIT_TC (UartInstance );
855+ data -> tx_poll_stream_on = false;
856+ uart_stm32_pm_constraint_release (dev );
857+ }
858+ /* Stream transmition was either async or IRQ based,
859+ * constraint will be released at the same time TC IT
860+ * is disabled
861+ */
810862 }
863+ #endif
811864
865+ #ifdef CONFIG_UART_INTERRUPT_DRIVEN
812866 if (data -> user_cb ) {
813867 data -> user_cb (dev , data -> user_data );
814868 }
@@ -837,8 +891,9 @@ static void uart_stm32_isr(const struct device *dev)
837891 /* Generate TX_DONE event when transmission is done */
838892 async_evt_tx_done (data );
839893
840- /* allow system to suspend, UART has now finished */
841- pm_constraint_release (PM_STATE_SUSPEND_TO_IDLE );
894+ #ifdef CONFIG_PM
895+ uart_stm32_pm_constraint_release (dev );
896+ #endif
842897 }
843898
844899 /* Clear errors */
@@ -849,12 +904,18 @@ static void uart_stm32_isr(const struct device *dev)
849904static void uart_stm32_isr (const struct device * dev )
850905{
851906 USART_TypeDef * UartInstance = UART_STRUCT (dev );
907+ struct uart_stm32_data * data = DEV_DATA (dev );
852908
853909 if (LL_USART_IsActiveFlag_TC (UartInstance )) {
854910 LL_USART_ClearFlag_TC (UartInstance );
911+ LL_USART_DisableIT_TC (UartInstance );
912+
913+ __ASSERT_NO_MSG (data -> tx_poll_stream_on );
914+
915+ data -> tx_poll_stream_on = false;
855916
856917 /* allow system to suspend, UART has now finished */
857- pm_constraint_release ( PM_STATE_SUSPEND_TO_IDLE );
918+ uart_stm32_pm_constraint_release ( dev );
858919 }
859920}
860921#endif /* (CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) */
@@ -1079,8 +1140,10 @@ static int uart_stm32_async_tx(const struct device *dev,
10791140 /* Start TX timer */
10801141 async_timer_start (& data -> dma_tx .timeout_work , data -> dma_tx .timeout );
10811142
1143+ #ifdef CONFIG_PM
10821144 /* do not allow system to suspend until transmission has completed */
1083- pm_constraint_set (PM_STATE_SUSPEND_TO_IDLE );
1145+ uart_stm32_pm_constraint_set (dev );
1146+ #endif
10841147
10851148 /* Enable TX DMA requests */
10861149 uart_stm32_dma_tx_enable (dev );
@@ -1446,14 +1509,6 @@ static int uart_stm32_init(const struct device *dev)
14461509 config -> irq_config_func (dev );
14471510#endif /* defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) */
14481511
1449- #if defined(CONFIG_UART_INTERRUPT_DRIVEN ) || defined(CONFIG_PM )
1450- /* Clear TC flag */
1451- LL_USART_ClearFlag_TC (UartInstance );
1452-
1453- /* Enable TC interrupt so we can release suspend constraint when done */
1454- LL_USART_EnableIT_TC (UartInstance );
1455- #endif /* defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_PM) */
1456-
14571512#ifdef CONFIG_UART_ASYNC_API
14581513 return uart_stm32_async_init (dev );
14591514#else
0 commit comments