From 435d5d1a94a11cebdbdc6bc18e4c77e5c907f0b5 Mon Sep 17 00:00:00 2001 From: Jeroen van Dooren Date: Mon, 6 Feb 2023 09:49:27 +0100 Subject: [PATCH] drivers: serial: stm32: rework code for max re-use in wide data support Restructuring code for poll_in/poll_out/fifo_fill/fifo_read because for wide data support, all code is identical except the calls to LL_USART_{ReceiveData8/TransmitData8}. This allows both implementations, 8 and 9 bit data-width to call a visitor function, passing the either the 8 bit or 9 bit data-width function pointer. Signed-off-by: Jeroen van Dooren --- drivers/serial/uart_stm32.c | 110 ++++++++++++++++++++++++++++-------- 1 file changed, 88 insertions(+), 22 deletions(-) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index c02ac8508eb..8407a26e7ce 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -569,7 +569,11 @@ static int uart_stm32_config_get(const struct device *dev, } #endif /* CONFIG_UART_USE_RUNTIME_CONFIGURE */ -static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) +typedef void (*poll_in_fn)( + const struct uart_stm32_config *config, + void *in); + +static int uart_stm32_poll_in_visitor(const struct device *dev, void *in, poll_in_fn get_fn) { const struct uart_stm32_config *config = dev->config; @@ -586,13 +590,15 @@ static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) return -1; } - *c = (unsigned char)LL_USART_ReceiveData8(config->usart); + get_fn(config, in); return 0; } -static void uart_stm32_poll_out(const struct device *dev, - unsigned char c) +typedef void (*poll_out_fn)( + const struct uart_stm32_config *config, void *out); + +static void uart_stm32_poll_out_visitor(const struct device *dev, void *out, poll_out_fn set_fn) { const struct uart_stm32_config *config = dev->config; #ifdef CONFIG_PM @@ -635,10 +641,30 @@ static void uart_stm32_poll_out(const struct device *dev, } #endif /* CONFIG_PM */ - LL_USART_TransmitData8(config->usart, (uint8_t)c); + set_fn(config, out); irq_unlock(key); } +static void uart_stm32_poll_in_u8(const struct uart_stm32_config *config, void *in) +{ + *((unsigned char *)in) = (unsigned char)LL_USART_ReceiveData8(config->usart); +} + +static void uart_stm32_poll_out_u8(const struct uart_stm32_config *config, void *out) +{ + LL_USART_TransmitData8(config->usart, *((uint8_t *)out)); +} + +static int uart_stm32_poll_in(const struct device *dev, unsigned char *c) +{ + return uart_stm32_poll_in_visitor(dev, (void *)c, uart_stm32_poll_in_u8); +} + +static void uart_stm32_poll_out(const struct device *dev, unsigned char c) +{ + uart_stm32_poll_out_visitor(dev, (void *)&c, uart_stm32_poll_out_u8); +} + static int uart_stm32_err_check(const struct device *dev) { const struct uart_stm32_config *config = dev->config; @@ -708,9 +734,11 @@ static inline void __uart_stm32_get_clock(const struct device *dev) #ifdef CONFIG_UART_INTERRUPT_DRIVEN -static int uart_stm32_fifo_fill(const struct device *dev, - const uint8_t *tx_data, - int size) +typedef void (*fifo_fill_fn)(const struct uart_stm32_config *config, const void *tx_data, + const uint8_t offset); + +static int uart_stm32_fifo_fill_visitor(const struct device *dev, const void *tx_data, int size, + fifo_fill_fn fill_fn) { const struct uart_stm32_config *config = dev->config; uint8_t num_tx = 0U; @@ -723,12 +751,12 @@ static int uart_stm32_fifo_fill(const struct device *dev, /* Lock interrupts to prevent nested interrupts or thread switch */ key = irq_lock(); - while ((size - num_tx > 0) && - LL_USART_IsActiveFlag_TXE(config->usart)) { + while ((size - num_tx > 0) && LL_USART_IsActiveFlag_TXE(config->usart)) { /* TXE flag will be cleared with byte write to DR|RDR register */ - /* Send a character (8bit , parity none) */ - LL_USART_TransmitData8(config->usart, tx_data[num_tx++]); + /* Send a character */ + fill_fn(config, tx_data, num_tx); + num_tx++; } irq_unlock(key); @@ -736,32 +764,70 @@ static int uart_stm32_fifo_fill(const struct device *dev, return num_tx; } -static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, - const int size) +static void fifo_fill_with_u8(const struct uart_stm32_config *config, + const void *tx_data, const uint8_t offset) +{ + const uint8_t *data = (const uint8_t *)tx_data; + /* Send a character (8bit) */ + LL_USART_TransmitData8(config->usart, data[offset]); +} + +static int uart_stm32_fifo_fill(const struct device *dev, const uint8_t *tx_data, int size) +{ + if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) == + UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + return uart_stm32_fifo_fill_visitor(dev, (const void *)tx_data, size, + fifo_fill_with_u8); +} + +typedef void (*fifo_read_fn)(const struct uart_stm32_config *config, void *rx_data, + const uint8_t offset); + +static int uart_stm32_fifo_read_visitor(const struct device *dev, void *rx_data, const int size, + fifo_read_fn read_fn) { const struct uart_stm32_config *config = dev->config; uint8_t num_rx = 0U; - while ((size - num_rx > 0) && - LL_USART_IsActiveFlag_RXNE(config->usart)) { + while ((size - num_rx > 0) && LL_USART_IsActiveFlag_RXNE(config->usart)) { /* RXNE flag will be cleared upon read from DR|RDR register */ - /* Receive a character (8bit , parity none) */ - rx_data[num_rx++] = LL_USART_ReceiveData8(config->usart); + read_fn(config, rx_data, num_rx); + num_rx++; /* Clear overrun error flag */ if (LL_USART_IsActiveFlag_ORE(config->usart)) { LL_USART_ClearFlag_ORE(config->usart); - /* - * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by - * the uart_err_check function call (on errors flags clearing) - */ + /* + * On stm32 F4X, F1X, and F2X, the RXNE flag is affected (cleared) by + * the uart_err_check function call (on errors flags clearing) + */ } } return num_rx; } +static void fifo_read_with_u8(const struct uart_stm32_config *config, void *rx_data, + const uint8_t offset) +{ + uint8_t *data = (uint8_t *)rx_data; + + data[offset] = LL_USART_ReceiveData8(config->usart); +} + +static int uart_stm32_fifo_read(const struct device *dev, uint8_t *rx_data, const int size) +{ + if (uart_stm32_ll2cfg_databits(uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)) == + UART_CFG_DATA_BITS_9) { + return -ENOTSUP; + } + return uart_stm32_fifo_read_visitor(dev, (void *)rx_data, size, + fifo_read_with_u8); +} + static void uart_stm32_irq_tx_enable(const struct device *dev) { const struct uart_stm32_config *config = dev->config;