diff options
author | px4dev <px4@purgatory.org> | 2013-01-14 21:01:58 -0800 |
---|---|---|
committer | px4dev <px4@purgatory.org> | 2013-01-14 21:01:58 -0800 |
commit | 854c6436b4e3b292fd04843795d0369dc8856783 (patch) | |
tree | 4d5602f5c70926d2dcd01294561ddd8df4378462 /nuttx/arch/arm/src/stm32/stm32_serial.c | |
parent | 6d138a845aabad31060bd00da0d20d177d3f4be4 (diff) | |
parent | c38ad4ded570eddadeeca3579d02dfc63dcc8a9d (diff) | |
download | px4-firmware-854c6436b4e3b292fd04843795d0369dc8856783.tar.gz px4-firmware-854c6436b4e3b292fd04843795d0369dc8856783.tar.bz2 px4-firmware-854c6436b4e3b292fd04843795d0369dc8856783.zip |
Pull NuttX up to the 6.24 release.
Merge branch 'nuttx-merge-5447'
Diffstat (limited to 'nuttx/arch/arm/src/stm32/stm32_serial.c')
-rw-r--r-- | nuttx/arch/arm/src/stm32/stm32_serial.c | 154 |
1 files changed, 133 insertions, 21 deletions
diff --git a/nuttx/arch/arm/src/stm32/stm32_serial.c b/nuttx/arch/arm/src/stm32/stm32_serial.c index 0868c3cd3..aa46a8987 100644 --- a/nuttx/arch/arm/src/stm32/stm32_serial.c +++ b/nuttx/arch/arm/src/stm32/stm32_serial.c @@ -96,6 +96,19 @@ # endif # endif +/* Currently RS-485 support cannot be enabled when RXDMA is in use due to lack + * of testing - RS-485 support was developed on STM32F1x + */ + +# if (defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_RS485)) || \ + (defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_RS485)) || \ + (defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_RS485)) || \ + (defined(CONFIG_UART4_RXDMA) && defined(CONFIG_UART4_RS485)) || \ + (defined(CONFIG_UART5_RXDMA) && defined(CONFIG_UART5_RS485)) || \ + (defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_RS485)) +# error "RXDMA and RS-485 cannot be enabled at the same time for the same U[S]ART" +# endif + /* For the F4, there are alternate DMA channels for USART1 and 6. * Logic in the board.h file make the DMA channel selection by defining * the following in the board.h file. @@ -219,6 +232,11 @@ struct up_dev_s uint32_t rxdmanext; /* Next byte in the DMA buffer to be read */ char *const rxfifo; /* Receive DMA buffer */ #endif + +#ifdef HAVE_RS485 + const uint32_t rs485_dir_gpio; /* U[S]ART RS-485 DIR GPIO pin configuration */ + const bool rs485_dir_polarity; /* U[S]ART RS-485 DIR pin state for TX enabled */ +#endif }; /**************************************************************************** @@ -415,6 +433,15 @@ static struct up_dev_s g_usart1priv = .rxfifo = g_usart1rxfifo, #endif .vector = up_interrupt_usart1, + +#ifdef CONFIG_USART1_RS485 + .rs485_dir_gpio = GPIO_USART1_RS485_DIR, +# if (CONFIG_USART1_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif }; #endif @@ -468,6 +495,15 @@ static struct up_dev_s g_usart2priv = .rxfifo = g_usart2rxfifo, #endif .vector = up_interrupt_usart2, + +#ifdef CONFIG_USART2_RS485 + .rs485_dir_gpio = GPIO_USART2_RS485_DIR, +# if (CONFIG_USART2_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif }; #endif @@ -521,6 +557,15 @@ static struct up_dev_s g_usart3priv = .rxfifo = g_usart3rxfifo, #endif .vector = up_interrupt_usart3, + +#ifdef CONFIG_USART3_RS485 + .rs485_dir_gpio = GPIO_USART3_RS485_DIR, +# if (CONFIG_USART3_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif }; #endif @@ -570,6 +615,15 @@ static struct up_dev_s g_uart4priv = .rxfifo = g_uart4rxfifo, #endif .vector = up_interrupt_uart4, + +#ifdef CONFIG_UART4_RS485 + .rs485_dir_gpio = GPIO_UART4_RS485_DIR, +# if (CONFIG_UART4_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif }; #endif @@ -619,6 +673,15 @@ static struct up_dev_s g_uart5priv = .rxfifo = g_uart5rxfifo, #endif .vector = up_interrupt_uart5, + +#ifdef CONFIG_UART5_RS485 + .rs485_dir_gpio = GPIO_UART5_RS485_DIR, +# if (CONFIG_UART5_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif }; #endif @@ -672,6 +735,15 @@ static struct up_dev_s g_usart6priv = .rxfifo = g_usart6rxfifo, #endif .vector = up_interrupt_usart6, + +#ifdef CONFIG_USART6_RS485 + .rs485_dir_gpio = GPIO_USART6_RS485_DIR, +# if (CONFIG_USART6_RS485_DIR_POLARITY == 0) + .rs485_dir_polarity = false, +# else + .rs485_dir_polarity = true, +# endif +#endif }; #endif @@ -744,8 +816,8 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) /* And restore the interrupt state (see the interrupt enable/usage table above) */ cr = up_serialin(priv, STM32_USART_CR1_OFFSET); - cr &= ~(USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE); - cr |= (ie & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE)); + cr &= ~(USART_CR1_USED_INTS); + cr |= (ie & (USART_CR1_USED_INTS)); up_serialout(priv, STM32_USART_CR1_OFFSET, cr); cr = up_serialin(priv, STM32_USART_CR3_OFFSET); @@ -772,7 +844,7 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used) * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read * " " USART_SR_ORE Overrun Error Detected - * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used) + * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (used only for RS-485) * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty * USART_CR1_PEIE 8 USART_SR_PE Parity Error * @@ -791,7 +863,7 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) * overlap. This logic would fail if we needed the break interrupt! */ - *ie = (cr1 & (USART_CR1_RXNEIE|USART_CR1_TXEIE|USART_CR1_PEIE)) | (cr3 & USART_CR3_EIE); + *ie = (cr1 & (USART_CR1_USED_INTS)) | (cr3 & USART_CR3_EIE); } /* Disable all interrupts */ @@ -853,18 +925,18 @@ static void up_set_format(struct uart_dev_s *dev) * usartdiv32 = 32 * usartdiv = fCK / (baud/2) */ - usartdiv32 = priv->apbclock / (priv->baud >> 1); + usartdiv32 = priv->apbclock / (priv->baud >> 1); - /* The mantissa part is then */ + /* The mantissa part is then */ - mantissa = usartdiv32 >> 5; - brr = mantissa << USART_BRR_MANT_SHIFT; + mantissa = usartdiv32 >> 5; + brr = mantissa << USART_BRR_MANT_SHIFT; - /* The fractional remainder (with rounding) */ + /* 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); + fraction = (usartdiv32 - (mantissa << 5) + 1) >> 1; + brr |= fraction << USART_BRR_FRAC_SHIFT; + up_serialout(priv, STM32_USART_BRR_OFFSET, brr); /* Configure parity mode */ @@ -946,6 +1018,14 @@ static int up_setup(struct uart_dev_s *dev) stm32_configgpio(priv->rts_gpio); } +#if HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + stm32_configgpio(priv->rs485_dir_gpio); + stm32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); + } +#endif + /* Configure CR2 */ /* Clear CLKEN, CPOL, CPHA, LBCL, and interrupt enable bits */ @@ -990,13 +1070,11 @@ static int up_setup(struct uart_dev_s *dev) regval = up_serialin(priv, STM32_USART_CR1_OFFSET); regval |= (USART_CR1_UE|USART_CR1_TE|USART_CR1_RE); up_serialout(priv, STM32_USART_CR1_OFFSET, regval); - -#endif /* CONFIG_SUPPRESS_UART_CONFIG */ +#endif /* Set up the cached interrupt enables value */ - up_restoreusartint(priv, 0); - + priv->ie = 0; return OK; } @@ -1217,7 +1295,7 @@ static int up_interrupt_common(struct up_dev_s *priv) * USART_CR1_IDLEIE 4 USART_SR_IDLE Idle Line Detected (not used) * USART_CR1_RXNEIE 5 USART_SR_RXNE Received Data Ready to be Read * " " USART_SR_ORE Overrun Error Detected - * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used) + * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (used only for RS-485) * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty * USART_CR1_PEIE 8 USART_SR_PE Parity Error * @@ -1232,6 +1310,21 @@ static int up_interrupt_common(struct up_dev_s *priv) * being used. */ +#ifdef HAVE_RS485 + /* Transmission of whole buffer is over - TC is set, TXEIE is cleared. + * Note - this should be first, to have the most recent TC bit value from + * SR register - sending data affects TC, but without refresh we will not + * know that... + */ + + if ((priv->sr & USART_SR_TC) != 0 && (priv->ie & USART_CR1_TCIE) != 0 && + (priv->ie & USART_CR1_TXEIE) == 0) + { + stm32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity); + up_restoreusartint(priv, priv->ie & ~USART_CR1_TCIE); + } +#endif + /* Handle incoming, receive bytes. */ if ((priv->sr & USART_SR_RXNE) != 0 && (priv->ie & USART_CR1_RXNEIE) != 0) @@ -1265,13 +1358,14 @@ static int up_interrupt_common(struct up_dev_s *priv) if ((priv->sr & USART_SR_TXE) != 0 && (priv->ie & USART_CR1_TXEIE) != 0) { - /* Transmit data regiser empty ... process outgoing bytes */ + /* Transmit data register empty ... process outgoing bytes */ uart_xmitchars(&priv->dev); handled = true; } } - return OK; + + return OK; } /**************************************************************************** @@ -1611,6 +1705,10 @@ static bool up_dma_rxavailable(struct uart_dev_s *dev) static void up_send(struct uart_dev_s *dev, int ch) { struct up_dev_s *priv = (struct up_dev_s*)dev->priv; +#ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + stm32_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity); +#endif up_serialout(priv, STM32_USART_DR_OFFSET, (uint32_t)ch); } @@ -1631,7 +1729,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable) * * Enable Bit Status Meaning Usage * ------------------ --- --------------- ---------------------------- ---------- - * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (not used) + * USART_CR1_TCIE 6 USART_SR_TC Transmission Complete (used only for RS-485) * USART_CR1_TXEIE 7 USART_SR_TXE Transmit Data Register Empty * USART_CR3_CTSIE 10 USART_SR_CTS CTS flag (not used) */ @@ -1642,7 +1740,20 @@ static void up_txint(struct uart_dev_s *dev, bool enable) /* Set to receive an interrupt when the TX data register is empty */ #ifndef CONFIG_SUPPRESS_SERIAL_INTS - up_restoreusartint(priv, priv->ie | USART_CR1_TXEIE); + uint16_t ie = priv->ie | USART_CR1_TXEIE; + + /* If RS-485 is supported on this U[S]ART, then also enable the + * transmission complete interrupt. + */ + +# ifdef HAVE_RS485 + if (priv->rs485_dir_gpio != 0) + { + ie |= USART_CR1_TCIE; + } +# endif + + up_restoreusartint(priv, ie); /* Fake a TX interrupt here by just calling uart_xmitchars() with * interrupts disabled (note this may recurse). @@ -1657,6 +1768,7 @@ static void up_txint(struct uart_dev_s *dev, bool enable) up_restoreusartint(priv, priv->ie & ~USART_CR1_TXEIE); } + irqrestore(flags); } |