diff --git a/arch/arm/src/imxrt/Kconfig b/arch/arm/src/imxrt/Kconfig index 2c6bab6ed5..252222ef3b 100644 --- a/arch/arm/src/imxrt/Kconfig +++ b/arch/arm/src/imxrt/Kconfig @@ -86,48 +86,56 @@ config IMXRT_LPUART1 bool "LPUART1" default n select LPUART1_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART2 bool "LPUART2" default n select LPUART2_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART3 bool "LPUART3" default n select LPUART3_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART4 bool "LPUART4" default n select LPUART4_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART5 bool "LPUART5" default n select LPUART5_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART6 bool "LPUART6" default n select LPUART6_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART7 bool "LPUART7" default n select LPUART7_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART config IMXRT_LPUART8 bool "LPUART8" default n select LPUART8_SERIALDRIVER + select ARCH_HAVE_SERIAL_TERMIOS select IMXRT_HAVE_LPUART endmenu # LPUART Peripherals diff --git a/arch/arm/src/imxrt/imxrt_serial.c b/arch/arm/src/imxrt/imxrt_serial.c index 45cbfe8011..7053f400ee 100644 --- a/arch/arm/src/imxrt/imxrt_serial.c +++ b/arch/arm/src/imxrt/imxrt_serial.c @@ -48,6 +48,10 @@ #include #include +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + #include #include #include @@ -726,6 +730,7 @@ static inline void imxrt_restoreuartint(struct imxrt_uart_s *priv, * enabled/disabled. */ + flags = spin_lock_irqsave(); regval = imxrt_serialin(priv, IMXRT_LPUART_CTRL_OFFSET); regval &= ~LPUART_ALL_INTS; regval |= ie; @@ -952,6 +957,166 @@ static int imxrt_ioctl(struct file *filep, int cmd, unsigned long arg) break; #endif +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios *)arg; + struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Return baud */ + + cfsetispeed(termiosp, priv->baud); + + /* Return parity */ + + termiosp->c_cflag = ((priv->parity != 0) ? PARENB : 0) | + ((priv->parity == 1) ? PARODD : 0); + + /* Return stop bits */ + + termiosp->c_cflag |= (priv->stopbits2) ? CSTOPB : 0; + +#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) + /* Return flow control */ + + termiosp->c_cflag |= (priv->flowc) ? (CCTS_OFLOW | CRTS_IFLOW): 0; +#endif + /* Return number of bits */ + + switch (priv->bits) + { + case 5: + termiosp->c_cflag |= CS5; + break; + + case 6: + termiosp->c_cflag |= CS6; + break; + + case 7: + termiosp->c_cflag |= CS7; + break; + + default: + case 8: + termiosp->c_cflag |= CS8; + break; + + case 9: + termiosp->c_cflag |= CS8 /* CS9 */; + break; + } + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios *)arg; + struct imxrt_uart_s *priv = (struct imxrt_uart_s *)dev->priv; + uint32_t baud; + uint32_t ie; + uint8_t parity; + uint8_t nbits; + bool stop2; +#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) + bool flowc; +#endif + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* Decode baud. */ + + ret = OK; + baud = cfgetispeed(termiosp); + + /* Decode number of bits */ + + switch (termiosp->c_cflag & CSIZE) + { + case CS5: + nbits = 5; + break; + + case CS6: + nbits = 6; + break; + + case CS7: + nbits = 7; + break; + + case CS8: + nbits = 8; + break; +#if 0 + case CS9: + nbits = 9; + break; +#endif + default: + ret = -EINVAL; + break; + } + + /* Decode parity */ + + if ((termiosp->c_cflag & PARENB) != 0) + { + parity = (termiosp->c_cflag & PARODD) ? 1 : 2; + } + else + { + parity = 0; + } + + /* Decode stop bits */ + + stop2 = (termiosp->c_cflag & CSTOPB) != 0; + +#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) + /* Decode flow control */ + + flowc = (termiosp->c_cflag & (CCTS_OFLOW | CRTS_IFLOW)) != 0; +#endif + /* Verify that all settings are valid before committing */ + + if (ret == OK) + { + /* Commit */ + + priv->baud = baud; + priv->parity = parity; + priv->bits = nbits; + priv->stopbits2 = stop2; +#if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL) + priv->flowc = flowc; +#endif + /* effect the changes immediately - note that we do not + * implement TCSADRAIN / TCSAFLUSH + */ + + imxrt_disableuartint(priv, &ie); + ret = imxrt_setup(dev); + + /* Restore the interrupt state */ + + imxrt_restoreuartint(priv, ie); + priv->ie = ie; + } + } + break; +#endif /* CONFIG_SERIAL_TERMIOS */ + case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ case TIOCCBRK: /* BSD compatibility: Turn break off, unconditionally */ default: