From 573eec1014c903e99a0ba37fb4c5680fedf4a431 Mon Sep 17 00:00:00 2001 From: Nicolas VINCENT Date: Wed, 10 Mar 2021 13:23:00 +0100 Subject: [PATCH] drivers: serial: stm32 databits depends on parity On stm32, the M bits defines the length of the frame between the start bit and the stop bit, eventually including the parity bit when enabled. Fix configuration of databits to set correct M bits when parity is enabled. This commit tries to address issue zephyrproject-rtos/zephyr#33351 Signed-off-by: Nicolas VINCENT --- drivers/serial/uart_stm32.c | 48 ++++++++++++++++++++++++++++++------- 1 file changed, 40 insertions(+), 8 deletions(-) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 190a89b2043..f53a442f202 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -227,13 +227,18 @@ static inline enum uart_config_stop_bits uart_stm32_ll2cfg_stopbits(uint32_t sb) } } -static inline uint32_t uart_stm32_cfg2ll_databits(enum uart_config_data_bits db) +static inline uint32_t uart_stm32_cfg2ll_databits(enum uart_config_data_bits db, + enum uart_config_parity p) { switch (db) { /* Some MCU's don't support 7B or 9B datawidth */ #ifdef LL_USART_DATAWIDTH_7B case UART_CFG_DATA_BITS_7: - return LL_USART_DATAWIDTH_7B; + if (p == UART_CFG_PARITY_NONE) { + return LL_USART_DATAWIDTH_7B; + } else { + return LL_USART_DATAWIDTH_8B; + } #endif /* LL_USART_DATAWIDTH_7B */ #ifdef LL_USART_DATAWIDTH_9B case UART_CFG_DATA_BITS_9: @@ -241,25 +246,45 @@ static inline uint32_t uart_stm32_cfg2ll_databits(enum uart_config_data_bits db) #endif /* LL_USART_DATAWIDTH_9B */ case UART_CFG_DATA_BITS_8: default: + if (p == UART_CFG_PARITY_NONE) { + return LL_USART_DATAWIDTH_8B; +#ifdef LL_USART_DATAWIDTH_9B + } else { + return LL_USART_DATAWIDTH_9B; +#endif + } return LL_USART_DATAWIDTH_8B; } } -static inline enum uart_config_data_bits uart_stm32_ll2cfg_databits(uint32_t db) +static inline enum uart_config_data_bits uart_stm32_ll2cfg_databits(uint32_t db, + uint32_t p) { switch (db) { /* Some MCU's don't support 7B or 9B datawidth */ #ifdef LL_USART_DATAWIDTH_7B case LL_USART_DATAWIDTH_7B: - return UART_CFG_DATA_BITS_7; + if (p == LL_USART_PARITY_NONE) { + return UART_CFG_DATA_BITS_7; + } else { + return UART_CFG_DATA_BITS_6; + } #endif /* LL_USART_DATAWIDTH_7B */ #ifdef LL_USART_DATAWIDTH_9B case LL_USART_DATAWIDTH_9B: - return UART_CFG_DATA_BITS_9; + if (p == LL_USART_PARITY_NONE) { + return UART_CFG_DATA_BITS_9; + } else { + return UART_CFG_DATA_BITS_8; + } #endif /* LL_USART_DATAWIDTH_9B */ case LL_USART_DATAWIDTH_8B: default: - return UART_CFG_DATA_BITS_8; + if (p == LL_USART_PARITY_NONE) { + return UART_CFG_DATA_BITS_8; + } else { + return UART_CFG_DATA_BITS_7; + } } } @@ -302,7 +327,8 @@ static int uart_stm32_configure(const struct device *dev, USART_TypeDef *UartInstance = UART_STRUCT(dev); const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity); const uint32_t stopbits = uart_stm32_cfg2ll_stopbits(cfg->stop_bits); - const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits); + const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits, + cfg->parity); const uint32_t flowctrl = uart_stm32_cfg2ll_hwctrl(cfg->flow_ctrl); /* Hardware doesn't support mark or space parity */ @@ -311,6 +337,12 @@ static int uart_stm32_configure(const struct device *dev, return -ENOTSUP; } + /* Driver does not supports parity + 9 databits */ + if ((cfg->parity != UART_CFG_PARITY_NONE) && + (cfg->data_bits == UART_CFG_DATA_BITS_9)) { + return -ENOTSUP; + } + #if defined(LL_USART_STOPBITS_0_5) && HAS_LPUART_1 if (IS_LPUART_INSTANCE(UartInstance) && (cfg->stop_bits == UART_CFG_STOP_BITS_0_5)) { @@ -388,7 +420,7 @@ static int uart_stm32_config_get(const struct device *dev, cfg->stop_bits = uart_stm32_ll2cfg_stopbits( uart_stm32_get_stopbits(dev)); cfg->data_bits = uart_stm32_ll2cfg_databits( - uart_stm32_get_databits(dev)); + uart_stm32_get_databits(dev), uart_stm32_get_parity(dev)); cfg->flow_ctrl = uart_stm32_ll2cfg_hwctrl( uart_stm32_get_hwctrl(dev)); return 0;