diff --git a/arch/arm/src/lpc43xx/Kconfig b/arch/arm/src/lpc43xx/Kconfig index 706dab8a36..920b601c40 100644 --- a/arch/arm/src/lpc43xx/Kconfig +++ b/arch/arm/src/lpc43xx/Kconfig @@ -485,5 +485,11 @@ config USART3_2STOP endmenu - - +config SERIAL_TERMIOS + bool "Serial driver TERMIOS supported" + depends on LPC43_USART0 || LPC43_UART1 || LPC43_USART2 || LPC43_USART3 + default n + ---help--- + Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.). + If this is not defined, then the terminal settings (baud, parity, etc). + are not configurable at runtime; serial streams cannot be flushed, etc.. diff --git a/arch/arm/src/stm32/Kconfig b/arch/arm/src/stm32/Kconfig index efeb3c8556..5d0d48f880 100644 --- a/arch/arm/src/stm32/Kconfig +++ b/arch/arm/src/stm32/Kconfig @@ -1756,6 +1756,15 @@ config USART6_RXDMA endmenu +config SERIAL_TERMIOS + bool "Serial driver TERMIOS supported" + depends on STM32_USART1 || STM32_USART2 || STM32_USART3 || STM32_UART4 || STM32_UART5 || STM32_USART6 + default n + ---help--- + Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.). + If this is not defined, then the terminal settings (baud, parity, etc). + are not configurable at runtime; serial streams cannot be flushed, etc.. + menu "SPI Configuration" depends on STM32_SPI diff --git a/arch/arm/src/stm32/stm32_serial.c b/arch/arm/src/stm32/stm32_serial.c index a5864acb63..aaed6270fa 100644 --- a/arch/arm/src/stm32/stm32_serial.c +++ b/arch/arm/src/stm32/stm32_serial.c @@ -53,6 +53,10 @@ #include #include +#ifdef CONFIG_SERIAL_TERMIOS +# include +#endif + #include #include @@ -149,11 +153,23 @@ struct up_dev_s uint16_t ie; /* Saved interrupt mask bits value */ uint16_t sr; /* Saved status bits */ - const uint8_t irq; /* IRQ associated with this USART */ + /* If termios are supported, then the following fields may vary at + * runtime. + */ + +#ifdef CONFIG_SERIAL_TERMIOS + uint8_t parity; /* 0=none, 1=odd, 2=even */ + uint8_t bits; /* Number of bits (7 or 8) */ + bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ + uint32_t baud; /* Configured baud */ +#else const uint8_t parity; /* 0=none, 1=odd, 2=even */ const uint8_t bits; /* Number of bits (7 or 8) */ const bool stopbits2; /* True: Configure with 2 stop bits instead of 1 */ const uint32_t baud; /* Configured baud */ +#endif + + const uint8_t irq; /* IRQ associated with this USART */ const uint32_t apbclock; /* PCLK 1 or 2 frequency */ const uint32_t usartbase; /* Base address of USART registers */ const uint32_t tx_gpio; /* U[S]ART TX GPIO pin configuration */ @@ -181,6 +197,7 @@ struct up_dev_s * Private Function Prototypes ****************************************************************************/ +static void up_setspeed(struct uart_dev_s *dev); static int up_setup(struct uart_dev_s *dev); static void up_shutdown(struct uart_dev_s *dev); static int up_attach(struct uart_dev_s *dev); @@ -770,6 +787,54 @@ static int up_dma_nextrx(struct up_dev_s *priv) } #endif +/**************************************************************************** + * Name: up_setspeed + * + * Description: + * Set the serial line speed. + * + ****************************************************************************/ + +#ifndef CONFIG_SUPPRESS_UART_CONFIG +static void up_setspeed(struct uart_dev_s *dev) +{ + struct up_dev_s *priv = (struct up_dev_s*)dev->priv; + uint32_t usartdiv32; + uint32_t mantissa; + uint32_t fraction; + uint32_t brr; + + /* Configure the USART Baud Rate. The baud rate for the receiver and + * transmitter (Rx and Tx) are both set to the same value as programmed + * in the Mantissa and Fraction values of USARTDIV. + * + * baud = fCK / (16 * usartdiv) + * usartdiv = fCK / (16 * baud) + * + * Where fCK is the input clock to the peripheral (PCLK1 for USART2, 3, 4, 5 + * or PCLK2 for USART1) + * + * First calculate (NOTE: all stand baud values are even so dividing by two + * does not lose precision): + * + * usartdiv32 = 32 * usartdiv = fCK / (baud/2) + */ + + usartdiv32 = priv->apbclock / (priv->baud >> 1); + + /* The mantissa part is then */ + + mantissa = usartdiv32 >> 5; + brr = mantissa << USART_BRR_MANT_SHIFT; + + /* The fractional remainder (with rounding) */ + + fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1; + brr |= fraction << USART_BRR_FRAC_SHIFT; + up_serialout(priv, STM32_USART_BRR_OFFSET, brr); +} +#endif + /**************************************************************************** * Name: up_setup * @@ -783,10 +848,6 @@ static int up_setup(struct uart_dev_s *dev) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; #ifndef CONFIG_SUPPRESS_UART_CONFIG - uint32_t usartdiv32; - uint32_t mantissa; - uint32_t fraction; - uint32_t brr; uint32_t regval; /* Note: The logic here depends on the fact that that the USART module @@ -858,34 +919,9 @@ static int up_setup(struct uart_dev_s *dev) up_serialout(priv, STM32_USART_CR3_OFFSET, regval); - /* Configure the USART Baud Rate. The baud rate for the receiver and - * transmitter (Rx and Tx) are both set to the same value as programmed - * in the Mantissa and Fraction values of USARTDIV. - * - * baud = fCK / (16 * usartdiv) - * usartdiv = fCK / (16 * baud) - * - * Where fCK is the input clock to the peripheral (PCLK1 for USART2, 3, 4, 5 - * or PCLK2 for USART1) - * - * First calculate (NOTE: all stand baud values are even so dividing by two - * does not lose precision): - * - * usartdiv32 = 32 * usartdiv = fCK / (baud/2) - */ + /* Configure the USART Baud Rate. */ - usartdiv32 = priv->apbclock / (priv->baud >> 1); - - /* The mantissa part is then */ - - mantissa = usartdiv32 >> 5; - brr = mantissa << USART_BRR_MANT_SHIFT; - - /* The fractional remainder (with rounding) */ - - fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1; - brr |= fraction << USART_BRR_FRAC_SHIFT; - up_serialout(priv, STM32_USART_BRR_OFFSET, brr); + up_setspeed(dev); /* Enable Rx, Tx, and the USART */ @@ -1182,26 +1218,75 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) { struct inode *inode = filep->f_inode; struct uart_dev_s *dev = inode->i_private; -#ifdef CONFIG_USART_BREAKS struct up_dev_s *priv = (struct up_dev_s*)dev->priv; -#endif int ret = OK; switch (cmd) { case TIOCSERGSTRUCT: { - struct up_dev_s *user = (struct up_dev_s*)arg; - if (!user) - { - ret = -EINVAL; - } - else - { - memcpy(user, dev, sizeof(struct up_dev_s)); - } - } - break; + struct up_dev_s *user = (struct up_dev_s*)arg; + if (!user) + { + ret = -EINVAL; + } + else + { + memcpy(user, dev, sizeof(struct up_dev_s)); + } + } + break; + +#ifdef CONFIG_SERIAL_TERMIOS + case TCGETS: + { + struct termios *termiosp = (struct termios*)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: (1) Note that only the BOTHER baud is returned; (2) Other + * termios fields are not yet initialized. Here we also exploit the + * internal knowledge that ctfsetospeed() is equivalent to + * cfsetispeed(). + */ + + cfsetispeed(termiosp, BOTHER); + termiosp->c_ispeed = priv->baud; + termiosp->c_ospeed = priv->baud; + } + break; + + case TCSETS: + { + struct termios *termiosp = (struct termios*)arg; + + if (!termiosp) + { + ret = -EINVAL; + break; + } + + /* TODO: Only the BOTHER speed setting is supported. Here we + * also exploit the internal knowledge that ctfgetospeed() is + * equivalent to cfgetispeed(). + */ + + if (cfgetospeed(termiosp) != BOTHER || + termiosp->c_ispeed != termiosp->c_ospeed) + { + ret = -ENOSYS; + break; + } + + priv->baud = termiosp->c_ispeed; + up_setspeed(dev); + } + break; +#endif #ifdef CONFIG_USART_BREAKS case TIOCSBRK: /* BSD compatibility: Turn break on, unconditionally */ diff --git a/arch/mips/src/pic32mx/Kconfig b/arch/mips/src/pic32mx/Kconfig index 26ec901a14..5c17f72c10 100644 --- a/arch/mips/src/pic32mx/Kconfig +++ b/arch/mips/src/pic32mx/Kconfig @@ -1188,6 +1188,15 @@ config UART6_2STOP endmenu +config SERIAL_TERMIOS + bool "Serial driver TERMIOS supported" + depends on PIC32MX_UART1 || PIC32MX_UART2 || PIC32MX_UART3 || PIC32MX_UART4 || PIC32MX_UART5 || PIC32MX_UART6 + default n + ---help--- + Serial driver supports termios.h interfaces (tcsetattr, tcflush, etc.). + If this is not defined, then the terminal settings (baud, parity, etc). + are not configurable at runtime; serial streams cannot be flushed, etc.. + choice prompt "PIC32MX PHY Selection" depends on PIC32MX_ETHERNET