From fd3e524c0f19f36c80f7b6e0402eb2f952beccfa Mon Sep 17 00:00:00 2001 From: Jiri Vlasak Date: Fri, 20 Feb 2026 10:55:07 +0100 Subject: [PATCH] kinetis/serial: Enable RTS as GPIO for RS485CONTROL When using CONFIG_UART?_RS485CONTROL, RTS pin is set high when sending data and low otherwise. PIN_UART?_RTS is defined in the board.h file as the appropriate ALT functionality of the chip's port. However, it may happen that PIN_UART?_RTS is wired to another pin of the chip that does not support the RTS as ALT functionality of the UART? in question. This commit addresses such a situation. When UART?_RS485CONTROL_RTSISGPIO is set in menuconfig for the given UART?, it is expected that the PIN_UART?_RTS is defined as GPIO_OUTPUT, and the PIN_UART?_RTS is set high when sending data and low otherwise. Signed-off-by: Jiri Vlasak --- arch/arm/src/kinetis/Kconfig | 66 +++++++++++++++++ arch/arm/src/kinetis/kinetis_serial.c | 103 ++++++++++++++++++++++++++ 2 files changed, 169 insertions(+) diff --git a/arch/arm/src/kinetis/Kconfig b/arch/arm/src/kinetis/Kconfig index 4349d5ee7e8..3403ae098c3 100644 --- a/arch/arm/src/kinetis/Kconfig +++ b/arch/arm/src/kinetis/Kconfig @@ -1409,6 +1409,17 @@ config UART0_RS485CONTROL ---help--- Enable RS-485 transmit enable on UART0. +config UART0_RS485CONTROL_RTSISGPIO + bool "RTS pin of the UART0 is GPIO" + default n + depends on UART0_RS485CONTROL + ---help--- + RTS pin of the UART0 is wired to something else than the chip's + ALT pin with UART0 RTS functionality. + + The GPIO, to which the UART0's RTS pin is wired to, is set to + high when sending data and low otherwise. + config UART1_RS485CONTROL bool "Use UART1 RTS as RS-485 transmit enable" default n @@ -1417,6 +1428,17 @@ config UART1_RS485CONTROL ---help--- Enable RS-485 transmit enable on UART1. +config UART1_RS485CONTROL_RTSISGPIO + bool "RTS pin of the UART1 is GPIO" + default n + depends on UART1_RS485CONTROL + ---help--- + RTS pin of the UART1 is wired to something else than the chip's + ALT pin with UART1 RTS functionality. + + The GPIO, to which the UART1's RTS pin is wired to, is set to + high when sending data and low otherwise. + config UART2_RS485CONTROL bool "Use UART2 RTS as RS-485 transmit enable" default n @@ -1425,6 +1447,17 @@ config UART2_RS485CONTROL ---help--- Enable RS-485 transmit enable on UART2. +config UART2_RS485CONTROL_RTSISGPIO + bool "RTS pin of the UART2 is GPIO" + default n + depends on UART2_RS485CONTROL + ---help--- + RTS pin of the UART2 is wired to something else than the chip's + ALT pin with UART2 RTS functionality. + + The GPIO, to which the UART2's RTS pin is wired to, is set to + high when sending data and low otherwise. + config UART3_RS485CONTROL bool "Use UART3 RTS as RS-485 transmit enable" default n @@ -1433,6 +1466,17 @@ config UART3_RS485CONTROL ---help--- Enable RS-485 transmit enable on UART3. +config UART3_RS485CONTROL_RTSISGPIO + bool "RTS pin of the UART3 is GPIO" + default n + depends on UART3_RS485CONTROL + ---help--- + RTS pin of the UART3 is wired to something else than the chip's + ALT pin with UART3 RTS functionality. + + The GPIO, to which the UART3's RTS pin is wired to, is set to + high when sending data and low otherwise. + config UART4_RS485CONTROL bool "Use UART4 RTS as RS-485 transmit enable" default n @@ -1441,6 +1485,17 @@ config UART4_RS485CONTROL ---help--- Enable RS-485 transmit enable on UART4. +config UART4_RS485CONTROL_RTSISGPIO + bool "RTS pin of the UART4 is GPIO" + default n + depends on UART4_RS485CONTROL + ---help--- + RTS pin of the UART4 is wired to something else than the chip's + ALT pin with UART4 RTS functionality. + + The GPIO, to which the UART4's RTS pin is wired to, is set to + high when sending data and low otherwise. + config UART5_RS485CONTROL bool "Use UART5 RTS as RS-485 transmit enable" default n @@ -1449,6 +1504,17 @@ config UART5_RS485CONTROL ---help--- Enable RS-485 transmit enable on UART5. +config UART5_RS485CONTROL_RTSISGPIO + bool "RTS pin of the UART5 is GPIO" + default n + depends on UART5_RS485CONTROL + ---help--- + RTS pin of the UART5 is wired to something else than the chip's + ALT pin with UART5 RTS functionality. + + The GPIO, to which the UART5's RTS pin is wired to, is set to + high when sending data and low otherwise. + endmenu # Kinetis RS485 transmit driver support endmenu # Kinetis UART Configuration diff --git a/arch/arm/src/kinetis/kinetis_serial.c b/arch/arm/src/kinetis/kinetis_serial.c index 5ce2fd4cb9f..232f0999aa9 100644 --- a/arch/arm/src/kinetis/kinetis_serial.c +++ b/arch/arm/src/kinetis/kinetis_serial.c @@ -1296,6 +1296,107 @@ static int up_interrupts(int irq, void *context, void *arg) uart_xmitchars(dev); handled = true; } + + if ((s1 & UART_S1_TC) == 0) + { + /* TC cleared, transmission started. */ + +#if defined(CONFIG_UART0_RS485CONTROL_RTSISGPIO) + if (&g_uart0priv == priv) + { + kinetis_gpiowrite(g_uart0priv.rts_gpio, 1); + handled = true; + } + +#endif +#if defined(CONFIG_UART1_RS485CONTROL_RTSISGPIO) + if (&g_uart1priv == priv) + { + kinetis_gpiowrite(g_uart1priv.rts_gpio, 1); + handled = true; + } + +#endif +#if defined(CONFIG_UART2_RS485CONTROL_RTSISGPIO) + if (&g_uart2priv == priv) + { + kinetis_gpiowrite(g_uart2priv.rts_gpio, 1); + handled = true; + } + +#endif +#if defined(CONFIG_UART3_RS485CONTROL_RTSISGPIO) + if (&g_uart3priv == priv) + { + kinetis_gpiowrite(g_uart3priv.rts_gpio, 1); + handled = true; + } + +#endif +#if defined(CONFIG_UART4_RS485CONTROL_RTSISGPIO) + if (&g_uart4priv == priv) + { + kinetis_gpiowrite(g_uart4priv.rts_gpio, 1); + handled = true; + } + +#endif +#if defined(CONFIG_UART5_RS485CONTROL_RTSISGPIO) + if (&g_uart5priv == priv) + { + kinetis_gpiowrite(g_uart5priv.rts_gpio, 1); + handled = true; + } + +#endif + } + else + { + /* Transmission complete. Do not set handle, exit immediately. */ + +#if defined(CONFIG_UART0_RS485CONTROL_RTSISGPIO) + if (&g_uart0priv == priv) + { + kinetis_gpiowrite(g_uart0priv.rts_gpio, 0); + } + +#endif +#if defined(CONFIG_UART1_RS485CONTROL_RTSISGPIO) + if (&g_uart1priv == priv) + { + kinetis_gpiowrite(g_uart1priv.rts_gpio, 0); + } + +#endif +#if defined(CONFIG_UART2_RS485CONTROL_RTSISGPIO) + if (&g_uart2priv == priv) + { + kinetis_gpiowrite(g_uart2priv.rts_gpio, 0); + } + +#endif +#if defined(CONFIG_UART3_RS485CONTROL_RTSISGPIO) + if (&g_uart3priv == priv) + { + kinetis_gpiowrite(g_uart3priv.rts_gpio, 0); + } + +#endif +#if defined(CONFIG_UART4_RS485CONTROL_RTSISGPIO) + if (&g_uart4priv == priv) + { + kinetis_gpiowrite(g_uart4priv.rts_gpio, 0); + } + +#endif +#if defined(CONFIG_UART5_RS485CONTROL_RTSISGPIO) + if (&g_uart5priv == priv) + { + kinetis_gpiowrite(g_uart5priv.rts_gpio, 0); + } + +#endif + } } return OK; @@ -1919,6 +2020,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable) #ifndef CONFIG_SUPPRESS_SERIAL_INTS priv->ie |= UART_C2_TIE; + priv->ie |= UART_C2_TCIE; up_setuartint(priv); /* Fake a TX interrupt here by just calling uart_xmitchars() with @@ -1933,6 +2035,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable) /* Disable the TX interrupt */ priv->ie &= ~UART_C2_TIE; + priv->ie &= ~UART_C2_TCIE; up_setuartint(priv); }