Files
PX4-Autopilot/nuttx-patches/serial_dma_hotfix.patch
T
David Sidrane e15b67ff70 HOTFIX:For Data loss on Nuttx serial w/ DMA & GPIO Flow Control
This hot fix essentialy revert commit 265af481209d60033f7cd4c4216048b1ce3eb435
   in NuttX/nuttx. The commit STM32 serial: Make input hardware flow-control work with RX DMA.
   From Jussi Kivilinna has broken the DMA on an STM32F4 in a yet TBD way.
   The symptoms are lost data on RX, the DMA count decrements but
   the data ia not written to memory. This looks to be introduced but the
   non circular DMA settings.
2016-12-24 09:42:48 +01:00

289 lines
9.5 KiB
Diff

diff --git NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c
index 644c810..80bb69a 100644
--- NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c
+++ NuttX/nuttx/arch/arm/src/stm32/stm32_serial.c
@@ -208,7 +208,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 +220,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 +227,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
@@ -1608,28 +1591,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 +1611,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;
}
@@ -1817,7 +1771,7 @@ static void up_detach(struct uart_dev_s *dev)
* interrupt received on the 'irq' It should call uart_transmitchars or
* uart_receivechar to perform the appropriate data transfers. The
* interrupt handling logic must be able to map the 'irq' number into the
- * appropriate uart_dev_s structure in order to call these functions.
+ * approprite uart_dev_s structure in order to call these functions.
*
****************************************************************************/
@@ -2316,9 +2270,9 @@ 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;
+ uint16_t ie;
-#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 +2300,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 +2315,7 @@ static bool up_rxflowcontrol(struct uart_dev_s *dev,
* received.
*/
- uart_enablerxint(dev);
+ up_rxint(dev, true);
}
}
#endif
@@ -2391,18 +2347,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 +2356,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 +2377,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
@@ -2510,14 +2412,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);
- }
+ stm32_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity);
#endif
-
up_serialout(priv, STM32_USART_TDR_OFFSET, (uint32_t)ch);
}
@@ -2683,16 +2581,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
@@ -2707,7 +2595,7 @@ static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
* Input Parameters:
*
* cb - Returned to the driver. The driver version of the callback
- * structure may include additional, driver-specific state data at
+ * strucure may include additional, driver-specific state data at
* the end of the structure.
*
* pmstate - Identifies the new PM state
@@ -2773,7 +2661,7 @@ static void up_pm_notify(struct pm_callback_s *cb, int domain,
* Input Parameters:
*
* cb - Returned to the driver. The driver version of the callback
- * structure may include additional, driver-specific state data at
+ * strucure may include additional, driver-specific state data at
* the end of the structure.
*
* pmstate - Identifies the new PM state
@@ -2791,6 +2679,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