diff --git a/arch/arm/src/stm32f7/Kconfig b/arch/arm/src/stm32f7/Kconfig index d5f19303da..44f60266dd 100644 --- a/arch/arm/src/stm32f7/Kconfig +++ b/arch/arm/src/stm32f7/Kconfig @@ -1977,6 +1977,22 @@ config STM32F7_USART_SINGLEWIRE Enable single wire UART support. The option enables support for the TIOCSSINGLEWIRE ioctl in the STM32F7 serial driver. +config STM32F7_USART_INVERT + bool "Signal Invert Support" + default n + depends on STM32F7_USART + ---help--- + Enable signal inversion UART support. The option enables support for the + TIOCSINVERT ioctl in the STM32F7 serial driver. + +config STM32F7_USART_SWAP + bool "Swap RX/TX pins support" + default n + depends on STM32F7_USART + ---help--- + Enable RX/TX pin swapping support. The option enables support for the + TIOCSSWAP ioctl in the STM32F7 serial driver. + if PM config STM32F7_PM_SERIAL_ACTIVITY diff --git a/arch/arm/src/stm32f7/stm32_serial.c b/arch/arm/src/stm32f7/stm32_serial.c index cdf924ea09..c3b1d830cb 100644 --- a/arch/arm/src/stm32f7/stm32_serial.c +++ b/arch/arm/src/stm32f7/stm32_serial.c @@ -74,7 +74,9 @@ /**************************************************************************** * Pre-processor Definitions ****************************************************************************/ + /* Some sanity checks *******************************************************/ + /* Total number of possible serial devices */ #define STM32_NSERIAL (STM32F7_NUSART + STM32F7_NUART) @@ -1258,12 +1260,13 @@ static void up_set_format(struct uart_dev_s *dev) /* Get the original state of UE */ - cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); + cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); cr1_ue = cr1 & USART_CR1_UE; - cr1 &= ~USART_CR1_UE; + cr1 &= ~USART_CR1_UE; /* Disable UE as the format bits and baud rate registers can not be - * updated while UE = 1 */ + * updated while UE = 1 + */ up_serialout(priv, STM32_USART_CR1_OFFSET, cr1); @@ -1354,7 +1357,7 @@ static void up_set_format(struct uart_dev_s *dev) /* Configure STOP bits */ - regval = up_serialin(priv, STM32_USART_CR2_OFFSET); + regval = up_serialin(priv, STM32_USART_CR2_OFFSET); regval &= ~(USART_CR2_STOP_MASK); if (priv->stopbits2) @@ -1683,6 +1686,7 @@ static int up_setup(struct uart_dev_s *dev) #endif /* Configure CR2 */ + /* Clear STOP, CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */ regval = up_serialin(priv, STM32_USART_CR2_OFFSET); @@ -1699,6 +1703,7 @@ static int up_setup(struct uart_dev_s *dev) up_serialout(priv, STM32_USART_CR2_OFFSET, regval); /* Configure CR1 */ + /* Clear TE, REm and all interrupt enable bits */ regval = up_serialin(priv, STM32_USART_CR1_OFFSET); @@ -1707,6 +1712,7 @@ static int up_setup(struct uart_dev_s *dev) up_serialout(priv, STM32_USART_CR1_OFFSET, regval); /* Configure CR3 */ + /* Clear CTSE, RTSE, and all interrupt enable bits */ regval = up_serialin(priv, STM32_USART_CR3_OFFSET); @@ -2148,6 +2154,99 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) break; #endif +#ifdef CONFIG_STM32F7_USART_INVERT + case TIOCSINVERT: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Get the original state of UE */ + + cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; + + /* Disable UE, {R,T}XINV can only be written when UE=0 */ + + up_serialout(priv, STM32_USART_CR1_OFFSET, cr1); + + /* Enable/disable signal inversion. */ + + uint32_t cr = up_serialin(priv, STM32_USART_CR2_OFFSET); + + if (arg & SER_INVERT_ENABLED_RX) + { + cr |= USART_CR2_RXINV; + } + else + { + cr &= ~USART_CR2_RXINV; + } + + if (arg & SER_INVERT_ENABLED_TX) + { + cr |= USART_CR2_TXINV; + } + else + { + cr &= ~USART_CR2_TXINV; + } + + up_serialout(priv, STM32_USART_CR2_OFFSET, cr); + + /* Re-enable UE if appropriate */ + + up_serialout(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; +#endif + +#ifdef CONFIG_STM32F7_USART_SWAP + case TIOCSSWAP: + { + uint32_t cr1; + uint32_t cr1_ue; + irqstate_t flags; + + flags = enter_critical_section(); + + /* Get the original state of UE */ + + cr1 = up_serialin(priv, STM32_USART_CR1_OFFSET); + cr1_ue = cr1 & USART_CR1_UE; + cr1 &= ~USART_CR1_UE; + + /* Disable UE, SWAP can only be written when UE=0 */ + + up_serialout(priv, STM32_USART_CR1_OFFSET, cr1); + + /* Enable/disable Swap mode. */ + + uint32_t cr = up_serialin(priv, STM32_USART_CR2_OFFSET); + + if (arg == SER_SWAP_ENABLED) + { + cr |= USART_CR2_SWAP; + } + else + { + cr &= ~USART_CR2_SWAP; + } + + up_serialout(priv, STM32_USART_CR2_OFFSET, cr); + + /* Re-enable UE if appropriate */ + + up_serialout(priv, STM32_USART_CR1_OFFSET, cr1 | cr1_ue); + leave_critical_section(flags); + } + break; +#endif + #ifdef CONFIG_SERIAL_TERMIOS case TCGETS: { @@ -2258,9 +2357,10 @@ static int up_ioctl(struct file *filep, int cmd, unsigned long arg) up_txint(dev, false); - /* Configure TX as a GPIO output pin and Send a break signal*/ + /* Configure TX as a GPIO output pin and Send a break signal */ - tx_break = GPIO_OUTPUT | (~(GPIO_MODE_MASK|GPIO_OUTPUT_SET) & priv->tx_gpio); + tx_break = GPIO_OUTPUT | + (~(GPIO_MODE_MASK | GPIO_OUTPUT_SET) & priv->tx_gpio); stm32_configgpio(tx_break); leave_critical_section(flags); @@ -2998,6 +3098,7 @@ static int up_pm_prepare(struct pm_callback_s *cb, int domain, default: /* Should not get here */ + break; } diff --git a/include/nuttx/serial/tioctl.h b/include/nuttx/serial/tioctl.h index 5cde650765..614b126984 100644 --- a/include/nuttx/serial/tioctl.h +++ b/include/nuttx/serial/tioctl.h @@ -190,6 +190,21 @@ #define TIOCSERGSTRUCT _TIOC(0x0032) /* Get device TTY structure */ +/* Inversion Support */ + +#define TIOCSINVERT _TIOC(0x0033) /* Set Singal Inversion */ +#define TIOCGINVERT _TIOC(0x0034) /* Get Singal Inversion */ + +#define SER_INVERT_ENABLED_RX (1 << 0) /* Enable/disable signal inversion for RX */ +#define SER_INVERT_ENABLED_TX (1 << 1) /* Enable/disable signal inversion for TX */ + +/* RX/TX Swap Support */ + +#define TIOCSSWAP _TIOC(0x0035) /* Set RX/TX Swap */ +#define TIOCGSWAP _TIOC(0x0036) /* Get RX/TX Swap */ + +#define SER_SWAP_ENABLED (1 << 0) /* Enable/disable RX/TX swap */ + /******************************************************************************************** * Public Type Definitions ********************************************************************************************/