From d42cef17b06465393462210a224fdc5cc58b1490 Mon Sep 17 00:00:00 2001 From: Julien D'ascenzio Date: Mon, 8 Nov 2021 12:47:25 +0100 Subject: [PATCH] uart_stm32: Fix conflit between poll_out and irq API A lock was added to manage situation where the API poll_out and irq API are used in same time. Signed-off-by: Julien D'ascenzio --- drivers/serial/uart_stm32.c | 20 ++++++++++++++++---- drivers/serial/uart_stm32.h | 1 + 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 67ca8257d85..a808c36c67b 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -527,13 +527,19 @@ static void uart_stm32_poll_out(const struct device *dev, unsigned char c) { USART_TypeDef *UartInstance = UART_STRUCT(dev); + struct uart_stm32_data *data = DEV_DATA(dev); /* Wait for TXE flag to be raised */ - while (!LL_USART_IsActiveFlag_TXE(UartInstance)) { + while (1) { + if (atomic_cas(&data->tx_lock, 0, 1)) { + if (LL_USART_IsActiveFlag_TXE(UartInstance)) { + break; + } + atomic_set(&data->tx_lock, 0); + } } #ifdef CONFIG_PM - struct uart_stm32_data *data = DEV_DATA(dev); if (!data->tx_poll_stream_on) { data->tx_poll_stream_on = true; @@ -551,6 +557,7 @@ static void uart_stm32_poll_out(const struct device *dev, #endif /* CONFIG_PM */ LL_USART_TransmitData8(UartInstance, (uint8_t)c); + atomic_set(&data->tx_lock, 0); } static int uart_stm32_err_check(const struct device *dev) @@ -647,10 +654,12 @@ static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, static void uart_stm32_irq_tx_enable(const struct device *dev) { USART_TypeDef *UartInstance = UART_STRUCT(dev); - -#ifdef CONFIG_PM struct uart_stm32_data *data = DEV_DATA(dev); + while (atomic_cas(&data->tx_lock, 0, 1) == false) { + } + +#ifdef CONFIG_PM data->tx_poll_stream_on = false; uart_stm32_pm_constraint_set(dev); #endif @@ -660,9 +669,12 @@ static void uart_stm32_irq_tx_enable(const struct device *dev) static void uart_stm32_irq_tx_disable(const struct device *dev) { USART_TypeDef *UartInstance = UART_STRUCT(dev); + struct uart_stm32_data *data = DEV_DATA(dev); LL_USART_DisableIT_TC(UartInstance); + atomic_set(&data->tx_lock, 0); + #ifdef CONFIG_PM uart_stm32_pm_constraint_release(dev); #endif diff --git a/drivers/serial/uart_stm32.h b/drivers/serial/uart_stm32.h index 85762a65fff..aa22070c83a 100644 --- a/drivers/serial/uart_stm32.h +++ b/drivers/serial/uart_stm32.h @@ -58,6 +58,7 @@ struct uart_stm32_data { uint32_t baud_rate; /* clock device */ const struct device *clock; + atomic_t tx_lock; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t user_cb; void *user_data;