You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
429 lines
15 KiB
429 lines
15 KiB
diff --git NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c |
|
index 644c810..c3b08b8 100644 |
|
--- NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c |
|
+++ NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c |
|
@@ -1,7 +1,7 @@ |
|
/**************************************************************************** |
|
* arch/arm/src/stm32/stm32_serial.c |
|
* |
|
- * Copyright (C) 2009-2014, 2016 Gregory Nutt. All rights reserved. |
|
+ * Copyright (C) 2009-2014, 2016, 2017 Gregory Nutt. All rights reserved. |
|
* Author: Gregory Nutt <gnutt@nuttx.org> |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
@@ -70,6 +70,7 @@ |
|
/**************************************************************************** |
|
* Pre-processor Definitions |
|
****************************************************************************/ |
|
+ |
|
/* Some sanity checks *******************************************************/ |
|
/* DMA configuration */ |
|
|
|
@@ -150,7 +151,8 @@ |
|
# endif |
|
|
|
# elif defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) || \ |
|
- defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F30XX) |
|
+ defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F33XX) || \ |
|
+ defined(CONFIG_STM32_STM32F37XX) |
|
|
|
# if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART2_RXDMA) || \ |
|
defined(CONFIG_USART3_RXDMA) |
|
@@ -180,14 +182,21 @@ |
|
* When streaming data, the generic serial layer will be called |
|
* every time the FIFO receives half this number of bytes. |
|
*/ |
|
- |
|
-# define RXDMA_BUFFER_SIZE 32 |
|
+# if !defined(CONFIG_STM32_SERIAL_RXDMA_BUFFER_SIZE) |
|
+# define CONFIG_STM32_SERIAL_RXDMA_BUFFER_SIZE 32 |
|
+# endif |
|
+# define RXDMA_MUTIPLE 4 |
|
+# define RXDMA_MUTIPLE_MASK (RXDMA_MUTIPLE -1) |
|
+# define RXDMA_BUFFER_SIZE ((CONFIG_STM32_SERIAL_RXDMA_BUFFER_SIZE \ |
|
+ + RXDMA_MUTIPLE_MASK) \ |
|
+ & ~RXDMA_MUTIPLE_MASK) |
|
|
|
/* DMA priority */ |
|
|
|
# ifndef CONFIG_USART_DMAPRIO |
|
# if defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) || \ |
|
- defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F37XX) |
|
+ defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F33XX) || \ |
|
+ defined(CONFIG_STM32_STM32F37XX) |
|
# define CONFIG_USART_DMAPRIO DMA_CCR_PRIMED |
|
# elif defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) |
|
# define CONFIG_USART_DMAPRIO DMA_SCR_PRIMED |
|
@@ -196,7 +205,8 @@ |
|
# endif |
|
# endif |
|
# if defined(CONFIG_STM32_STM32L15XX) || defined(CONFIG_STM32_STM32F10XX) || \ |
|
- defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F37XX) |
|
+ defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F33XX) || \ |
|
+ defined(CONFIG_STM32_STM32F37XX) |
|
# if (CONFIG_USART_DMAPRIO & ~DMA_CCR_PL_MASK) != 0 |
|
# error "Illegal value for CONFIG_USART_DMAPRIO" |
|
# endif |
|
@@ -208,7 +218,7 @@ |
|
# error "Unknown STM32 DMA" |
|
# endif |
|
|
|
-/* DMA control words */ |
|
+/* DMA control word */ |
|
|
|
# if defined(CONFIG_STM32_STM32F20XX) || defined(CONFIG_STM32_STM32F40XX) |
|
# define SERIAL_DMA_CONTROL_WORD \ |
|
@@ -220,16 +230,6 @@ |
|
CONFIG_USART_DMAPRIO | \ |
|
DMA_SCR_PBURST_SINGLE | \ |
|
DMA_SCR_MBURST_SINGLE) |
|
-# ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
-# define SERIAL_DMA_IFLOW_CONTROL_WORD \ |
|
- (DMA_SCR_DIR_P2M | \ |
|
- DMA_SCR_MINC | \ |
|
- DMA_SCR_PSIZE_8BITS | \ |
|
- DMA_SCR_MSIZE_8BITS | \ |
|
- CONFIG_USART_DMAPRIO | \ |
|
- DMA_SCR_PBURST_SINGLE | \ |
|
- DMA_SCR_MBURST_SINGLE) |
|
-# endif |
|
# else |
|
# define SERIAL_DMA_CONTROL_WORD \ |
|
(DMA_CCR_CIRC | \ |
|
@@ -237,13 +237,6 @@ |
|
DMA_CCR_PSIZE_8BITS | \ |
|
DMA_CCR_MSIZE_8BITS | \ |
|
CONFIG_USART_DMAPRIO) |
|
-# ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
-# define SERIAL_DMA_IFLOW_CONTROL_WORD \ |
|
- (DMA_CCR_MINC | \ |
|
- DMA_CCR_PSIZE_8BITS | \ |
|
- DMA_CCR_MSIZE_8BITS | \ |
|
- CONFIG_USART_DMAPRIO) |
|
-# endif |
|
# endif |
|
|
|
#endif |
|
@@ -556,7 +549,11 @@ static struct up_dev_s g_usart1priv = |
|
.bits = CONFIG_USART1_BITS, |
|
.stopbits2 = CONFIG_USART1_2STOP, |
|
.baud = CONFIG_USART1_BAUD, |
|
+#if defined(CONFIG_STM32_STM32F33XX) |
|
+ .apbclock = STM32_PCLK1_FREQUENCY, /* Errata 2.5.1 */ |
|
+#else |
|
.apbclock = STM32_PCLK2_FREQUENCY, |
|
+#endif |
|
.usartbase = STM32_USART1_BASE, |
|
.tx_gpio = GPIO_USART1_TX, |
|
.rx_gpio = GPIO_USART1_RX, |
|
@@ -1088,10 +1085,10 @@ static inline void up_serialout(struct up_dev_s *priv, int offset, uint32_t valu |
|
} |
|
|
|
/**************************************************************************** |
|
- * Name: up_restoreusartint |
|
+ * Name: up_setusartint |
|
****************************************************************************/ |
|
|
|
-static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) |
|
+static inline void up_setusartint(struct up_dev_s *priv, uint16_t ie) |
|
{ |
|
uint32_t cr; |
|
|
|
@@ -1113,11 +1110,30 @@ static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) |
|
} |
|
|
|
/**************************************************************************** |
|
+ * Name: up_restoreusartint |
|
+ ****************************************************************************/ |
|
+ |
|
+static void up_restoreusartint(struct up_dev_s *priv, uint16_t ie) |
|
+{ |
|
+ irqstate_t flags; |
|
+ |
|
+ flags = enter_critical_section(); |
|
+ |
|
+ up_setusartint(priv, ie); |
|
+ |
|
+ leave_critical_section(flags); |
|
+} |
|
+ |
|
+/**************************************************************************** |
|
* Name: up_disableusartint |
|
****************************************************************************/ |
|
|
|
-static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) |
|
+static void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) |
|
{ |
|
+ irqstate_t flags; |
|
+ |
|
+ flags = enter_critical_section(); |
|
+ |
|
if (ie) |
|
{ |
|
uint32_t cr1; |
|
@@ -1154,7 +1170,9 @@ static inline void up_disableusartint(struct up_dev_s *priv, uint16_t *ie) |
|
|
|
/* Disable all interrupts */ |
|
|
|
- up_restoreusartint(priv, 0); |
|
+ up_setusartint(priv, 0); |
|
+ |
|
+ leave_critical_section(flags); |
|
} |
|
|
|
/**************************************************************************** |
|
@@ -1189,7 +1207,8 @@ static int up_dma_nextrx(struct up_dev_s *priv) |
|
static void up_set_format(struct uart_dev_s *dev) |
|
{ |
|
struct up_dev_s *priv = (struct up_dev_s *)dev->priv; |
|
-#if defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F37XX) |
|
+#if defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F33XX) || \ |
|
+ defined(CONFIG_STM32_STM32F37XX) |
|
uint32_t usartdiv8; |
|
#else |
|
uint32_t usartdiv32; |
|
@@ -1203,7 +1222,8 @@ static void up_set_format(struct uart_dev_s *dev) |
|
|
|
regval = up_serialin(priv, STM32_USART_CR1_OFFSET); |
|
|
|
-#if defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F37XX) |
|
+#if defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F33XX)|| \ |
|
+ defined(CONFIG_STM32_STM32F37XX) |
|
/* This first implementation is for U[S]ARTs that support oversampling |
|
* by 8 in additional to the standard oversampling by 16. |
|
* With baud rate of fCK / Divider for oversampling by 16. |
|
@@ -1608,28 +1628,13 @@ static int up_dma_setup(struct uart_dev_s *dev) |
|
|
|
priv->rxdma = stm32_dmachannel(priv->rxdma_channel); |
|
|
|
-#ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
- if (priv->iflow) |
|
- { |
|
- /* Configure for non-circular DMA reception into the RX FIFO */ |
|
- |
|
- stm32_dmasetup(priv->rxdma, |
|
- priv->usartbase + STM32_USART_RDR_OFFSET, |
|
- (uint32_t)priv->rxfifo, |
|
- RXDMA_BUFFER_SIZE, |
|
- SERIAL_DMA_IFLOW_CONTROL_WORD); |
|
- } |
|
- else |
|
-#endif |
|
- { |
|
- /* Configure for circular DMA reception into the RX FIFO */ |
|
+ /* Configure for circular DMA reception into the RX fifo */ |
|
|
|
- stm32_dmasetup(priv->rxdma, |
|
- priv->usartbase + STM32_USART_RDR_OFFSET, |
|
- (uint32_t)priv->rxfifo, |
|
- RXDMA_BUFFER_SIZE, |
|
- SERIAL_DMA_CONTROL_WORD); |
|
- } |
|
+ stm32_dmasetup(priv->rxdma, |
|
+ priv->usartbase + STM32_USART_RDR_OFFSET, |
|
+ (uint32_t)priv->rxfifo, |
|
+ RXDMA_BUFFER_SIZE, |
|
+ SERIAL_DMA_CONTROL_WORD); |
|
|
|
/* Reset our DMA shadow pointer to match the address just |
|
* programmed above. |
|
@@ -1643,26 +1648,12 @@ static int up_dma_setup(struct uart_dev_s *dev) |
|
regval |= USART_CR3_DMAR; |
|
up_serialout(priv, STM32_USART_CR3_OFFSET, regval); |
|
|
|
-#ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
- if (priv->iflow) |
|
- { |
|
- /* Start the DMA channel, and arrange for callbacks at the full point |
|
- * in the FIFO. After buffer gets full, hardware flow-control kicks |
|
- * in and DMA transfer is stopped. |
|
- */ |
|
- |
|
- stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, false); |
|
- } |
|
- else |
|
-#endif |
|
- { |
|
- /* Start the DMA channel, and arrange for callbacks at the half and |
|
- * full points in the FIFO. This ensures that we have half a FIFO |
|
- * worth of time to claim bytes before they are overwritten. |
|
- */ |
|
+ /* Start the DMA channel, and arrange for callbacks at the half and |
|
+ * full points in the FIFO. This ensures that we have half a FIFO |
|
+ * worth of time to claim bytes before they are overwritten. |
|
+ */ |
|
|
|
- stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, true); |
|
- } |
|
+ stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, true); |
|
|
|
return OK; |
|
} |
|
@@ -1789,6 +1780,7 @@ static int up_attach(struct uart_dev_s *dev) |
|
|
|
up_enable_irq(priv->irq); |
|
} |
|
+ |
|
return ret; |
|
} |
|
|
|
@@ -1900,7 +1892,8 @@ static int up_interrupt_common(struct up_dev_s *priv) |
|
|
|
else if ((priv->sr & (USART_SR_ORE | USART_SR_NE | USART_SR_FE)) != 0) |
|
{ |
|
-#if defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F37XX) |
|
+#if defined(CONFIG_STM32_STM32F30XX) || defined(CONFIG_STM32_STM32F33XX) || \ |
|
+ defined(CONFIG_STM32_STM32F37XX) |
|
/* These errors are cleared by writing the corresponding bit to the |
|
* interrupt clear register (ICR). |
|
*/ |
|
@@ -1945,11 +1938,11 @@ static int up_interrupt_common(struct up_dev_s *priv) |
|
static int up_ioctl(struct file *filep, int cmd, unsigned long arg) |
|
{ |
|
#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_SERIAL_TIOCSERGSTRUCT) \ |
|
- || defined(CONFIG_STM32F7_SERIALBRK_BSDCOMPAT) |
|
+ || defined(CONFIG_STM32_SERIALBRK_BSDCOMPAT) |
|
struct inode *inode = filep->f_inode; |
|
struct uart_dev_s *dev = inode->i_private; |
|
#endif |
|
-#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_STM32F7_SERIALBRK_BSDCOMPAT) |
|
+#if defined(CONFIG_SERIAL_TERMIOS) || defined(CONFIG_STM32_SERIALBRK_BSDCOMPAT) |
|
struct up_dev_s *priv = (struct up_dev_s *)dev->priv; |
|
#endif |
|
int ret = OK; |
|
@@ -2316,9 +2309,11 @@ static bool up_rxflowcontrol(struct uart_dev_s *dev, |
|
unsigned int nbuffered, bool upper) |
|
{ |
|
struct up_dev_s *priv = (struct up_dev_s *)dev->priv; |
|
+#if !(defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS) && defined(CONFIG_STM32_FLOWCONTROL_BROKEN)) |
|
+ uint16_t ie; |
|
+#endif |
|
|
|
-#if defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS) && \ |
|
- defined(CONFIG_STM32_FLOWCONTROL_BROKEN) |
|
+#if defined(CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS) && defined(CONFIG_STM32_FLOWCONTROL_BROKEN) |
|
if (priv->iflow && (priv->rts_gpio != 0)) |
|
{ |
|
/* Assert/de-assert nRTS set it high resume/stop sending */ |
|
@@ -2346,7 +2341,9 @@ static bool up_rxflowcontrol(struct uart_dev_s *dev, |
|
* enable Rx interrupts. |
|
*/ |
|
|
|
- uart_disablerxint(dev); |
|
+ ie = priv->ie; |
|
+ ie &= ~USART_CR1_RXNEIE; |
|
+ up_restoreusartint(priv, ie); |
|
return true; |
|
} |
|
|
|
@@ -2359,7 +2356,7 @@ static bool up_rxflowcontrol(struct uart_dev_s *dev, |
|
* received. |
|
*/ |
|
|
|
- uart_enablerxint(dev); |
|
+ up_rxint(dev, true); |
|
} |
|
} |
|
#endif |
|
@@ -2391,18 +2388,7 @@ static int up_dma_receive(struct uart_dev_s *dev, unsigned int *status) |
|
priv->rxdmanext++; |
|
if (priv->rxdmanext == RXDMA_BUFFER_SIZE) |
|
{ |
|
-#ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
- if (priv->iflow) |
|
- { |
|
- /* RX DMA buffer full. RX paused, RTS line pulled up to prevent |
|
- * more input data from other end. |
|
- */ |
|
- } |
|
- else |
|
-#endif |
|
- { |
|
- priv->rxdmanext = 0; |
|
- } |
|
+ priv->rxdmanext = 0; |
|
} |
|
} |
|
|
|
@@ -2411,40 +2397,6 @@ static int up_dma_receive(struct uart_dev_s *dev, unsigned int *status) |
|
#endif |
|
|
|
/**************************************************************************** |
|
- * Name: up_dma_reenable |
|
- * |
|
- * Description: |
|
- * Call to re-enable RX DMA. |
|
- * |
|
- ****************************************************************************/ |
|
- |
|
-#if defined(SERIAL_HAVE_DMA) && defined(CONFIG_SERIAL_IFLOWCONTROL) |
|
-static void up_dma_reenable(struct up_dev_s *priv) |
|
-{ |
|
- /* Configure for non-circular DMA reception into the RX fifo */ |
|
- |
|
- stm32_dmasetup(priv->rxdma, |
|
- priv->usartbase + STM32_USART_RDR_OFFSET, |
|
- (uint32_t)priv->rxfifo, |
|
- RXDMA_BUFFER_SIZE, |
|
- SERIAL_DMA_IFLOW_CONTROL_WORD); |
|
- |
|
- /* Reset our DMA shadow pointer to match the address just |
|
- * programmed above. |
|
- */ |
|
- |
|
- priv->rxdmanext = 0; |
|
- |
|
- /* Start the DMA channel, and arrange for callbacks at the full point in |
|
- * the FIFO. After buffer gets full, hardware flow-control kicks in and |
|
- * DMA transfer is stopped. |
|
- */ |
|
- |
|
- stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, false); |
|
-} |
|
-#endif |
|
- |
|
-/**************************************************************************** |
|
* Name: up_dma_rxint |
|
* |
|
* Description: |
|
@@ -2466,15 +2418,6 @@ static void up_dma_rxint(struct uart_dev_s *dev, bool enable) |
|
*/ |
|
|
|
priv->rxenable = enable; |
|
- |
|
-#ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
- if (priv->iflow && priv->rxenable && (priv->rxdmanext == RXDMA_BUFFER_SIZE)) |
|
- { |
|
- /* Re-enable RX DMA. */ |
|
- |
|
- up_dma_reenable(priv); |
|
- } |
|
-#endif |
|
} |
|
#endif |
|
|
|
@@ -2683,16 +2626,6 @@ static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg) |
|
if (priv->rxenable && up_dma_rxavailable(&priv->dev)) |
|
{ |
|
uart_recvchars(&priv->dev); |
|
- |
|
-#ifdef CONFIG_SERIAL_IFLOWCONTROL |
|
- if (priv->iflow && priv->rxenable && |
|
- (priv->rxdmanext == RXDMA_BUFFER_SIZE)) |
|
- { |
|
- /* Re-enable RX DMA. */ |
|
- |
|
- up_dma_reenable(priv); |
|
- } |
|
-#endif |
|
} |
|
} |
|
#endif |
|
@@ -2791,6 +2724,7 @@ static void up_pm_notify(struct pm_callback_s *cb, int domain, |
|
* return non-zero values when reverting back to higher power |
|
* consumption modes! |
|
* |
|
+ * |
|
****************************************************************************/ |
|
|
|
#ifdef CONFIG_PM
|
|
|