diff --git a/nuttx-patches/serial_dma_hotfix.patch b/nuttx-patches/serial_dma_hotfix.patch new file mode 100644 index 0000000000..23a8c0e122 --- /dev/null +++ b/nuttx-patches/serial_dma_hotfix.patch @@ -0,0 +1,288 @@ +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