Skip to content

Commit c1297a7

Browse files
committed
drivers: serial: stm32: Fix flawed runtime config check
Replace incorrect and limited runtime parity/data bits conditional configuration with build-time logic using BUILD_ASSERT. This allows for more flexible UART configurations, while preventing invalid DTS configurations at build-time. Signed-off-by: Kenneth J. Miller <[email protected]>
1 parent 1f294bd commit c1297a7

File tree

1 file changed

+112
-1
lines changed

1 file changed

+112
-1
lines changed

drivers/serial/uart_stm32.c

Lines changed: 112 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,112 @@ static void uart_stm32_irq_config_func_##index(const struct device *dev) \
21662166
#define STM32_UART_PM_WAKEUP(index) /* Not used */
21672167
#endif
21682168

2169+
/* Ensure DTS doesn't present an incompatible parity configuration.
2170+
* Mark/space parity isn't supported on the STM32 family.
2171+
* If 9 data bits are configured, ensure that a parity bit isn't set.
2172+
*/
2173+
#define STM32_UART_CHECK_DT_PARITY(index) \
2174+
BUILD_ASSERT( \
2175+
!(DT_INST_ENUM_IDX_OR(index, parity, STM32_UART_DEFAULT_PARITY) \
2176+
== UART_CFG_PARITY_MARK || \
2177+
DT_INST_ENUM_IDX_OR(index, parity, STM32_UART_DEFAULT_PARITY) \
2178+
== UART_CFG_PARITY_SPACE), \
2179+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2180+
" has unsupported parity configuration"); \
2181+
BUILD_ASSERT( \
2182+
!(DT_INST_ENUM_IDX_OR(index, parity, STM32_UART_DEFAULT_PARITY) \
2183+
!= UART_CFG_PARITY_NONE && \
2184+
DT_INST_ENUM_IDX_OR(index, data_bits, \
2185+
STM32_UART_DEFAULT_DATA_BITS) \
2186+
== UART_CFG_DATA_BITS_9), \
2187+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2188+
" has unsupported parity + data bits combination");
2189+
2190+
/* Ensure DTS doesn't present an incompatible data bits configuration
2191+
* The STM32 family doesn't support 5 data bits, or 6 data bits without parity.
2192+
* Only some series support 7 data bits.
2193+
*/
2194+
#ifdef LL_USART_DATAWIDTH_7B
2195+
#define STM32_UART_CHECK_DT_DATA_BITS(index) \
2196+
BUILD_ASSERT( \
2197+
!(DT_INST_ENUM_IDX_OR(index, data_bits, \
2198+
STM32_UART_DEFAULT_DATA_BITS) \
2199+
== UART_CFG_DATA_BITS_5 || \
2200+
(DT_INST_ENUM_IDX_OR(index, data_bits, \
2201+
STM32_UART_DEFAULT_DATA_BITS) \
2202+
== UART_CFG_DATA_BITS_6 && \
2203+
DT_INST_ENUM_IDX_OR(index, parity, \
2204+
STM32_UART_DEFAULT_PARITY) \
2205+
== UART_CFG_PARITY_NONE)), \
2206+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2207+
" has unsupported data bits configuration");
2208+
#else
2209+
#define STM32_UART_CHECK_DT_DATA_BITS(index) \
2210+
BUILD_ASSERT( \
2211+
!(DT_INST_ENUM_IDX_OR(index, data_bits, \
2212+
STM32_UART_DEFAULT_DATA_BITS) \
2213+
== UART_CFG_DATA_BITS_5 || \
2214+
DT_INST_ENUM_IDX_OR(index, data_bits, \
2215+
STM32_UART_DEFAULT_DATA_BITS) \
2216+
== UART_CFG_DATA_BITS_6 || \
2217+
(DT_INST_ENUM_IDX_OR(index, data_bits, \
2218+
STM32_UART_DEFAULT_DATA_BITS) \
2219+
== UART_CFG_DATA_BITS_7 && \
2220+
DT_INST_ENUM_IDX_OR(index, parity, \
2221+
STM32_UART_DEFAULT_PARITY) \
2222+
== UART_CFG_PARITY_NONE)), \
2223+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2224+
" has unsupported data bits configuration");
2225+
#endif
2226+
2227+
/* Ensure DTS doesn't present an incompatible stop bits configuration.
2228+
* Some STM32 series USARTs don't support 0.5 stop bits, and it generally isn't
2229+
* supported for LPUART.
2230+
*/
2231+
#ifndef LL_USART_STOPBITS_0_5
2232+
#define STM32_UART_CHECK_DT_STOP_BITS_0_5(index) \
2233+
BUILD_ASSERT( \
2234+
!(DT_INST_ENUM_IDX_OR(index, stop_bits, \
2235+
STM32_UART_DEFAULT_STOP_BITS) \
2236+
== UART_CFG_STOP_BITS_0_5), \
2237+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2238+
" has unsupported stop bits configuration");
2239+
/* LPUARTs don't support 0.5 stop bits configurations */
2240+
#else
2241+
#define STM32_UART_CHECK_DT_STOP_BITS_0_5(index) \
2242+
BUILD_ASSERT( \
2243+
!(DT_HAS_COMPAT_STATUS_OKAY(st_stm32_lpuart) && \
2244+
DT_INST_ENUM_IDX_OR(index, stop_bits, \
2245+
STM32_UART_DEFAULT_STOP_BITS) \
2246+
== UART_CFG_STOP_BITS_0_5), \
2247+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2248+
" has unsupported stop bits configuration");
2249+
#endif
2250+
2251+
/* Ensure DTS doesn't present an incompatible stop bits configuration.
2252+
* Some STM32 series USARTs don't support 1.5 stop bits, and it generally isn't
2253+
* supported for LPUART.
2254+
*/
2255+
#ifndef LL_USART_STOPBITS_1_5
2256+
#define STM32_UART_CHECK_DT_STOP_BITS_1_5(index) \
2257+
BUILD_ASSERT( \
2258+
DT_INST_ENUM_IDX_OR(index, stop_bits, \
2259+
STM32_UART_DEFAULT_STOP_BITS) \
2260+
!= UART_CFG_STOP_BITS_1_5, \
2261+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2262+
" has unsupported stop bits configuration");
2263+
/* LPUARTs don't support 1.5 stop bits configurations */
2264+
#else
2265+
#define STM32_UART_CHECK_DT_STOP_BITS_1_5(index) \
2266+
BUILD_ASSERT( \
2267+
!(DT_HAS_COMPAT_STATUS_OKAY(st_stm32_lpuart) && \
2268+
DT_INST_ENUM_IDX_OR(index, stop_bits, \
2269+
STM32_UART_DEFAULT_STOP_BITS) \
2270+
== UART_CFG_STOP_BITS_1_5), \
2271+
"Node " DT_NODE_PATH(DT_DRV_INST(index)) \
2272+
" has unsupported stop bits configuration");
2273+
#endif
2274+
21692275
#define STM32_UART_INIT(index) \
21702276
STM32_UART_IRQ_HANDLER_DECL(index) \
21712277
\
@@ -2221,6 +2327,11 @@ DEVICE_DT_INST_DEFINE(index, \
22212327
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY, \
22222328
&uart_stm32_driver_api); \
22232329
\
2224-
STM32_UART_IRQ_HANDLER(index)
2330+
STM32_UART_IRQ_HANDLER(index) \
2331+
\
2332+
STM32_UART_CHECK_DT_PARITY(index) \
2333+
STM32_UART_CHECK_DT_DATA_BITS(index) \
2334+
STM32_UART_CHECK_DT_STOP_BITS_0_5(index) \
2335+
STM32_UART_CHECK_DT_STOP_BITS_1_5(index)
22252336

22262337
DT_INST_FOREACH_STATUS_OKAY(STM32_UART_INIT)

0 commit comments

Comments
 (0)