From c8ffeb47f7b74c980e008b94ce792117810cc42b Mon Sep 17 00:00:00 2001 From: "Kenneth J. Miller" Date: Tue, 20 Jun 2023 01:16:42 +0200 Subject: [PATCH] drivers: serial: stm32: Add persistent uart_config struct Add static uart_config struct to init macro with corresponding pointer as uart_stm32_config struct member. This struct will store boot and runtime UART configuration for reinitialization upon exiting low-power modes, where register contents might be lost. Remove hw_flow_control, parity, and baud_rate from uart_stm32_config and uart_stm32_data structs, respectively, as the need for these is now obviated by the presence of the uart_config struct, which contains equivalent members. Add default baudrate, parity, stop, and data bits constants, used to initialize the uart_config struct, in case the corresponding UART DT properties are not set. Signed-off-by: Kenneth J. Miller --- drivers/serial/uart_stm32.c | 39 +++++++++++++++++++++++++------------ drivers/serial/uart_stm32.h | 14 +++++++------ 2 files changed, 35 insertions(+), 18 deletions(-) diff --git a/drivers/serial/uart_stm32.c b/drivers/serial/uart_stm32.c index 8f74bf2868a..6c8cc43d213 100644 --- a/drivers/serial/uart_stm32.c +++ b/drivers/serial/uart_stm32.c @@ -465,6 +465,7 @@ static int uart_stm32_configure(const struct device *dev, { const struct uart_stm32_config *config = dev->config; struct uart_stm32_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; const uint32_t parity = uart_stm32_cfg2ll_parity(cfg->parity); const uint32_t stopbits = uart_stm32_cfg2ll_stopbits(config, cfg->stop_bits); const uint32_t databits = uart_stm32_cfg2ll_databits(cfg->data_bits, @@ -536,9 +537,9 @@ static int uart_stm32_configure(const struct device *dev, } #endif - if (cfg->baudrate != data->baud_rate) { + if (cfg->baudrate != uart_cfg->baudrate) { uart_stm32_set_baudrate(dev, cfg->baudrate); - data->baud_rate = cfg->baudrate; + uart_cfg->baudrate = cfg->baudrate; } LL_USART_Enable(config->usart); @@ -549,8 +550,9 @@ static int uart_stm32_config_get(const struct device *dev, struct uart_config *cfg) { struct uart_stm32_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; - cfg->baudrate = data->baud_rate; + cfg->baudrate = uart_cfg->baudrate; cfg->parity = uart_stm32_ll2cfg_parity(uart_stm32_get_parity(dev)); cfg->stop_bits = uart_stm32_ll2cfg_stopbits( uart_stm32_get_stopbits(dev)); @@ -1817,6 +1819,7 @@ static int uart_stm32_init(const struct device *dev) { const struct uart_stm32_config *config = dev->config; struct uart_stm32_data *data = dev->data; + struct uart_config *uart_cfg = data->uart_cfg; uint32_t ll_parity; uint32_t ll_datawidth; int err; @@ -1868,18 +1871,18 @@ static int uart_stm32_init(const struct device *dev) /* Determine the datawidth and parity. If we use other parity than * 'none' we must use datawidth = 9 (to get 8 databit + 1 parity bit). */ - if (config->parity == 2) { + if (uart_cfg->parity == 2) { /* 8 databit, 1 parity bit, parity even */ ll_parity = LL_USART_PARITY_EVEN; ll_datawidth = LL_USART_DATAWIDTH_9B; - } else if (config->parity == 1) { + } else if (uart_cfg->parity == 1) { /* 8 databit, 1 parity bit, parity odd */ ll_parity = LL_USART_PARITY_ODD; ll_datawidth = LL_USART_DATAWIDTH_9B; } else { /* Default to 8N0, but show warning if invalid value */ - if (config->parity != 0) { + if (uart_cfg->parity != 0) { LOG_WRN("Invalid parity setting '%d'." - "Defaulting to 'none'.", config->parity); + "Defaulting to 'none'.", uart_cfg->parity); } /* 8 databit, parity none */ ll_parity = LL_USART_PARITY_NONE; @@ -1892,12 +1895,12 @@ static int uart_stm32_init(const struct device *dev) ll_parity, LL_USART_STOPBITS_1); - if (config->hw_flow_control) { + if (uart_cfg->flow_ctrl) { uart_stm32_set_hwctrl(dev, LL_USART_HWCONTROL_RTS_CTS); } /* Set the default baudrate */ - uart_stm32_set_baudrate(dev, data->baud_rate); + uart_stm32_set_baudrate(dev, uart_cfg->baudrate); /* Enable the single wire / half-duplex mode */ if (config->single_wire) { @@ -2141,13 +2144,25 @@ PINCTRL_DT_INST_DEFINE(index); \ static const struct stm32_pclken pclken_##index[] = \ STM32_DT_INST_CLOCKS(index);\ \ +static struct uart_config uart_cfg_##index = { \ + .baudrate = DT_INST_PROP_OR(index, current_speed, \ + STM32_UART_DEFAULT_BAUDRATE), \ + .parity = DT_INST_ENUM_IDX_OR(index, parity, \ + STM32_UART_DEFAULT_PARITY), \ + .stop_bits = DT_INST_ENUM_IDX_OR(index, stop_bits, \ + STM32_UART_DEFAULT_STOP_BITS), \ + .data_bits = DT_INST_ENUM_IDX_OR(index, data_bits, \ + STM32_UART_DEFAULT_DATA_BITS), \ + .flow_ctrl = DT_INST_PROP(index, hw_flow_control) \ + ? UART_CFG_FLOW_CTRL_RTS_CTS \ + : UART_CFG_FLOW_CTRL_NONE, \ +}; \ + \ static const struct uart_stm32_config uart_stm32_cfg_##index = { \ .usart = (USART_TypeDef *)DT_INST_REG_ADDR(index), \ .reset = RESET_DT_SPEC_GET(DT_DRV_INST(index)), \ .pclken = pclken_##index, \ .pclk_len = DT_INST_NUM_CLOCKS(index), \ - .hw_flow_control = DT_INST_PROP(index, hw_flow_control), \ - .parity = DT_INST_ENUM_IDX_OR(index, parity, UART_CFG_PARITY_NONE), \ .pcfg = PINCTRL_DT_INST_DEV_CONFIG_GET(index), \ .single_wire = DT_INST_PROP_OR(index, single_wire, false), \ .tx_rx_swap = DT_INST_PROP_OR(index, tx_rx_swap, false), \ @@ -2162,7 +2177,7 @@ static const struct uart_stm32_config uart_stm32_cfg_##index = { \ }; \ \ static struct uart_stm32_data uart_stm32_data_##index = { \ - .baud_rate = DT_INST_PROP(index, current_speed), \ + .uart_cfg = &uart_cfg_##index, \ UART_DMA_CHANNEL(index, rx, RX, PERIPHERAL, MEMORY) \ UART_DMA_CHANNEL(index, tx, TX, MEMORY, PERIPHERAL) \ }; \ diff --git a/drivers/serial/uart_stm32.h b/drivers/serial/uart_stm32.h index 536b8200d35..ed8e8584cd6 100644 --- a/drivers/serial/uart_stm32.h +++ b/drivers/serial/uart_stm32.h @@ -18,6 +18,11 @@ #include +#define STM32_UART_DEFAULT_BAUDRATE 115200 +#define STM32_UART_DEFAULT_PARITY UART_CFG_PARITY_NONE +#define STM32_UART_DEFAULT_STOP_BITS UART_CFG_STOP_BITS_1 +#define STM32_UART_DEFAULT_DATA_BITS UART_CFG_DATA_BITS_8 + /* device config */ struct uart_stm32_config { /* USART instance */ @@ -28,10 +33,6 @@ struct uart_stm32_config { const struct stm32_pclken *pclken; /* number of clock subsystems */ size_t pclk_len; - /* initial hardware flow control, 1 for RTS/CTS */ - bool hw_flow_control; - /* initial parity, 0 for none, 1 for odd, 2 for even */ - int parity; /* switch to enable single wire / half duplex feature */ bool single_wire; /* enable tx/rx pin swap */ @@ -48,6 +49,7 @@ struct uart_stm32_config { uint8_t de_deassert_time; /* enable de pin inversion */ bool de_invert; + /* pin muxing */ const struct pinctrl_dev_config *pcfg; #if defined(CONFIG_UART_INTERRUPT_DRIVEN) || defined(CONFIG_UART_ASYNC_API) || \ defined(CONFIG_PM) @@ -82,10 +84,10 @@ struct uart_dma_stream { /* driver data */ struct uart_stm32_data { - /* Baud rate */ - uint32_t baud_rate; /* clock device */ const struct device *clock; + /* uart config */ + struct uart_config *uart_cfg; #ifdef CONFIG_UART_INTERRUPT_DRIVEN uart_irq_callback_user_data_t user_cb; void *user_data;