You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by GitBox <gi...@apache.org> on 2022/07/15 07:03:55 UTC

[GitHub] [incubator-nuttx] pkarashchenko commented on a diff in pull request #6614: samv7: add support for RX DMA and RS-485 mode to serial driver

pkarashchenko commented on code in PR #6614:
URL: https://github.com/apache/incubator-nuttx/pull/6614#discussion_r921840825


##########
arch/arm/src/samv7/Kconfig:
##########
@@ -1068,6 +1107,32 @@ config SAMV7_SDRAMHEAP
 
 endmenu # SDRAM Configuration
 
+menu "Serial Driver Configuration"
+	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
+
+config SAMV7_SERIAL_RXDMA_BUFFER
+	int "Rx DMA buffer size"
+	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
+	default 128
+	range 32 4096
+	---help---
+		The DMA buffer size when using RX DMA to emulate a FIFO.
+
+config SAMV7_SERIAL_DMA_TIMEOUT
+	int "Rx DMA timeout"
+	default 3750
+	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
+	range 0 131071

Review Comment:
   ```suggestion
   	default 3750
   	range 0 131071
   	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -318,16 +386,38 @@
 
 struct sam_dev_s
 {
+  struct uart_dev_s dev;        /* Generic UART device */
   const uint32_t usartbase;     /* Base address of USART registers */
   uint32_t baud;                /* Configured baud */
   uint32_t sr;                  /* Saved status bits */
   uint8_t  irq;                 /* IRQ associated with this USART */
+  uint8_t  pid;                 /* Peripheral PID */
   uint8_t  parity;              /* 0=none, 1=odd, 2=even */
   uint8_t  bits;                /* Number of bits (5-9) */
   bool     stopbits2;           /* true: Configure with 2 stop bits instead of 1 */
 #if defined(CONFIG_SERIAL_IFLOWCONTROL) || defined(CONFIG_SERIAL_OFLOWCONTROL)
   bool     flowc;               /* input flow control (RTS) enabled */
 #endif
+
+  bool     has_rxdma;           /* True if RX DMA is enabled */
+  bool     has_rs485;           /* True if RS-485 mode is enabled */
+
+#ifdef SERIAL_HAVE_RS485
+  uint32_t rs485_dir_gpio;      /* RS-485 RTS pin */
+#endif
+  /* RX DMA state */
+
+#ifdef SERIAL_HAVE_RXDMA
+  const unsigned int rxdma_channel; /* DMA channel assigned */
+  DMA_HANDLE         rxdma;         /* currently-open receive DMA stream */
+  bool               rxenable;      /* DMA-based reception en/disable */
+  bool               odd;           /* True if odd buffer is used */
+  uint8_t            buf_idx;       /* 0 or 1, points to the correct buffer */
+  uint32_t           nextcache;     /* Next byte in data cache to be invalidated */
+  uint32_t           rxdmanext;     /* Next byte in the DMA buffer to be read */
+  uint32_t    *const rxbuf[2];      /* Receive DMA buffer */

Review Comment:
   ```suggestion
     uint32_t * const   rxbuf[2];      /* Receive DMA buffer */
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -396,14 +524,29 @@ static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE];
 #if defined(CONFIG_SAMV7_USART0) && defined(CONFIG_USART0_SERIALDRIVER)
 static char g_usart0rxbuffer[CONFIG_USART0_RXBUFSIZE];
 static char g_usart0txbuffer[CONFIG_USART0_TXBUFSIZE];
+# ifdef CONFIG_USART0_RXDMA
+static uint32_t g_usart0rxbuf[2][RXDMA_BUFFER_SIZE] \
+aligned_data(ARMV7M_DCACHE_LINESIZE);
+static struct chnext_view1_s g_usart0rxdesc[2];
+# endif
 #endif
 #if defined(CONFIG_SAMV7_USART1) && defined(CONFIG_USART1_SERIALDRIVER)
 static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE];
 static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE];
+# ifdef CONFIG_USART1_RXDMA
+static uint32_t g_usart1rxbuf[2][RXDMA_BUFFER_SIZE] \
+aligned_data(ARMV7M_DCACHE_LINESIZE);

Review Comment:
   ```suggestion
   static uint32_t g_usart1rxbuf[2][RXDMA_BUFFER_SIZE]
   aligned_data(ARMV7M_DCACHE_LINESIZE);
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -474,9 +623,12 @@ static struct sam_dev_s g_uart2priv =
   .usartbase      = SAM_UART2_BASE,
   .baud           = CONFIG_UART2_BAUD,
   .irq            = SAM_IRQ_UART2,
+  .pid            = SAM_PID_UART2,
   .parity         = CONFIG_UART2_PARITY,
   .bits           = CONFIG_UART2_BITS,
   .stopbits2      = CONFIG_UART2_2STOP,
+  .has_rxdma      = false,
+  .has_rs485      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -617,7 +824,12 @@ static uart_dev_t g_usart1port =
     .size   = CONFIG_USART1_TXBUFSIZE,
     .buffer = g_usart1txbuffer,
   },
+  .isconsole = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -650,7 +884,12 @@ static uart_dev_t g_usart2port =
       .size   = CONFIG_USART2_TXBUFSIZE,
       .buffer = g_usart2txbuffer,
     },
-  .ops        = &g_uart_ops,
+  .isconsole = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -1344,11 +1801,139 @@ static void sam_rxint(struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
+#ifdef SERIAL_HAVE_NODMA_OPS
 static bool sam_rxavailable(struct uart_dev_s *dev)
 {
   struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
   return ((sam_serialin(priv, SAM_UART_SR_OFFSET) & UART_INT_RXRDY) != 0);
 }
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_receive
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to receive one
+ *   character from the USART.  Error bits associated with the
+ *   receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int c = 0;
+
+  *status  = priv->sr;
+  priv->sr = 0;
+
+  /* Read character from the RX FIFO */
+
+  c = priv->rxbuf[priv->buf_idx][priv->rxdmanext] & UART_RHR_RXCHR_MASK;
+  priv->rxdmanext++;
+
+  if ((priv->rxdmanext) == RXDMA_BUFFER_SIZE)
+    {
+      priv->rxdmanext = 0;
+      priv->nextcache = 0;
+      priv->odd = !priv->odd;
+      priv->buf_idx = 1 & ~(priv->buf_idx);

Review Comment:
   ```suggestion
         priv->buf_idx = 1 & ~priv->buf_idx;
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -1344,11 +1801,139 @@ static void sam_rxint(struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
+#ifdef SERIAL_HAVE_NODMA_OPS
 static bool sam_rxavailable(struct uart_dev_s *dev)
 {
   struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
   return ((sam_serialin(priv, SAM_UART_SR_OFFSET) & UART_INT_RXRDY) != 0);
 }
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_receive
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to receive one
+ *   character from the USART.  Error bits associated with the
+ *   receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int c = 0;
+
+  *status  = priv->sr;
+  priv->sr = 0;
+
+  /* Read character from the RX FIFO */
+
+  c = priv->rxbuf[priv->buf_idx][priv->rxdmanext] & UART_RHR_RXCHR_MASK;
+  priv->rxdmanext++;
+
+  if ((priv->rxdmanext) == RXDMA_BUFFER_SIZE)
+    {
+      priv->rxdmanext = 0;
+      priv->nextcache = 0;
+      priv->odd = !priv->odd;
+      priv->buf_idx = 1 & ~(priv->buf_idx);
+    }
+
+  return c;
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static void sam_dma_rxint(struct uart_dev_s *dev, bool enable)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+
+  /* En/disable DMA reception.
+   *
+   * Note that it is not safe to check for available bytes and immediately
+   * pass them to uart_recvchars as that could potentially recurse back
+   * to us again.  Instead, bytes must wait until the next sam_dma_poll or
+   * DMA event.
+   */
+
+  if (priv->rxenable != enable)
+    {
+      priv->rxenable = enable;
+
+      if (enable)
+        {
+          sam_serialout(priv, SAM_UART_IER_OFFSET, UART_INT_TIMEOUT);
+        }
+      else
+        {
+          sam_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_TIMEOUT);
+        }
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_rxavailable
+ *
+ * Description:
+ *   Return true if there are some data in the buffer we can read. Also takes
+ *   care of invalidating data cache.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static bool sam_dma_rxavailable(struct uart_dev_s *dev)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  uint32_t nextrx;
+  bool ret;
+
+  ret = false;
+
+  /* Get the current DMA pointer */
+
+  nextrx = sam_dma_nextrx(priv);
+
+  /* Compare our receive pointer to the current DMA pointer, if they
+   * do match, then there are bytes to be received.
+   */
+
+  if ((nextrx != priv->rxdmanext) && priv->rxenable)
+    {
+      /* Invalidate data cache if necessary. This basically ensures
+       * we invalidate only that part of cache we need to.
+       */
+
+      if (priv->nextcache < nextrx)
+        {
+          up_invalidate_dcache((uintptr_t)priv->rxbuf[priv->buf_idx] \

Review Comment:
   ```suggestion
             up_invalidate_dcache((uintptr_t)priv->rxbuf[priv->buf_idx]
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -396,14 +524,29 @@ static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE];
 #if defined(CONFIG_SAMV7_USART0) && defined(CONFIG_USART0_SERIALDRIVER)
 static char g_usart0rxbuffer[CONFIG_USART0_RXBUFSIZE];
 static char g_usart0txbuffer[CONFIG_USART0_TXBUFSIZE];
+# ifdef CONFIG_USART0_RXDMA
+static uint32_t g_usart0rxbuf[2][RXDMA_BUFFER_SIZE] \
+aligned_data(ARMV7M_DCACHE_LINESIZE);
+static struct chnext_view1_s g_usart0rxdesc[2];
+# endif
 #endif
 #if defined(CONFIG_SAMV7_USART1) && defined(CONFIG_USART1_SERIALDRIVER)
 static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE];
 static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE];
+# ifdef CONFIG_USART1_RXDMA
+static uint32_t g_usart1rxbuf[2][RXDMA_BUFFER_SIZE] \
+aligned_data(ARMV7M_DCACHE_LINESIZE);
+static struct chnext_view1_s g_usart1rxdesc[2];
+# endif
 #endif
 #if defined(CONFIG_SAMV7_USART2) && defined(CONFIG_USART2_SERIALDRIVER)
 static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE];
 static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE];
+# ifdef CONFIG_USART2_RXDMA
+static uint32_t g_usart2rxbuf[2][RXDMA_BUFFER_SIZE] \
+aligned_data(ARMV7M_DCACHE_LINESIZE);

Review Comment:
   ```suggestion
   static uint32_t g_usart2rxbuf[2][RXDMA_BUFFER_SIZE]
   aligned_data(ARMV7M_DCACHE_LINESIZE);
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -396,14 +524,29 @@ static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE];
 #if defined(CONFIG_SAMV7_USART0) && defined(CONFIG_USART0_SERIALDRIVER)
 static char g_usart0rxbuffer[CONFIG_USART0_RXBUFSIZE];
 static char g_usart0txbuffer[CONFIG_USART0_TXBUFSIZE];
+# ifdef CONFIG_USART0_RXDMA
+static uint32_t g_usart0rxbuf[2][RXDMA_BUFFER_SIZE] \
+aligned_data(ARMV7M_DCACHE_LINESIZE);

Review Comment:
   ```suggestion
   static uint32_t g_usart0rxbuf[2][RXDMA_BUFFER_SIZE]
   aligned_data(ARMV7M_DCACHE_LINESIZE);
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -46,14 +46,82 @@
 
 #include "arm_internal.h"
 #include "sam_config.h"
+
+#include "hardware/sam_pinmap.h"
 #include "hardware/sam_uart.h"
+#include "hardware/sam_xdmac.h"
+#include "sam_xdmac.h"
+#include "sam_gpio.h"
+#include "sam_serial.h"
 
 /****************************************************************************
  * Pre-processor Definitions
  ****************************************************************************/
 
 #ifdef USE_SERIALDRIVER
 
+/* DMA Configuration */
+
+#if defined(CONFIG_USART0_RXDMA) || defined(CONFIG_USART1_RXDMA) || \
+    defined(CONFIG_USART2_RXDMA)
+# define SERIAL_HAVE_RXDMA
+#else
+# undef SERIAL_HAVE_RXDMA
+#endif
+
+#if defined(CONFIG_UART0_RXDMA) || defined(CONFIG_UART1_RXDMA) || \
+    defined(CONFIG_UART2_RXDMA) || defined(CONFIG_UART3_RXDMA) || \
+    defined(CONFIG_UART4_RXDMA)
+# warning RX DMA is currently supported only for USART driver.
+#endif
+
+#if defined(SERIAL_HAVE_RXDMA) && !defined(CONFIG_SAMV7_XDMAC)
+# error SERIAL DMA requires CONFIG_SAMV7_XDMAC to be selected
+#endif
+
+#ifdef SERIAL_HAVE_CONSOLE_RXDMA
+# error RX DMA for serial console is currently not supported.
+#endif
+
+#if defined(CONFIG_UART0_TXDMA) || defined(CONFIG_UART1_TXDMA) || \
+    defined(CONFIG_UART2_TXDMA) || defined(CONFIG_UART3_TXDMA) || \
+    defined(CONFIG_UART4_TXDMA) || defined(CONFIG_USART0_TXDMA) || \
+    defined(CONFIG_USART1_TXDMA) || defined(CONFIG_USART2_TXDMA)
+# warning TX DMA is currently not supported.
+#endif
+
+#ifndef CONFIG_SAMV7_SERIAL_DMA_TIMEOUT
+# define CONFIG_SAMV7_SERIAL_DMA_TIMEOUT 0
+#endif
+
+#ifdef SERIAL_HAVE_RXDMA
+
+# define DMA_RXFLAGS  (DMACH_FLAG_FIFOCFG_LARGEST | \
+     DMACH_FLAG_PERIPHH2SEL | DMACH_FLAG_PERIPHISPERIPH |  \
+     DMACH_FLAG_PERIPHWIDTH_32BITS | DMACH_FLAG_PERIPHCHUNKSIZE_1 | \
+     DMACH_FLAG_MEMPID_MAX | DMACH_FLAG_MEMAHB_AHB_IF0 | \
+     DMACH_FLAG_PERIPHAHB_AHB_IF1 | DMACH_FLAG_MEMWIDTH_32BITS | \
+     DMACH_FLAG_MEMINCREMENT | DMACH_FLAG_MEMCHUNKSIZE_1 | \
+     DMACH_FLAG_MEMBURST_1)
+
+/* The DMA buffer size when using RX DMA to emulate a FIFO.
+ *
+ * When streaming data, the generic serial layer will be called
+ * every time the FIFO receives half this number of bytes.
+ */
+
+#  ifndef CONFIG_SAMV7_SERIAL_RXDMA_BUFFER
+#    define CONFIG_SAMV7_SERIAL_RXDMA_BUFFER 128
+#  endif
+#define RXDMA_CACHE_SIZE  ARMV7M_DCACHE_LINESIZE/sizeof(uint32_t)
+#define RXDMA_MUTIPLE (4 > RXDMA_CACHE_SIZE) ? (4) : (RXDMA_CACHE_SIZE)
+#define RXDMA_MUTIPLE_MASK  (RXDMA_MUTIPLE - 1)
+#define RXDMA_BUFFER_SIZE ((CONFIG_SAMV7_SERIAL_RXDMA_BUFFER \
+                           + RXDMA_MUTIPLE_MASK) \
+                           & ~RXDMA_MUTIPLE_MASK)

Review Comment:
   ```suggestion
   #  define RXDMA_CACHE_SIZE    (ARMV7M_DCACHE_LINESIZE / sizeof(uint32_t))
   #  define RXDMA_MUTIPLE       (sizeof(uint32_t) > RXDMA_CACHE_SIZE ? \
                                  sizeof(uint32_t) : RXDMA_CACHE_SIZE)
   #  define RXDMA_MUTIPLE_MASK  (RXDMA_MUTIPLE - 1)
   #  define RXDMA_BUFFER_SIZE   ((CONFIG_SAMV7_SERIAL_RXDMA_BUFFER \
                                  + RXDMA_MUTIPLE_MASK) \
                                  & ~RXDMA_MUTIPLE_MASK)
   ```
   
   I'm not sure why `RXDMA_MUTIPLE` is needed as `ARMV7M_DCACHE_LINESIZE` is defined and condition `X > RXDMA_CACHE_SIZE` does not make sense to be evaluated at runtime. Is `#ifdef CONFIG_ARMV7M_DCACHE` missing around `#  define RXDMA_CACHE_SIZE`?



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -564,12 +722,34 @@ static struct sam_dev_s g_usart0priv =
   .usartbase      = SAM_USART0_BASE,
   .baud           = CONFIG_USART0_BAUD,
   .irq            = SAM_IRQ_USART0,
+  .pid            = SAM_PID_USART0,
   .parity         = CONFIG_USART0_PARITY,
   .bits           = CONFIG_USART0_BITS,
   .stopbits2      = CONFIG_USART0_2STOP,
 #if defined(CONFIG_USART0_OFLOWCONTROL) || defined(CONFIG_USART0_IFLOWCONTROL)
   .flowc          = true,
 #endif
+#ifdef CONFIG_USART0_RXDMA
+  .buf_idx        = 0,
+  .nextcache      = 0,
+  .rxbuf          =
+                    {
+                      g_usart0rxbuf[0], g_usart0rxbuf[1]
+                    },
+  .desc           =
+                    {
+                      &g_usart0rxdesc[0], &g_usart0rxdesc[1]
+                    },

Review Comment:
   ```suggestion
     .rxbuf          =
       {
         g_usart0rxbuf[0], g_usart0rxbuf[1]
       },
     .desc           =
       {
         &g_usart0rxdesc[0], &g_usart0rxdesc[1]
       },
   ```



##########
arch/arm/src/samv7/Kconfig:
##########
@@ -1068,6 +1107,32 @@ config SAMV7_SDRAMHEAP
 
 endmenu # SDRAM Configuration
 
+menu "Serial Driver Configuration"
+	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
+
+config SAMV7_SERIAL_RXDMA_BUFFER
+	int "Rx DMA buffer size"
+	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
+	default 128
+	range 32 4096

Review Comment:
   ```suggestion
   	default 128
   	range 32 4096
   	depends on SAMV7_HAVE_USART0 || SAMV7_HAVE_USART1 || SAMV7_HAVE_USART2
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -444,9 +590,12 @@ static struct sam_dev_s g_uart1priv =
   .usartbase      = SAM_UART1_BASE,
   .baud           = CONFIG_UART1_BAUD,
   .irq            = SAM_IRQ_UART1,
+  .pid            = SAM_PID_UART1,
   .parity         = CONFIG_UART1_PARITY,
   .bits           = CONFIG_UART1_BITS,
   .stopbits2      = CONFIG_UART1_2STOP,
+  .has_rxdma      = false,
+  .has_rs485      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -414,9 +557,12 @@ static struct sam_dev_s g_uart0priv =
   .usartbase      = SAM_UART0_BASE,
   .baud           = CONFIG_UART0_BAUD,
   .irq            = SAM_IRQ_UART0,
+  .pid            = SAM_PID_UART0,
   .parity         = CONFIG_UART0_PARITY,
   .bits           = CONFIG_UART0_BITS,
   .stopbits2      = CONFIG_UART0_2STOP,
+  .has_rxdma      = false,
+  .has_rs485      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -534,9 +689,12 @@ static struct sam_dev_s g_uart4priv =
   .usartbase      = SAM_UART4_BASE,
   .baud           = CONFIG_UART4_BAUD,
   .irq            = SAM_IRQ_UART4,
+  .pid            = SAM_PID_UART4,
   .parity         = CONFIG_UART4_PARITY,
   .bits           = CONFIG_UART4_BITS,
   .stopbits2      = CONFIG_UART4_2STOP,
+  .has_rxdma      = false,
+  .has_rs485      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -504,9 +656,12 @@ static struct sam_dev_s g_uart3priv =
   .usartbase      = SAM_UART3_BASE,
   .baud           = CONFIG_UART3_BAUD,
   .irq            = SAM_IRQ_UART3,
+  .pid            = SAM_PID_UART3,
   .parity         = CONFIG_UART3_PARITY,
   .bits           = CONFIG_UART3_BITS,
   .stopbits2      = CONFIG_UART3_2STOP,
+  .has_rxdma      = false,
+  .has_rs485      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -564,12 +722,34 @@ static struct sam_dev_s g_usart0priv =
   .usartbase      = SAM_USART0_BASE,
   .baud           = CONFIG_USART0_BAUD,
   .irq            = SAM_IRQ_USART0,
+  .pid            = SAM_PID_USART0,
   .parity         = CONFIG_USART0_PARITY,
   .bits           = CONFIG_USART0_BITS,
   .stopbits2      = CONFIG_USART0_2STOP,
 #if defined(CONFIG_USART0_OFLOWCONTROL) || defined(CONFIG_USART0_IFLOWCONTROL)
   .flowc          = true,
 #endif
+#ifdef CONFIG_USART0_RXDMA
+  .buf_idx        = 0,
+  .nextcache      = 0,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -597,12 +782,34 @@ static struct sam_dev_s g_usart1priv =
   .usartbase      = SAM_USART1_BASE,
   .baud           = CONFIG_USART1_BAUD,
   .irq            = SAM_IRQ_USART1,
+  .pid            = SAM_PID_USART1,
   .parity         = CONFIG_USART1_PARITY,
   .bits           = CONFIG_USART1_BITS,
   .stopbits2      = CONFIG_USART1_2STOP,
 #if defined(CONFIG_USART1_OFLOWCONTROL) || defined(CONFIG_USART1_IFLOWCONTROL)
   .flowc          = true,
 #endif
+#ifdef CONFIG_USART1_RXDMA
+  .buf_idx        = 0,
+  .nextcache      = 0,
+  .rxbuf          =
+                    {
+                      g_usart1rxbuf[0], g_usart1rxbuf[1]
+                    },
+  .desc           =
+                    {
+                      &g_usart1rxdesc[0], &g_usart1rxdesc[1]
+                    },
+  .has_rxdma      = true,
+#else
+  .has_rxdma      = false,
+#endif
+#ifdef CONFIG_SAMV7_USART1_RS485MODE
+  .has_rs485      = true,
+  .rs485_dir_gpio = GPIO_USART1_RTS,
+#else
+  .has_rs485      = false,
+#endif

Review Comment:
   ```suggestion
   #ifdef CONFIG_USART1_RXDMA
     .rxbuf          =
       {
         g_usart1rxbuf[0], g_usart1rxbuf[1]
       },
     .desc           =
       {
         &g_usart1rxdesc[0], &g_usart1rxdesc[1]
       },
     .has_rxdma      = true,
   #endif
   #ifdef CONFIG_SAMV7_USART1_RS485MODE
     .has_rs485      = true,
     .rs485_dir_gpio = GPIO_USART1_RTS,
   #endif
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -564,12 +722,34 @@ static struct sam_dev_s g_usart0priv =
   .usartbase      = SAM_USART0_BASE,
   .baud           = CONFIG_USART0_BAUD,
   .irq            = SAM_IRQ_USART0,
+  .pid            = SAM_PID_USART0,
   .parity         = CONFIG_USART0_PARITY,
   .bits           = CONFIG_USART0_BITS,
   .stopbits2      = CONFIG_USART0_2STOP,
 #if defined(CONFIG_USART0_OFLOWCONTROL) || defined(CONFIG_USART0_IFLOWCONTROL)
   .flowc          = true,
 #endif
+#ifdef CONFIG_USART0_RXDMA
+  .buf_idx        = 0,
+  .nextcache      = 0,
+  .rxbuf          =
+                    {
+                      g_usart0rxbuf[0], g_usart0rxbuf[1]
+                    },
+  .desc           =
+                    {
+                      &g_usart0rxdesc[0], &g_usart0rxdesc[1]
+                    },
+  .has_rxdma      = true,
+#else
+  .has_rxdma      = false,
+#endif
+#ifdef CONFIG_SAMV7_USART0_RS485MODE
+  .has_rs485      = true,
+  .rs485_dir_gpio = GPIO_USART0_RTS,
+#else
+  .has_rs485      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -584,7 +764,12 @@ static uart_dev_t g_usart0port =
     .size   = CONFIG_USART0_TXBUFSIZE,
     .buffer = g_usart0txbuffer,
   },
+  .isconsole = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -564,12 +722,34 @@ static struct sam_dev_s g_usart0priv =
   .usartbase      = SAM_USART0_BASE,
   .baud           = CONFIG_USART0_BAUD,
   .irq            = SAM_IRQ_USART0,
+  .pid            = SAM_PID_USART0,
   .parity         = CONFIG_USART0_PARITY,
   .bits           = CONFIG_USART0_BITS,
   .stopbits2      = CONFIG_USART0_2STOP,
 #if defined(CONFIG_USART0_OFLOWCONTROL) || defined(CONFIG_USART0_IFLOWCONTROL)
   .flowc          = true,
 #endif
+#ifdef CONFIG_USART0_RXDMA
+  .buf_idx        = 0,
+  .nextcache      = 0,
+  .rxbuf          =
+                    {
+                      g_usart0rxbuf[0], g_usart0rxbuf[1]
+                    },
+  .desc           =
+                    {
+                      &g_usart0rxdesc[0], &g_usart0rxdesc[1]
+                    },
+  .has_rxdma      = true,
+#else
+  .has_rxdma      = false,

Review Comment:
   ```suggestion
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -879,10 +1168,109 @@ static int sam_setup(struct uart_dev_s *dev)
   /* Enable receiver & transmitter */
 
   sam_serialout(priv, SAM_UART_CR_OFFSET, (UART_CR_RXEN | UART_CR_TXEN));
+
+#ifdef SERIAL_HAVE_RS485
+  if (priv->has_rs485)
+    {
+      sam_configgpio(priv->rs485_dir_gpio);
+
+      regval = sam_serialin(priv, SAM_UART_MR_OFFSET);
+      regval |= UART_MR_MODE_RS485;
+      sam_serialout(priv, SAM_UART_MR_OFFSET, regval);
+    }
+#endif
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: sam_dma_setup
+ *
+ * Description:
+ *   Configure the UART (USART) baud, bits, parity, etc. This method is
+ *   called the first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_setup(struct uart_dev_s *dev)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int result;
+
+  /* Do the basic UART setup first, unless we are the console */
+
+  if (!dev->isconsole)
+    {
+      result = sam_setup(dev);
+      if (result != OK)
+        {
+          return result;
+        }
+    }
+
+#ifdef SERIAL_HAVE_RXDMA
+  /* Acquire the DMA channel. This should always succeed. */
+
+  if (priv->has_rxdma)
+    {
+      /* Do this only if this peripheral has RX DMA. This might not be
+       * neccessary at current state of the driver as sam_dma_setup()
+       * cannot be called if USARTn does not have RX DMA but it will be
+       * needed when TX DMA is implemented. The sam_dma_setup() can be
+       * called even when TX DMA is defined and RX DMA is not.
+       */
+
+      priv->rxdma = sam_dmachannel(0, DMA_RXFLAGS | \

Review Comment:
   ```suggestion
         priv->rxdma = sam_dmachannel(0, DMA_RXFLAGS |
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -879,10 +1168,109 @@ static int sam_setup(struct uart_dev_s *dev)
   /* Enable receiver & transmitter */
 
   sam_serialout(priv, SAM_UART_CR_OFFSET, (UART_CR_RXEN | UART_CR_TXEN));
+
+#ifdef SERIAL_HAVE_RS485
+  if (priv->has_rs485)
+    {
+      sam_configgpio(priv->rs485_dir_gpio);
+
+      regval = sam_serialin(priv, SAM_UART_MR_OFFSET);
+      regval |= UART_MR_MODE_RS485;
+      sam_serialout(priv, SAM_UART_MR_OFFSET, regval);
+    }
+#endif
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: sam_dma_setup
+ *
+ * Description:
+ *   Configure the UART (USART) baud, bits, parity, etc. This method is
+ *   called the first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_setup(struct uart_dev_s *dev)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int result;
+
+  /* Do the basic UART setup first, unless we are the console */
+
+  if (!dev->isconsole)
+    {
+      result = sam_setup(dev);
+      if (result != OK)
+        {
+          return result;
+        }
+    }
+
+#ifdef SERIAL_HAVE_RXDMA
+  /* Acquire the DMA channel. This should always succeed. */
+
+  if (priv->has_rxdma)
+    {
+      /* Do this only if this peripheral has RX DMA. This might not be
+       * neccessary at current state of the driver as sam_dma_setup()
+       * cannot be called if USARTn does not have RX DMA but it will be
+       * needed when TX DMA is implemented. The sam_dma_setup() can be
+       * called even when TX DMA is defined and RX DMA is not.
+       */
+
+      priv->rxdma = sam_dmachannel(0, DMA_RXFLAGS | \
+                                      DMACH_FLAG_PERIPHPID(priv->pid));
+
+      /* Configure for circular DMA reception into the RX fifo */
+
+      uint32_t paddr = priv->usartbase + SAM_UART_RHR_OFFSET;
+      uint32_t maddr[] = {
+                            (uintptr_t)priv->rxbuf[0],
+                            (uintptr_t)priv->rxbuf[1]
+                         };
+
+      /* sam_dmarxsetup() needs number of bytes to transfer. Since 1
+       * transfer is 32 bits = 4 bytes we need to multiply
+       * RXDMA_BUFFER_SIZE by 4 to get the number of characters as
+       * defined in RXDMA_BUFFER_SIZE.
+       */
+
+      size_t buflen = RXDMA_BUFFER_SIZE << 2;
+
+      sam_dmarxsetup_circular(priv->rxdma, priv->desc, (uintptr_t **)maddr,

Review Comment:
   ```suggestion
         sam_dmarxsetup_circular(priv->rxdma, priv->desc, maddr,
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -715,6 +954,56 @@ static void sam_disableallints(struct sam_dev_s *priv, uint32_t *imr)
   leave_critical_section(flags);
 }
 
+/****************************************************************************
+ * Name: sam_dma_nextrx
+ *
+ * Description:
+ *   Returns the index into the RX FIFO where the DMA will place the next
+ *   byte that it receives.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_nextrx(struct sam_dev_s *priv)
+{
+  uint32_t cda;
+  uint32_t ret;
+
+  /* Get the DMA destination address */
+
+  cda = sam_destaddr(priv->rxdma);
+
+  if (!priv->odd)
+    {
+      ret = (cda - (uint32_t)priv->rxbuf[0]) / sizeof(uint32_t);
+      if (cda >= ((uint32_t)priv->rxbuf[0] + (RXDMA_BUFFER_SIZE << 2)))

Review Comment:
   ```suggestion
         ret = (cda - priv->rxbuf[0]) / sizeof(uint32_t);
         if (cda >= (priv->rxbuf[0] + (RXDMA_BUFFER_SIZE << 2)))
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -650,7 +884,12 @@ static uart_dev_t g_usart2port =
       .size   = CONFIG_USART2_TXBUFSIZE,
       .buffer = g_usart2txbuffer,
     },
-  .ops        = &g_uart_ops,
+  .isconsole = false,
+#ifdef CONFIG_USART2_RXDMA
+  .ops       = &g_uart_rxdma_ops,
+#else
+  .ops       = &g_uart_ops,

Review Comment:
   ```suggestion
     .ops        = &g_uart_rxdma_ops,
   #else
     .ops        = &g_uart_ops,
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -879,10 +1168,109 @@ static int sam_setup(struct uart_dev_s *dev)
   /* Enable receiver & transmitter */
 
   sam_serialout(priv, SAM_UART_CR_OFFSET, (UART_CR_RXEN | UART_CR_TXEN));
+
+#ifdef SERIAL_HAVE_RS485
+  if (priv->has_rs485)
+    {
+      sam_configgpio(priv->rs485_dir_gpio);
+
+      regval = sam_serialin(priv, SAM_UART_MR_OFFSET);
+      regval |= UART_MR_MODE_RS485;
+      sam_serialout(priv, SAM_UART_MR_OFFSET, regval);
+    }
+#endif
+#endif
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: sam_dma_setup
+ *
+ * Description:
+ *   Configure the UART (USART) baud, bits, parity, etc. This method is
+ *   called the first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_setup(struct uart_dev_s *dev)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int result;
+
+  /* Do the basic UART setup first, unless we are the console */
+
+  if (!dev->isconsole)
+    {
+      result = sam_setup(dev);
+      if (result != OK)
+        {
+          return result;
+        }
+    }
+
+#ifdef SERIAL_HAVE_RXDMA
+  /* Acquire the DMA channel. This should always succeed. */
+
+  if (priv->has_rxdma)
+    {
+      /* Do this only if this peripheral has RX DMA. This might not be
+       * neccessary at current state of the driver as sam_dma_setup()
+       * cannot be called if USARTn does not have RX DMA but it will be
+       * needed when TX DMA is implemented. The sam_dma_setup() can be
+       * called even when TX DMA is defined and RX DMA is not.
+       */
+
+      priv->rxdma = sam_dmachannel(0, DMA_RXFLAGS | \
+                                      DMACH_FLAG_PERIPHPID(priv->pid));
+
+      /* Configure for circular DMA reception into the RX fifo */
+
+      uint32_t paddr = priv->usartbase + SAM_UART_RHR_OFFSET;
+      uint32_t maddr[] = {
+                            (uintptr_t)priv->rxbuf[0],
+                            (uintptr_t)priv->rxbuf[1]
+                         };

Review Comment:
   ```suggestion
         uint32_t maddr[] =
           {
             priv->rxbuf[0],
             priv->rxbuf[1]
           };
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -630,12 +842,34 @@ static struct sam_dev_s g_usart2priv =
   .usartbase      = SAM_USART2_BASE,
   .baud           = CONFIG_USART2_BAUD,
   .irq            = SAM_IRQ_USART2,
+  .pid            = SAM_PID_USART2,
   .parity         = CONFIG_USART2_PARITY,
   .bits           = CONFIG_USART2_BITS,
   .stopbits2      = CONFIG_USART2_2STOP,
 #if defined(CONFIG_USART2_OFLOWCONTROL) || defined(CONFIG_USART2_IFLOWCONTROL)
   .flowc          = true,
 #endif
+#ifdef CONFIG_USART2_RXDMA
+  .buf_idx        = 0,
+  .nextcache      = 0,
+  .rxbuf          =
+                    {
+                      g_usart2rxbuf[0], g_usart2rxbuf[1]
+                    },
+  .desc           =
+                    {
+                      &g_usart2rxdesc[0], &g_usart2rxdesc[1]
+                    },
+  .has_rxdma      = true,
+#else
+  .has_rxdma      = false,
+#endif
+#ifdef CONFIG_SAMV7_USART2_RS485MODE
+  .has_rs485      = true,
+  .rs485_dir_gpio = GPIO_USART2_RTS,
+#else
+  .has_rs485      = false,
+#endif

Review Comment:
   ```suggestion
   #ifdef CONFIG_USART2_RXDMA
     .rxbuf          =
       {
         g_usart2rxbuf[0], g_usart2rxbuf[1]
       },
     .desc           =
       {
         &g_usart2rxdesc[0], &g_usart2rxdesc[1]
       },
     .has_rxdma      = true,
   #endif
   #ifdef CONFIG_SAMV7_USART2_RS485MODE
     .has_rs485      = true,
     .rs485_dir_gpio = GPIO_USART2_RTS,
   #endif
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -896,18 +1284,65 @@ static int sam_setup(struct uart_dev_s *dev)
 static void sam_shutdown(struct uart_dev_s *dev)
 {
   struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  uint32_t regval;
 
   /* Reset and disable receiver and transmitter */
 
   sam_serialout(priv, SAM_UART_CR_OFFSET,
-                (UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS |
+                (UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | \
                  UART_CR_TXDIS));
 
+  /* Set mode back to normal */
+
+  regval = sam_serialin(priv, SAM_UART_MR_OFFSET);
+  regval &= ~(UART_MR_MODE_MASK);

Review Comment:
   ```suggestion
     regval &= ~UART_MR_MODE_MASK;
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -715,6 +954,56 @@ static void sam_disableallints(struct sam_dev_s *priv, uint32_t *imr)
   leave_critical_section(flags);
 }
 
+/****************************************************************************
+ * Name: sam_dma_nextrx
+ *
+ * Description:
+ *   Returns the index into the RX FIFO where the DMA will place the next
+ *   byte that it receives.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_nextrx(struct sam_dev_s *priv)
+{
+  uint32_t cda;
+  uint32_t ret;
+
+  /* Get the DMA destination address */
+
+  cda = sam_destaddr(priv->rxdma);
+
+  if (!priv->odd)
+    {
+      ret = (cda - (uint32_t)priv->rxbuf[0]) / sizeof(uint32_t);
+      if (cda >= ((uint32_t)priv->rxbuf[0] + (RXDMA_BUFFER_SIZE << 2)))
+        {
+          /* We are already in another buffer so we need to read the
+           * whole RXDMA_BUFFER_SIZE.
+           */
+
+          ret = RXDMA_BUFFER_SIZE;
+        }
+
+      return ret;
+    }
+  else
+    {
+      ret = (cda - (uint32_t)priv->rxbuf[1]) / sizeof(uint32_t);
+      if (cda < (uint32_t)priv->rxbuf[1])

Review Comment:
   ```suggestion
         ret = (cda - priv->rxbuf[1]) / sizeof(uint32_t);
         if (cda < priv->rxbuf[1])
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -896,18 +1284,65 @@ static int sam_setup(struct uart_dev_s *dev)
 static void sam_shutdown(struct uart_dev_s *dev)
 {
   struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  uint32_t regval;
 
   /* Reset and disable receiver and transmitter */
 
   sam_serialout(priv, SAM_UART_CR_OFFSET,
-                (UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS |
+                (UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS | \

Review Comment:
   ```suggestion
                   (UART_CR_RSTRX | UART_CR_RSTTX | UART_CR_RXDIS |
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -1344,11 +1801,139 @@ static void sam_rxint(struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
+#ifdef SERIAL_HAVE_NODMA_OPS
 static bool sam_rxavailable(struct uart_dev_s *dev)
 {
   struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
   return ((sam_serialin(priv, SAM_UART_SR_OFFSET) & UART_INT_RXRDY) != 0);
 }
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_receive
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to receive one
+ *   character from the USART.  Error bits associated with the
+ *   receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int c = 0;
+
+  *status  = priv->sr;
+  priv->sr = 0;
+
+  /* Read character from the RX FIFO */
+
+  c = priv->rxbuf[priv->buf_idx][priv->rxdmanext] & UART_RHR_RXCHR_MASK;
+  priv->rxdmanext++;
+
+  if ((priv->rxdmanext) == RXDMA_BUFFER_SIZE)

Review Comment:
   ```suggestion
     if (priv->rxdmanext == RXDMA_BUFFER_SIZE)
   ```



##########
arch/arm/src/samv7/sam_xdmac.c:
##########
@@ -1921,6 +1936,130 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
   return ret;
 }
 
+/****************************************************************************
+ * Name: sam_dmarxsetup_circular
+ *
+ * Description:
+ *   Configure DMA for receipt of two circular buffers for peripheral to
+ *   memory transfer. Function sam_dmastart_circular() needs to be called
+ *   to start the transfer. Only peripheral to memory transfer is currently
+ *   supported.
+ *
+ * Input Parameters:
+ *   handle - DMA handler
+ *   descr - array with DMA descriptors
+ *   maddr - array of memory addresses (i.e. destination addresses)
+ *   paddr - peripheral address (i.e. source address)
+ *   nbytes - number of bytes to transfer
+ *   ndescrs - number of descriptors (i.e. the lenght of descr array)
+ *
+ ****************************************************************************/
+
+int sam_dmarxsetup_circular(DMA_HANDLE handle,
+                            struct chnext_view1_s *descr[],
+                            uintptr_t *maddr[],

Review Comment:
   ```suggestion
                               uint32_t maddr[],
   ```



##########
arch/arm/src/samv7/sam_xdmac.c:
##########
@@ -1921,6 +1936,130 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
   return ret;
 }
 
+/****************************************************************************
+ * Name: sam_dmarxsetup_circular
+ *
+ * Description:
+ *   Configure DMA for receipt of two circular buffers for peripheral to
+ *   memory transfer. Function sam_dmastart_circular() needs to be called
+ *   to start the transfer. Only peripheral to memory transfer is currently
+ *   supported.
+ *
+ * Input Parameters:
+ *   handle - DMA handler
+ *   descr - array with DMA descriptors
+ *   maddr - array of memory addresses (i.e. destination addresses)
+ *   paddr - peripheral address (i.e. source address)
+ *   nbytes - number of bytes to transfer
+ *   ndescrs - number of descriptors (i.e. the lenght of descr array)
+ *
+ ****************************************************************************/
+
+int sam_dmarxsetup_circular(DMA_HANDLE handle,
+                            struct chnext_view1_s *descr[],
+                            uintptr_t *maddr[],
+                            uint32_t paddr,
+                            size_t nbytes,
+                            uint8_t ndescrs)
+{
+  struct sam_xdmach_s *xdmach = (struct sam_xdmach_s *)handle;
+  uint32_t cubc;
+  uint8_t nextdescr;
+  int i;
+
+  /* Set circular as true */
+
+  xdmach->circular = true;
+
+  xdmach->cc = sam_rxcc(xdmach);
+
+  /* Calculate the number of transfers for CUBC */
+
+  cubc  = sam_cubc(xdmach, nbytes);
+  cubc |= (CHNEXT_UBC_NDE | CHNEXT_UBC_NVIEW_1 | CHNEXT_UBC_NDEN | \

Review Comment:
   ```suggestion
     cubc |= (CHNEXT_UBC_NDE | CHNEXT_UBC_NVIEW_1 | CHNEXT_UBC_NDEN |
   ```



##########
arch/arm/src/samv7/sam_xdmac.c:
##########
@@ -1921,6 +1936,130 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
   return ret;
 }
 
+/****************************************************************************
+ * Name: sam_dmarxsetup_circular
+ *
+ * Description:
+ *   Configure DMA for receipt of two circular buffers for peripheral to
+ *   memory transfer. Function sam_dmastart_circular() needs to be called
+ *   to start the transfer. Only peripheral to memory transfer is currently
+ *   supported.
+ *
+ * Input Parameters:
+ *   handle - DMA handler
+ *   descr - array with DMA descriptors
+ *   maddr - array of memory addresses (i.e. destination addresses)
+ *   paddr - peripheral address (i.e. source address)
+ *   nbytes - number of bytes to transfer
+ *   ndescrs - number of descriptors (i.e. the lenght of descr array)
+ *
+ ****************************************************************************/
+
+int sam_dmarxsetup_circular(DMA_HANDLE handle,
+                            struct chnext_view1_s *descr[],
+                            uintptr_t *maddr[],
+                            uint32_t paddr,
+                            size_t nbytes,
+                            uint8_t ndescrs)
+{
+  struct sam_xdmach_s *xdmach = (struct sam_xdmach_s *)handle;
+  uint32_t cubc;
+  uint8_t nextdescr;
+  int i;
+
+  /* Set circular as true */
+
+  xdmach->circular = true;
+
+  xdmach->cc = sam_rxcc(xdmach);
+
+  /* Calculate the number of transfers for CUBC */
+
+  cubc  = sam_cubc(xdmach, nbytes);
+  cubc |= (CHNEXT_UBC_NDE | CHNEXT_UBC_NVIEW_1 | CHNEXT_UBC_NDEN | \
+           CHNEXT_UBC_NSEN);
+
+  nextdescr = 0;
+
+  for (i = ndescrs - 1; i >= 0; i--)
+    {
+      descr[i]->cnda  = (uint32_t)descr[nextdescr];   /* Next Descriptor Address */
+      descr[i]->cubc  = cubc;                         /* Channel Microblock Control Register */
+      descr[i]->csa   = paddr;                        /* Source address */
+      descr[i]->cda   = (uint32_t)maddr[i];           /* Destination address */

Review Comment:
   ```suggestion
         descr[i]->cda   = maddr[i];                     /* Destination address */
   ```



##########
arch/arm/src/samv7/sam_serial.c:
##########
@@ -1344,11 +1801,139 @@ static void sam_rxint(struct uart_dev_s *dev, bool enable)
  *
  ****************************************************************************/
 
+#ifdef SERIAL_HAVE_NODMA_OPS
 static bool sam_rxavailable(struct uart_dev_s *dev)
 {
   struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
   return ((sam_serialin(priv, SAM_UART_SR_OFFSET) & UART_INT_RXRDY) != 0);
 }
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_receive
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to receive one
+ *   character from the USART.  Error bits associated with the
+ *   receipt are provided in the return 'status'.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static int sam_dma_receive(struct uart_dev_s *dev, unsigned int *status)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  int c = 0;
+
+  *status  = priv->sr;
+  priv->sr = 0;
+
+  /* Read character from the RX FIFO */
+
+  c = priv->rxbuf[priv->buf_idx][priv->rxdmanext] & UART_RHR_RXCHR_MASK;
+  priv->rxdmanext++;
+
+  if ((priv->rxdmanext) == RXDMA_BUFFER_SIZE)
+    {
+      priv->rxdmanext = 0;
+      priv->nextcache = 0;
+      priv->odd = !priv->odd;
+      priv->buf_idx = 1 & ~(priv->buf_idx);
+    }
+
+  return c;
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static void sam_dma_rxint(struct uart_dev_s *dev, bool enable)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+
+  /* En/disable DMA reception.
+   *
+   * Note that it is not safe to check for available bytes and immediately
+   * pass them to uart_recvchars as that could potentially recurse back
+   * to us again.  Instead, bytes must wait until the next sam_dma_poll or
+   * DMA event.
+   */
+
+  if (priv->rxenable != enable)
+    {
+      priv->rxenable = enable;
+
+      if (enable)
+        {
+          sam_serialout(priv, SAM_UART_IER_OFFSET, UART_INT_TIMEOUT);
+        }
+      else
+        {
+          sam_serialout(priv, SAM_UART_IDR_OFFSET, UART_INT_TIMEOUT);
+        }
+    }
+}
+#endif
+
+/****************************************************************************
+ * Name: sam_dma_rxavailable
+ *
+ * Description:
+ *   Return true if there are some data in the buffer we can read. Also takes
+ *   care of invalidating data cache.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static bool sam_dma_rxavailable(struct uart_dev_s *dev)
+{
+  struct sam_dev_s *priv = (struct sam_dev_s *)dev->priv;
+  uint32_t nextrx;
+  bool ret;
+
+  ret = false;
+
+  /* Get the current DMA pointer */
+
+  nextrx = sam_dma_nextrx(priv);
+
+  /* Compare our receive pointer to the current DMA pointer, if they
+   * do match, then there are bytes to be received.
+   */
+
+  if ((nextrx != priv->rxdmanext) && priv->rxenable)
+    {
+      /* Invalidate data cache if necessary. This basically ensures
+       * we invalidate only that part of cache we need to.
+       */
+
+      if (priv->nextcache < nextrx)
+        {
+          up_invalidate_dcache((uintptr_t)priv->rxbuf[priv->buf_idx] \
+                                + (priv->nextcache << 2),
+                               (uintptr_t)priv->rxbuf[priv->buf_idx] \

Review Comment:
   ```suggestion
                                  (uintptr_t)priv->rxbuf[priv->buf_idx]
   ```



##########
arch/arm/src/samv7/sam_xdmac.c:
##########
@@ -1921,6 +1936,130 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
   return ret;
 }
 
+/****************************************************************************
+ * Name: sam_dmarxsetup_circular
+ *
+ * Description:
+ *   Configure DMA for receipt of two circular buffers for peripheral to
+ *   memory transfer. Function sam_dmastart_circular() needs to be called
+ *   to start the transfer. Only peripheral to memory transfer is currently
+ *   supported.
+ *
+ * Input Parameters:
+ *   handle - DMA handler
+ *   descr - array with DMA descriptors
+ *   maddr - array of memory addresses (i.e. destination addresses)
+ *   paddr - peripheral address (i.e. source address)
+ *   nbytes - number of bytes to transfer
+ *   ndescrs - number of descriptors (i.e. the lenght of descr array)
+ *
+ ****************************************************************************/
+
+int sam_dmarxsetup_circular(DMA_HANDLE handle,
+                            struct chnext_view1_s *descr[],
+                            uintptr_t *maddr[],
+                            uint32_t paddr,
+                            size_t nbytes,
+                            uint8_t ndescrs)
+{
+  struct sam_xdmach_s *xdmach = (struct sam_xdmach_s *)handle;
+  uint32_t cubc;
+  uint8_t nextdescr;
+  int i;
+
+  /* Set circular as true */
+
+  xdmach->circular = true;
+
+  xdmach->cc = sam_rxcc(xdmach);
+
+  /* Calculate the number of transfers for CUBC */
+
+  cubc  = sam_cubc(xdmach, nbytes);
+  cubc |= (CHNEXT_UBC_NDE | CHNEXT_UBC_NVIEW_1 | CHNEXT_UBC_NDEN | \
+           CHNEXT_UBC_NSEN);
+
+  nextdescr = 0;
+
+  for (i = ndescrs - 1; i >= 0; i--)
+    {
+      descr[i]->cnda  = (uint32_t)descr[nextdescr];   /* Next Descriptor Address */
+      descr[i]->cubc  = cubc;                         /* Channel Microblock Control Register */
+      descr[i]->csa   = paddr;                        /* Source address */
+      descr[i]->cda   = (uint32_t)maddr[i];           /* Destination address */
+
+      /* Clean data cache */
+
+      up_clean_dcache((uintptr_t)descr[i],
+                      (uintptr_t)descr[i] + \

Review Comment:
   ```suggestion
                         (uintptr_t)descr[i] +
   ```



##########
arch/arm/src/samv7/sam_xdmac.h:
##########
@@ -304,6 +320,43 @@ int sam_dmatxsetup(DMA_HANDLE handle, uint32_t paddr,
 int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr,
                    uint32_t maddr, size_t nbytes);
 
+/****************************************************************************
+ * Name: sam_dmarxsetup_circular
+ *
+ * Description:
+ *   Configure DMA for receipt of two circular buffers for peripheral to
+ *   memory transfer. Function sam_dmastart_circular() needs to be called
+ *   to start the transfer. Only peripheral to memory transfer is currently
+ *   supported.
+ *
+ * Input Parameters:
+ *   handle - DMA handler
+ *   descr - array with DMA descriptors
+ *   maddr - array of memory addresses (i.e. destination addresses)
+ *   paddr - peripheral address (i.e. source address)
+ *   nbytes - number of bytes to transfer
+ *   ndescrs - number of descriptors (i.e. the lenght of descr array)
+ *
+ ****************************************************************************/
+
+int sam_dmarxsetup_circular(DMA_HANDLE handle,
+                            struct chnext_view1_s *descr[],
+                            uintptr_t *maddr[],

Review Comment:
   ```suggestion
                               uint32_t maddr[],
   ```



##########
arch/arm/src/samv7/sam_xdmac.c:
##########
@@ -1921,6 +1936,130 @@ int sam_dmarxsetup(DMA_HANDLE handle, uint32_t paddr, uint32_t maddr,
   return ret;
 }
 
+/****************************************************************************
+ * Name: sam_dmarxsetup_circular
+ *
+ * Description:
+ *   Configure DMA for receipt of two circular buffers for peripheral to
+ *   memory transfer. Function sam_dmastart_circular() needs to be called
+ *   to start the transfer. Only peripheral to memory transfer is currently
+ *   supported.
+ *
+ * Input Parameters:
+ *   handle - DMA handler
+ *   descr - array with DMA descriptors
+ *   maddr - array of memory addresses (i.e. destination addresses)
+ *   paddr - peripheral address (i.e. source address)
+ *   nbytes - number of bytes to transfer
+ *   ndescrs - number of descriptors (i.e. the lenght of descr array)
+ *
+ ****************************************************************************/
+
+int sam_dmarxsetup_circular(DMA_HANDLE handle,
+                            struct chnext_view1_s *descr[],
+                            uintptr_t *maddr[],
+                            uint32_t paddr,
+                            size_t nbytes,
+                            uint8_t ndescrs)
+{
+  struct sam_xdmach_s *xdmach = (struct sam_xdmach_s *)handle;
+  uint32_t cubc;
+  uint8_t nextdescr;
+  int i;
+
+  /* Set circular as true */
+
+  xdmach->circular = true;
+
+  xdmach->cc = sam_rxcc(xdmach);
+
+  /* Calculate the number of transfers for CUBC */
+
+  cubc  = sam_cubc(xdmach, nbytes);
+  cubc |= (CHNEXT_UBC_NDE | CHNEXT_UBC_NVIEW_1 | CHNEXT_UBC_NDEN | \
+           CHNEXT_UBC_NSEN);
+
+  nextdescr = 0;
+
+  for (i = ndescrs - 1; i >= 0; i--)
+    {
+      descr[i]->cnda  = (uint32_t)descr[nextdescr];   /* Next Descriptor Address */
+      descr[i]->cubc  = cubc;                         /* Channel Microblock Control Register */
+      descr[i]->csa   = paddr;                        /* Source address */
+      descr[i]->cda   = (uint32_t)maddr[i];           /* Destination address */
+
+      /* Clean data cache */
+
+      up_clean_dcache((uintptr_t)descr[i],
+                      (uintptr_t)descr[i] + \
+                       sizeof(struct chnext_view1_s));
+      up_clean_dcache((uintptr_t)maddr[i], (uintptr_t)(maddr + nbytes));
+      nextdescr = i;
+    }
+
+  /* Settup of llhead and lltail does not really matter in this case */
+
+  xdmach->llhead = descr[0];
+  xdmach->lltail = descr[0];
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: sam_dmastart_circular
+ *
+ * Description:
+ *   Start the DMA transfer with circular buffers.
+ *
+ ****************************************************************************/
+
+int sam_dmastart_circular(DMA_HANDLE handle, dma_callback_t callback,
+                          void *arg)
+{
+  struct sam_xdmach_s *xdmach = (struct sam_xdmach_s *)handle;
+  struct sam_xdmac_s *xdmac = sam_controller(xdmach);
+  struct chnext_view1_s *llhead = xdmach->llhead;
+  uintptr_t paddr;
+  uint32_t regval;
+
+  /* Save the callback info.  This will be invoked when the DMA
+   * completes
+   */
+
+  xdmach->callback = callback;
+  xdmach->arg      = arg;
+
+  /* Clear pending interrupts */
+
+  sam_getdmach(xdmach, SAM_XDMACH_CIS_OFFSET);
+
+  sam_putdmach(xdmach, xdmach->cc, SAM_XDMACH_CC_OFFSET);
+
+  /* Setup next descriptor */
+
+  regval = (XDMACH_CNDC_NDE | XDMACH_CNDC_NDVIEW_NDV1 | \

Review Comment:
   ```suggestion
     regval = (XDMACH_CNDC_NDE | XDMACH_CNDC_NDVIEW_NDV1 |
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscribe@nuttx.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org