This is an automated email from the ASF dual-hosted git repository.

raiden00 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-nuttx.git

commit c801de4201f7be3004e85078c2783f6765582a59
Author: David Sidrane <[email protected]>
AuthorDate: Fri Apr 9 09:26:03 2021 -0700

    stm32h7:Serial Add RX and TX DMA
    
    stm32h7:Serial Use Idel to poll RX DMA
    
    stm32h7:Serial Do not loop in an ISR!
    
    stm32h7:Serial signal txdma completion with semaphore
    
    stm32h7:Serial Apply formatting suggestions from code review
    
    Co-authored-by: Mateusz Szafoni <[email protected]>
    
    stm32h7: Serail Add Power Managment (Untested)
---
 arch/arm/src/stm32h7/Kconfig        |   12 +
 arch/arm/src/stm32h7/stm32_serial.c | 1899 ++++++++++++++++++++++++++++++++---
 arch/arm/src/stm32h7/stm32_uart.h   |  281 +++++-
 3 files changed, 2053 insertions(+), 139 deletions(-)

diff --git a/arch/arm/src/stm32h7/Kconfig b/arch/arm/src/stm32h7/Kconfig
index 00e5b69..64d518f 100644
--- a/arch/arm/src/stm32h7/Kconfig
+++ b/arch/arm/src/stm32h7/Kconfig
@@ -1310,6 +1310,18 @@ config UART8_RXFIFO_THRES
 
 endif # STM32H7_UART8
 
+config STM32H7_SERIAL_RXDMA_BUFFER_SIZE
+       int "Rx DMA buffer size"
+       default 32
+       depends on USART1_RXDMA || USART2_RXDMA || USART3_RXDMA || UART4_RXDMA 
|| UART5_RXDMA || USART6_RXDMA || UART7_RXDMA || UART8_RXDMA
+       ---help---
+               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.
+
+               Value given here will be rounded up to next multiple of 32 
bytes.
+
 config STM32H7_SERIAL_DISABLE_REORDERING
        bool "Disable reordering of ttySx devices."
        default n
diff --git a/arch/arm/src/stm32h7/stm32_serial.c 
b/arch/arm/src/stm32h7/stm32_serial.c
index 005077e..f747879 100644
--- a/arch/arm/src/stm32h7/stm32_serial.c
+++ b/arch/arm/src/stm32h7/stm32_serial.c
@@ -36,6 +36,7 @@
 #include <nuttx/arch.h>
 #include <nuttx/fs/ioctl.h>
 #include <nuttx/serial/serial.h>
+#include <nuttx/semaphore.h>
 #include <nuttx/power/pm.h>
 
 #ifdef CONFIG_SERIAL_TERMIOS
@@ -48,6 +49,7 @@
 #include "chip.h"
 #include "stm32_gpio.h"
 #include "hardware/stm32_pinmap.h"
+#include "stm32_dma.h"
 #include "stm32_rcc.h"
 #include "stm32_uart.h"
 
@@ -63,15 +65,429 @@
 
 #define STM32_NSERIAL (STM32H7_NUSART + STM32H7_NUART)
 
+/* DMA configuration */
+
+/* If DMA is enabled on any USART, then verify that other pre-requisites
+ * have also been selected.
+ */
+
+#ifdef SERIAL_HAVE_RXDMA
+
+/* Verify that RX DMA configuration. */
+
+#  if defined(CONFIG_USART1_RXDMA)
+#    if !defined(DMAMAP_USART1_RX)
+#     error "USART1 DMA map not defined (DMAMAP_USART1_RX)"
+#    endif
+#    if DMAMAP_USART1_RX == DMAMAP_DMA12_USART1RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART1 using DMAMAP_DMA12_USART1RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART1_RX == DMAMAP_DMA12_USART1RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART1 using DMAMAP_DMA12_USART1RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_USART2_RXDMA)
+#    if !defined(DMAMAP_USART2_RX)
+#     error "USART2 DMA map not defined (DMAMAP_USART2_RX)"
+#    endif
+#    if DMAMAP_USART2_RX == DMAMAP_DMA12_USART2RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART2 using DMAMAP_DMA12_USART2RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART2_RX == DMAMAP_DMA12_USART2RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART2 using DMAMAP_DMA12_USART2RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_USART3_RXDMA)
+#    if !defined(DMAMAP_USART3_RX)
+#     error "USART3 DMA map not defined (DMAMAP_USART3_RX)"
+#    endif
+#    if DMAMAP_USART3_RX == DMAMAP_DMA12_USART3RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART3 using DMAMAP_DMA12_USART3RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART3_RX == DMAMAP_DMA12_USART3RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART3 using DMAMAP_DMA12_USART3RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART4_RXDMA)
+#    if !defined(DMAMAP_UART4_RX)
+#     error "UART4 DMA map not defined (DMAMAP_UART4_RX)"
+#    endif
+#    if DMAMAP_UART4_RX == DMAMAP_DMA12_UART4RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART4 using DMAMAP_DMA12_UART4RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART4_RX == DMAMAP_DMA12_UART4RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART4 using DMAMAP_DMA12_UART4RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART5_RXDMA)
+#    if !defined(DMAMAP_UART5_RX)
+#     error "UART5 DMA map not defined (DMAMAP_UART5_RX)"
+#    endif
+#    if DMAMAP_UART5_RX == DMAMAP_DMA12_UART5RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART5 using DMAMAP_DMA12_UART5RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART5_RX == DMAMAP_DMA12_UART5RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART5 using DMAMAP_DMA12_UART5RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_USART6_RXDMA)
+#    if !defined(DMAMAP_USART6_RX)
+#     error "USART6 DMA map not defined (DMAMAP_USART6_RX)"
+#    endif
+#    if DMAMAP_USART6_RX == DMAMAP_DMA12_USART6RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART6 using DMAMAP_DMA12_USART6RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART6_RX == DMAMAP_DMA12_USART6RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART6 using DMAMAP_DMA12_USART6RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART7_RXDMA)
+#    if !defined(DMAMAP_UART7_RX)
+#     error "UART7 DMA map not defined (DMAMAP_UART7_RX)"
+#    endif
+#    if DMAMAP_UART7_RX == DMAMAP_DMA12_UART7RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART7 using DMAMAP_DMA12_UART7RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART7_RX == DMAMAP_DMA12_UART7RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART7 using DMAMAP_DMA12_UART7RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART8_RXDMA)
+#    if !defined(DMAMAP_UART8_RX)
+#     error "UART8 DMA map not defined (DMAMAP_UART8_RX)"
+#    endif
+#    if DMAMAP_UART8_RX == DMAMAP_DMA12_UART8RX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART8 using DMAMAP_DMA12_UART8RX_0 for receive DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART8_RX == DMAMAP_DMA12_UART8RX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART8 using DMAMAP_DMA12_UART8RX_1 for receive DMA 
requires CONFIG_STM32H7_DMA2
+#    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)) || \
+      (defined(CONFIG_UART7_RXDMA) && defined(CONFIG_UART7_RS485)) || \
+      (defined(CONFIG_UART8_RXDMA) && defined(CONFIG_UART8_RS485))
+#    error "RXDMA and RS-485 cannot be enabled at the same time for the same 
U[S]ART"
+#  endif
+
+/* 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.
+ *
+ * This buffer size should be an even multiple of the Cortex-M7 D-Cache line
+ * size, ARMV7M_DCACHE_LINESIZE, so that it can be individually invalidated.
+ *
+ * Should there be a Cortex-M7 without a D-Cache, ARMV7M_DCACHE_LINESIZE
+ * would be zero!
+ */
+
+#  if !defined(ARMV7M_DCACHE_LINESIZE) || ARMV7M_DCACHE_LINESIZE == 0
+#    undef ARMV7M_DCACHE_LINESIZE
+#    define ARMV7M_DCACHE_LINESIZE 32
+#  endif
+
+#  if !defined(CONFIG_STM32H7_SERIAL_RXDMA_BUFFER_SIZE) || \
+      (CONFIG_STM32H7_SERIAL_RXDMA_BUFFER_SIZE < ARMV7M_DCACHE_LINESIZE)
+#    undef CONFIG_STM32H7_SERIAL_RXDMA_BUFFER_SIZE
+#    define CONFIG_STM32H7_SERIAL_RXDMA_BUFFER_SIZE ARMV7M_DCACHE_LINESIZE
+#  endif
+
+#  define RXDMA_BUFFER_MASK   (ARMV7M_DCACHE_LINESIZE - 1)
+#  define RXDMA_BUFFER_SIZE   ((CONFIG_STM32H7_SERIAL_RXDMA_BUFFER_SIZE \
+                                + RXDMA_BUFFER_MASK) & ~RXDMA_BUFFER_MASK)
+
+/* DMA priority */
+
+#  ifndef CONFIG_USART_RXDMAPRIO
+#      define CONFIG_USART_RXDMAPRIO  DMA_SCR_PRIMED
+#  endif
+
+#  if (CONFIG_USART_RXDMAPRIO & ~DMA_SCR_PL_MASK) != 0
+#    error "Illegal value for CONFIG_USART_RXDMAPRIO"
+#  endif
+
+/* DMA control words */
+
+#  define SERIAL_RXDMA_CONTROL_WORD   \
+              (DMA_SCR_DIR_P2M        | \
+               DMA_SCR_CIRC           | \
+               DMA_SCR_MINC           | \
+               DMA_SCR_PSIZE_8BITS    | \
+               DMA_SCR_MSIZE_8BITS    | \
+               CONFIG_USART_RXDMAPRIO | \
+               DMA_SCR_PBURST_SINGLE  | \
+               DMA_SCR_MBURST_SINGLE)
+
+#endif  /* SERIAL_HAVE_RXDMA */
+
+#ifdef SERIAL_HAVE_TXDMA
+
+/* Verify that TX DMA configuration. */
+
+#  if defined(CONFIG_USART1_TXDMA)
+#    if !defined(DMAMAP_USART1_TX)
+#     error "USART1 DMA map not defined (DMAMAP_USART1_TX)"
+#    endif
+#    if DMAMAP_USART1_TX == DMAMAP_DMA12_USART1TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART1 using DMAMAP_DMA12_USART1TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART1_TX == DMAMAP_DMA12_USART1TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART1 using DMAMAP_DMA12_USART1TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_USART2_TXDMA)
+#    if !defined(DMAMAP_USART2_TX)
+#     error "USART2 DMA map not defined (DMAMAP_USART2_TX)"
+#    endif
+#    if DMAMAP_USART2_TX == DMAMAP_DMA12_USART2TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART2 using DMAMAP_DMA12_USART2TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART2_TX == DMAMAP_DMA12_USART2TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART2 using DMAMAP_DMA12_USART2TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_USART3_TXDMA)
+#    if !defined(DMAMAP_USART3_TX)
+#     error "USART3 DMA map not defined (DMAMAP_USART3_TX)"
+#    endif
+#    if DMAMAP_USART3_TX == DMAMAP_DMA12_USART3TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART3 using DMAMAP_DMA12_USART3TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART3_TX == DMAMAP_DMA12_USART3TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART3 using DMAMAP_DMA12_USART3TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART4_TXDMA)
+#    if !defined(DMAMAP_UART4_TX)
+#     error "UART4 DMA map not defined (DMAMAP_UART4_TX)"
+#    endif
+#    if DMAMAP_UART4_TX == DMAMAP_DMA12_UART4TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART4 using DMAMAP_DMA12_UART4TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART4_TX == DMAMAP_DMA12_UART4TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART4 using DMAMAP_DMA12_UART4TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART5_TXDMA)
+#    if !defined(DMAMAP_UART5_TX)
+#     error "UART5 DMA map not defined (DMAMAP_UART5_TX)"
+#    endif
+#    if DMAMAP_UART5_TX == DMAMAP_DMA12_UART5TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART5 using DMAMAP_DMA12_UART5TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART5_TX == DMAMAP_DMA12_UART5TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART5 using DMAMAP_DMA12_UART5TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_USART6_TXDMA)
+#    if !defined(DMAMAP_USART6_TX)
+#     error "USART6 DMA map not defined (DMAMAP_USART6_TX)"
+#    endif
+#    if DMAMAP_USART6_TX == DMAMAP_DMA12_USART6TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 USART6 using DMAMAP_DMA12_USART6TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_USART6_TX == DMAMAP_DMA12_USART6TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 USART6 using DMAMAP_DMA12_USART6TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART7_TXDMA)
+#    if !defined(DMAMAP_UART7_TX)
+#     error "UART7 DMA map not defined (DMAMAP_UART7_TX)"
+#    endif
+#    if DMAMAP_UART7_TX == DMAMAP_DMA12_UART7TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART7 using DMAMAP_DMA12_UART7TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART7_TX == DMAMAP_DMA12_UART7TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART7 using DMAMAP_DMA12_UART7TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+
+#  if defined(CONFIG_UART8_TXDMA)
+#    if !defined(DMAMAP_UART8_TX)
+#     error "UART8 DMA map not defined (DMAMAP_UART8_TX)"
+#    endif
+#    if DMAMAP_UART8_TX == DMAMAP_DMA12_UART8TX_0 && 
!defined(CONFIG_STM32H7_DMA1)
+#        error STM32 UART8 using DMAMAP_DMA12_UART8TX_0 for transmit DMA 
requires CONFIG_STM32H7_DMA1
+#    endif
+#    if DMAMAP_UART8_TX == DMAMAP_DMA12_UART8TX_1 && 
!defined(CONFIG_STM32H7_DMA2)
+#        error STM32 UART8 using DMAMAP_DMA12_UART8TX_1 for transmit DMA 
requires CONFIG_STM32H7_DMA2
+#    endif
+#  endif
+#endif
+
+/* Currently RS-485 support cannot be enabled when TXDMA is in use due to
+ * lack of testing - RS-485 support was developed on STM32F1x
+ */
+
+#if (defined(CONFIG_USART1_TXDMA) && defined(CONFIG_USART1_RS485)) || \
+     (defined(CONFIG_USART2_TXDMA) && defined(CONFIG_USART2_RS485)) || \
+     (defined(CONFIG_USART3_TXDMA) && defined(CONFIG_USART3_RS485)) || \
+     (defined(CONFIG_UART4_TXDMA) && defined(CONFIG_UART4_RS485)) || \
+     (defined(CONFIG_UART5_TXDMA) && defined(CONFIG_UART5_RS485)) || \
+     (defined(CONFIG_USART6_TXDMA) && defined(CONFIG_USART6_RS485)) || \
+     (defined(CONFIG_UART7_TXDMA) && defined(CONFIG_UART7_RS485)) || \
+     (defined(CONFIG_UART8_TXDMA) && defined(CONFIG_UART8_RS485))
+#  error "TXDMA and RS-485 cannot be enabled at the same time for the same 
U[S]ART"
+#endif
+
+/* The DMA buffer size when using TX DMA.
+ *
+ * This TX buffer size should be an even multiple of the Cortex-M7 D-Cache
+ * line size, ARMV7M_DCACHE_LINESIZE, so that it can be individually
+ * invalidated.
+ *
+ * Should there be a Cortex-M7 without a D-Cache, ARMV7M_DCACHE_LINESIZE
+ * would be zero!
+ */
+
+#if !defined(ARMV7M_DCACHE_LINESIZE) || ARMV7M_DCACHE_LINESIZE == 0
+#  undef ARMV7M_DCACHE_LINESIZE
+#  define ARMV7M_DCACHE_LINESIZE 32
+#endif
+
+#define TXDMA_BUFFER_MASK   (ARMV7M_DCACHE_LINESIZE - 1)
+#define TXDMA_BUFFER_SIZE   ((CONFIG_STM32H7_SERIAL_RXDMA_BUFFER_SIZE \
+                              + RXDMA_BUFFER_MASK) & ~RXDMA_BUFFER_MASK)
+
+/* If built with CONFIG_ARMV7M_DCACHE Buffers need to be aligned and
+ * multiples of ARMV7M_DCACHE_LINESIZE
+ */
+
+#if defined(CONFIG_ARMV7M_DCACHE)
+#  define TXDMA_BUF_SIZE(b) (((b) + TXDMA_BUFFER_MASK) & ~TXDMA_BUFFER_MASK)
+#  define TXDMA_BUF_ALIGN   aligned_data(ARMV7M_DCACHE_LINESIZE);
+#else
+#  define TXDMA_BUF_SIZE(b)  (b)
+#  define TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_USART1_TXDMA)
+#  define USART1_TXBUFSIZE_ADJUSTED  CONFIG_USART1_TXBUFSIZE
+#  define USART1_TXBUFSIZE_ALGN
+#else
+#  define USART1_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_USART1_TXBUFSIZE)
+#  define USART1_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_USART2_TXDMA)
+#  define USART2_TXBUFSIZE_ADJUSTED  CONFIG_USART2_TXBUFSIZE
+#  define USART2_TXBUFSIZE_ALGN
+#else
+#  define USART2_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_USART2_TXBUFSIZE)
+#  define USART2_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_USART3_TXDMA)
+#  define USART3_TXBUFSIZE_ADJUSTED  CONFIG_USART3_TXBUFSIZE
+#  define USART3_TXBUFSIZE_ALGN
+#else
+#  define USART3_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_USART3_TXBUFSIZE)
+#  define USART3_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_UART4_TXDMA)
+#  define UART4_TXBUFSIZE_ADJUSTED  CONFIG_UART4_TXBUFSIZE
+#  define UART4_TXBUFSIZE_ALGN
+#else
+#  define UART4_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_UART4_TXBUFSIZE)
+#  define UART4_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_UART5_TXDMA)
+#  define UART5_TXBUFSIZE_ADJUSTED  CONFIG_UART5_TXBUFSIZE
+#  define UART5_TXBUFSIZE_ALGN
+#else
+#  define UART5_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_UART5_TXBUFSIZE)
+#  define UART5_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_USART6_TXDMA)
+#  define USART6_TXBUFSIZE_ADJUSTED  CONFIG_USART6_TXBUFSIZE
+#  define USART6_TXBUFSIZE_ALGN
+#else
+#  define USART6_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_USART6_TXBUFSIZE)
+#  define USART6_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_UART7_TXDMA)
+#  define UART7_TXBUFSIZE_ADJUSTED  CONFIG_UART7_TXBUFSIZE
+#  define UART7_TXBUFSIZE_ALGN
+#else
+#  define UART7_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_UART7_TXBUFSIZE)
+#  define UART7_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#if !defined(CONFIG_UART8_TXDMA)
+#  define UART8_TXBUFSIZE_ADJUSTED  CONFIG_UART8_TXBUFSIZE
+#  define UART8_TXBUFSIZE_ALGN
+#else
+#  define UART8_TXBUFSIZE_ADJUSTED TXDMA_BUF_SIZE(CONFIG_UART8_TXBUFSIZE)
+#  define UART8_TXBUFSIZE_ALGN TXDMA_BUF_ALIGN
+#endif
+
+#ifdef SERIAL_HAVE_TXDMA
+/* DMA priority */
+
+#  ifndef CONFIG_USART_TXDMAPRIO
+#      define CONFIG_USART_TXDMAPRIO  DMA_SCR_PRIMED
+#  endif
+
+#  if (CONFIG_USART_TXDMAPRIO & ~DMA_SCR_PL_MASK) != 0
+#    error "Illegal value for CONFIG_USART_TXDMAPRIO"
+#  endif
+
+#  define SERIAL_TXDMA_CONTROL_WORD     \
+              (DMA_SCR_DIR_M2P        | \
+               DMA_SCR_MINC           | \
+               DMA_SCR_PSIZE_8BITS    | \
+               DMA_SCR_MSIZE_8BITS    | \
+               DMA_SCR_PBURST_SINGLE  | \
+               DMA_SCR_MBURST_SINGLE  | \
+               CONFIG_USART_TXDMAPRIO)
+
+#endif /* SERIAL_HAVE_TXDMA */
+
 /* Power management definitions */
 
 #if defined(CONFIG_PM) && !defined(CONFIG_STM32H7_PM_SERIAL_ACTIVITY)
 #  define CONFIG_STM32H7_PM_SERIAL_ACTIVITY 10
 #endif
 #if defined(CONFIG_PM)
+#  warning stm32h7 serial power managemnt was taken from stm32f7 and is 
untested!
 #  define PM_IDLE_DOMAIN             0 /* Revisit */
 #endif
 
+/* Since RX DMA or TX DMA or both may be enabled for a given U[S]ART.
+ * We need runtime detection in up_dma_setup and up_dma_shutdown
+ * We use the default struct default init value of 0 which does not map
+ * to a valid DMA MAPS.
+ */
+
+#define INVALID_SERIAL_DMA_CHANNEL 0
+
 /* Keep track if a Break was set
  *
  * Note:
@@ -99,6 +515,51 @@
           CONFIG_SERIAL_IFLOWCONTROL_WATERMARKS to be enabled."
 #endif
 
+#ifndef CONFIG_STM32H7_FLOWCONTROL_BROKEN
+/* Combination of RXDMA + IFLOWCONTROL does not work as one might expect.
+ * Since RXDMA uses circular DMA-buffer, DMA will always keep reading new
+ * data from USART peripheral even if DMA buffer underruns. Thus this
+ * combination only does following: RTS is asserted on USART setup and
+ * deasserted on shutdown and does not perform actual RTS flow-control.
+ *
+ * With SW flow-control, RTS is asserted before UART receive buffer fully
+ * fills, thus preventing data loss if application is slow to process data
+ * from serial device node. However, if RxDMA interrupt is blocked for too
+ * long, data loss is still possible as SW flow-control would also be
+ * blocked.
+ */
+
+# if defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_IFLOWCONTROL)
+#    warning "RXDMA and IFLOWCONTROL both enabled for USART1. \
+              This combination can lead to data loss."
+#  endif
+
+#  if defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_IFLOWCONTROL)
+#    warning "RXDMA and IFLOWCONTROL both enabled for USART2. \
+              This combination can lead to data loss."
+#  endif
+
+#  if defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_IFLOWCONTROL)
+#    warning "RXDMA and IFLOWCONTROL both enabled for USART3. \
+              This combination can lead to data loss."
+#  endif
+
+#  if defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_IFLOWCONTROL)
+#    warning "RXDMA and IFLOWCONTROL both enabled for USART6. \
+              This combination can lead to data loss."
+#  endif
+
+#  if defined(CONFIG_UART7_RXDMA) && defined(CONFIG_UART7_IFLOWCONTROL)
+#    warning "RXDMA and IFLOWCONTROL both enabled for UART7. \
+              This combination can lead to data loss."
+#  endif
+
+#  if defined(CONFIG_UART8_RXDMA) && defined(CONFIG_UART8_IFLOWCONTROL)
+#    warning "RXDMA and IFLOWCONTROL both enabled for UART8. \
+              This combination can lead to data loss."
+#  endif
+#endif /* CONFIG_STM32H7_FLOWCONTROL_BROKEN */
+
 /****************************************************************************
  * Private Types
  ****************************************************************************/
@@ -113,6 +574,14 @@ struct up_dev_s
 
   bool              initialized;
 
+#ifdef CONFIG_PM
+  bool              suspended; /* UART device has been suspended. */
+
+  /* Interrupt mask value stored before suspending for stop mode. */
+
+  uint16_t          suspended_ie;
+#endif
+
   /* If termios are supported, then the following fields may vary at
    * runtime.
    */
@@ -155,12 +624,45 @@ struct up_dev_s
   const uint32_t    cts_gpio;  /* U[S]ART CTS GPIO pin configuration */
 #endif
 
+  /* TX DMA state */
+
+#ifdef SERIAL_HAVE_TXDMA
+  const unsigned int txdma_channel; /* DMA channel assigned */
+  DMA_HANDLE        txdma;          /* currently-open trasnmit DMA stream */
+  sem_t             txdmasem;       /* Indicate TX DMA completion */
+#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 */
+#ifdef CONFIG_PM
+  bool              rxdmasusp;      /* Rx DMA suspended */
+#endif
+  uint32_t          rxdmanext;      /* Next byte in the DMA buffer to be read 
*/
+#ifdef CONFIG_ARMV7M_DCACHE
+  uint32_t          rxdmaavail;     /* Number of bytes available without need 
to
+                                     * to invalidate the data cache */
+#endif
+  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
 };
 
+#ifdef CONFIG_PM
+struct pm_config_s
+{
+  struct pm_callback_s pm_cb;
+  bool serial_suspended;
+};
+#endif
+
 /****************************************************************************
  * Private Function Prototypes
  ****************************************************************************/
@@ -172,9 +674,11 @@ static int  up_attach(struct uart_dev_s *dev);
 static void up_detach(struct uart_dev_s *dev);
 static int  up_interrupt(int irq, void *context, FAR void *arg);
 static int  up_ioctl(struct file *filep, int cmd, unsigned long arg);
+#if defined(SERIAL_HAVE_TXDMA_OPS) || defined(SERIAL_HAVE_NODMA_OPS)
 static int  up_receive(struct uart_dev_s *dev, unsigned int *status);
 static void up_rxint(struct uart_dev_s *dev, bool enable);
 static bool up_rxavailable(struct uart_dev_s *dev);
+#endif
 #ifdef CONFIG_SERIAL_IFLOWCONTROL
 static bool up_rxflowcontrol(struct uart_dev_s *dev, unsigned int nbuffered,
                              bool upper);
@@ -183,7 +687,32 @@ static void up_send(struct uart_dev_s *dev, int ch);
 static void up_txint(struct uart_dev_s *dev, bool enable);
 static bool up_txready(struct uart_dev_s *dev);
 
+#ifdef SERIAL_HAVE_TXDMA
+static void up_dma_send(struct uart_dev_s *dev);
+static void up_dma_txint(struct uart_dev_s *dev, bool enable);
+static void up_dma_txavailable(struct uart_dev_s *dev);
+static void up_dma_txcallback(DMA_HANDLE handle, uint8_t status, void *arg);
+#endif
+
+#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA)
+static int  up_dma_setup(struct uart_dev_s *dev);
+static void up_dma_shutdown(struct uart_dev_s *dev);
+#endif
+
+#ifdef SERIAL_HAVE_RXDMA
+static int  up_dma_receive(struct uart_dev_s *dev, unsigned int *status);
+#ifdef CONFIG_PM
+static void up_dma_reenable(struct up_dev_s *priv);
+#endif
+static void up_dma_rxint(struct uart_dev_s *dev, bool enable);
+static bool up_dma_rxavailable(struct uart_dev_s *dev);
+
+static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg);
+#endif
+
 #ifdef CONFIG_PM
+static void up_setsuspend(struct uart_dev_s *dev, bool suspend);
+static void up_pm_setsuspend(bool suspend);
 static void up_pm_notify(struct pm_callback_s *cb, int domain,
                          enum pm_state_e pmstate);
 static int  up_pm_prepare(struct pm_callback_s *cb, int domain,
@@ -194,6 +723,7 @@ static int  up_pm_prepare(struct pm_callback_s *cb, int 
domain,
  * Private Data
  ****************************************************************************/
 
+#ifdef SERIAL_HAVE_NODMA_OPS
 static const struct uart_ops_s g_uart_ops =
 {
   .setup          = up_setup,
@@ -212,47 +742,174 @@ static const struct uart_ops_s g_uart_ops =
   .txready        = up_txready,
   .txempty        = up_txready,
 };
+#endif
+
+#ifdef SERIAL_HAVE_RXTXDMA_OPS
+static const struct uart_ops_s g_uart_rxtxdma_ops =
+{
+  .setup          = up_dma_setup,
+  .shutdown       = up_dma_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_dma_receive,
+  .rxint          = up_dma_rxint,
+  .rxavailable    = up_dma_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = up_rxflowcontrol,
+#endif
+  .send           = up_send,
+  .txint          = up_dma_txint,
+  .txready        = up_txready,
+  .txempty        = up_txready,
+  .dmatxavail     = up_dma_txavailable,
+  .dmasend        = up_dma_send,
+};
+#endif
+
+#ifdef SERIAL_HAVE_RXDMA_OPS
+static const struct uart_ops_s g_uart_rxdma_ops =
+{
+  .setup          = up_dma_setup,
+  .shutdown       = up_dma_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_dma_receive,
+  .rxint          = up_dma_rxint,
+  .rxavailable    = up_dma_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = up_rxflowcontrol,
+#endif
+  .send           = up_send,
+  .txint          = up_txint,
+  .txready        = up_txready,
+  .txempty        = up_txready,
+};
+#endif
+
+#ifdef SERIAL_HAVE_TXDMA_OPS
+static const struct uart_ops_s g_uart_txdma_ops =
+{
+  .setup          = up_dma_setup,
+  .shutdown       = up_dma_shutdown,
+  .attach         = up_attach,
+  .detach         = up_detach,
+  .ioctl          = up_ioctl,
+  .receive        = up_receive,
+  .rxint          = up_rxint,
+  .rxavailable    = up_rxavailable,
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+  .rxflowcontrol  = up_rxflowcontrol,
+#endif
+  .send           = up_send,
+  .txint          = up_dma_txint,
+  .txready        = up_txready,
+  .txempty        = up_txready,
+  .dmatxavail     = up_dma_txavailable,
+  .dmasend        = up_dma_send,
+};
+#endif
+
+/* DMA buffers.  RX DMA buffers must:
+ *
+ * 1. Be a multiple of the D-Cache line size.  This requirement is assured
+ *    by the definition of RXDMA buffer size above.
+ * 2. Be aligned a D-Cache line boundaries, and
+ * 3. Be positioned in DMA-able memory.
+ *
+ * These DMA buffers are defined sequentially here to best assure optimal
+ * packing of the buffers.
+ */
+
+#ifdef CONFIG_USART1_RXDMA
+static char g_usart1rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+# ifdef CONFIG_USART2_RXDMA
+static char g_usart2rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_USART3_RXDMA
+static char g_usart3rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_UART4_RXDMA
+static char g_uart4rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_UART5_RXDMA
+static char g_uart5rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_USART6_RXDMA
+static char g_usart6rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_UART7_RXDMA
+static char g_uart7rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
+
+#ifdef CONFIG_UART8_RXDMA
+static char g_uart8rxfifo[RXDMA_BUFFER_SIZE]
+  aligned_data(ARMV7M_DCACHE_LINESIZE);
+#endif
 
 /* Receive/Transmit buffers */
 
 #ifdef CONFIG_STM32H7_USART1
 static char g_usart1rxbuffer[CONFIG_USART1_RXBUFSIZE];
-static char g_usart1txbuffer[CONFIG_USART1_TXBUFSIZE];
+static char g_usart1txbuffer[USART1_TXBUFSIZE_ADJUSTED] \
+  USART1_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_USART2
 static char g_usart2rxbuffer[CONFIG_USART2_RXBUFSIZE];
-static char g_usart2txbuffer[CONFIG_USART2_TXBUFSIZE];
+static char g_usart2txbuffer[USART2_TXBUFSIZE_ADJUSTED] \
+  USART2_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_USART3
 static char g_usart3rxbuffer[CONFIG_USART3_RXBUFSIZE];
-static char g_usart3txbuffer[CONFIG_USART3_TXBUFSIZE];
+static char g_usart3txbuffer[USART3_TXBUFSIZE_ADJUSTED] \
+  USART3_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_UART4
 static char g_uart4rxbuffer[CONFIG_UART4_RXBUFSIZE];
-static char g_uart4txbuffer[CONFIG_UART4_TXBUFSIZE];
+static char g_uart4txbuffer[UART4_TXBUFSIZE_ADJUSTED] \
+  UART4_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_UART5
 static char g_uart5rxbuffer[CONFIG_UART5_RXBUFSIZE];
-static char g_uart5txbuffer[CONFIG_UART5_TXBUFSIZE];
+static char g_uart5txbuffer[UART5_TXBUFSIZE_ADJUSTED] \
+  UART5_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_USART6
 static char g_usart6rxbuffer[CONFIG_USART6_RXBUFSIZE];
-static char g_usart6txbuffer[CONFIG_USART6_TXBUFSIZE];
+static char g_usart6txbuffer[USART6_TXBUFSIZE_ADJUSTED] \
+  USART6_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_UART7
 static char g_uart7rxbuffer[CONFIG_UART7_RXBUFSIZE];
-static char g_uart7txbuffer[CONFIG_UART7_TXBUFSIZE];
+static char g_uart7txbuffer[UART7_TXBUFSIZE_ADJUSTED] \
+  UART7_TXBUFSIZE_ALGN;
 #endif
 
 #ifdef CONFIG_STM32H7_UART8
 static char g_uart8rxbuffer[CONFIG_UART8_RXBUFSIZE];
-static char g_uart8txbuffer[CONFIG_UART8_TXBUFSIZE];
+static char g_uart8txbuffer[UART8_TXBUFSIZE_ADJUSTED] \
+  UART8_TXBUFSIZE_ALGN;
 #endif
 
 /* This describes the state of the STM32 USART1 ports. */
@@ -267,15 +924,23 @@ static struct up_dev_s g_usart1priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_USART1_RXBUFSIZE,
+        .size    = sizeof(g_usart1rxbuffer),
         .buffer  = g_usart1rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_USART1_TXBUFSIZE,
+        .size    = sizeof(g_usart1txbuffer),
         .buffer  = g_usart1txbuffer,
       },
+#if defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_USART1_RXDMA) && !defined(CONFIG_USART1_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_usart1priv,
     },
 
@@ -297,6 +962,13 @@ static struct up_dev_s g_usart1priv =
   .iflow         = true,
   .rts_gpio      = GPIO_USART1_RTS,
 #endif
+#ifdef CONFIG_USART1_TXDMA
+  .txdma_channel = DMAMAP_USART1_TX,
+#endif
+#ifdef CONFIG_USART1_RXDMA
+  .rxdma_channel = DMAMAP_USART1_RX,
+  .rxfifo        = g_usart1rxfifo,
+#endif
 
 #ifdef CONFIG_USART1_RS485
   .rs485_dir_gpio = GPIO_USART1_RS485_DIR,
@@ -321,15 +993,23 @@ static struct up_dev_s g_usart2priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_USART2_RXBUFSIZE,
+        .size    = sizeof(g_usart2rxbuffer),
         .buffer  = g_usart2rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_USART2_TXBUFSIZE,
+        .size    = sizeof(g_usart2txbuffer),
         .buffer  = g_usart2txbuffer,
       },
+#if defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_USART2_RXDMA) && !defined(CONFIG_USART2_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_usart2priv,
     },
 
@@ -351,6 +1031,13 @@ static struct up_dev_s g_usart2priv =
   .iflow         = true,
   .rts_gpio      = GPIO_USART2_RTS,
 #endif
+#ifdef CONFIG_USART2_TXDMA
+  .txdma_channel = DMAMAP_USART2_TX,
+#endif
+#ifdef CONFIG_USART2_RXDMA
+  .rxdma_channel = DMAMAP_USART2_RX,
+  .rxfifo        = g_usart2rxfifo,
+#endif
 
 #ifdef CONFIG_USART2_RS485
   .rs485_dir_gpio = GPIO_USART2_RS485_DIR,
@@ -375,15 +1062,23 @@ static struct up_dev_s g_usart3priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_USART3_RXBUFSIZE,
+        .size    = sizeof(g_usart3rxbuffer),
         .buffer  = g_usart3rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_USART3_TXBUFSIZE,
+        .size    = sizeof(g_usart3txbuffer),
         .buffer  = g_usart3txbuffer,
       },
+#if defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_USART3_RXDMA) && !defined(CONFIG_USART3_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_usart3priv,
     },
 
@@ -405,6 +1100,13 @@ static struct up_dev_s g_usart3priv =
   .iflow         = true,
   .rts_gpio      = GPIO_USART3_RTS,
 #endif
+#ifdef CONFIG_USART3_TXDMA
+  .txdma_channel = DMAMAP_USART3_TX,
+#endif
+#ifdef CONFIG_USART3_RXDMA
+  .rxdma_channel = DMAMAP_USART3_RX,
+  .rxfifo        = g_usart3rxfifo,
+#endif
 
 #ifdef CONFIG_USART3_RS485
   .rs485_dir_gpio = GPIO_USART3_RS485_DIR,
@@ -429,15 +1131,23 @@ static struct up_dev_s g_uart4priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_UART4_RXBUFSIZE,
+        .size    = sizeof(g_uart4rxbuffer),
         .buffer  = g_uart4rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_UART4_TXBUFSIZE,
+        .size    = sizeof(g_uart4txbuffer),
         .buffer  = g_uart4txbuffer,
       },
+#if defined(CONFIG_UART4_RXDMA) && defined(CONFIG_UART4_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_UART4_RXDMA) && !defined(CONFIG_UART4_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_UART4_RXDMA) && defined(CONFIG_UART4_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_uart4priv,
     },
 
@@ -459,6 +1169,13 @@ static struct up_dev_s g_uart4priv =
   .usartbase     = STM32_UART4_BASE,
   .tx_gpio       = GPIO_UART4_TX,
   .rx_gpio       = GPIO_UART4_RX,
+#ifdef CONFIG_UART4_TXDMA
+  .txdma_channel = DMAMAP_UART4_TX,
+#endif
+#ifdef CONFIG_UART4_RXDMA
+  .rxdma_channel = DMAMAP_UART4_RX,
+  .rxfifo        = g_uart4rxfifo,
+#endif
 
 #ifdef CONFIG_UART4_RS485
   .rs485_dir_gpio = GPIO_UART4_RS485_DIR,
@@ -483,15 +1200,23 @@ static struct up_dev_s g_uart5priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_UART5_RXBUFSIZE,
+        .size    = sizeof(g_uart5rxbuffer),
         .buffer  = g_uart5rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_UART5_TXBUFSIZE,
+        .size    = sizeof(g_uart5txbuffer),
         .buffer  = g_uart5txbuffer,
       },
+#if defined(CONFIG_UART5_RXDMA) && defined(CONFIG_UART5_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_UART5_RXDMA) && !defined(CONFIG_UART5_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_UART5_RXDMA) && defined(CONFIG_UART5_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_uart5priv,
     },
 
@@ -513,6 +1238,13 @@ static struct up_dev_s g_uart5priv =
   .usartbase     = STM32_UART5_BASE,
   .tx_gpio       = GPIO_UART5_TX,
   .rx_gpio       = GPIO_UART5_RX,
+#ifdef CONFIG_UART5_TXDMA
+  .txdma_channel = DMAMAP_UART5_TX,
+#endif
+#ifdef CONFIG_UART5_RXDMA
+  .rxdma_channel = DMAMAP_UART5_RX,
+  .rxfifo        = g_uart5rxfifo,
+#endif
 
 #ifdef CONFIG_UART5_RS485
   .rs485_dir_gpio = GPIO_UART5_RS485_DIR,
@@ -537,15 +1269,23 @@ static struct up_dev_s g_usart6priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_USART6_RXBUFSIZE,
+        .size    = sizeof(g_usart6rxbuffer),
         .buffer  = g_usart6rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_USART6_TXBUFSIZE,
+        .size    = sizeof(g_usart6txbuffer),
         .buffer  = g_usart6txbuffer,
       },
+#if defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_USART6_RXDMA) && !defined(CONFIG_USART6_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_usart6priv,
     },
 
@@ -567,6 +1307,13 @@ static struct up_dev_s g_usart6priv =
   .iflow         = true,
   .rts_gpio      = GPIO_USART6_RTS,
 #endif
+#ifdef CONFIG_USART6_TXDMA
+  .txdma_channel = DMAMAP_USART6_TX,
+#endif
+#ifdef CONFIG_USART6_RXDMA
+  .rxdma_channel = DMAMAP_USART6_RX,
+  .rxfifo        = g_usart6rxfifo,
+#endif
 
 #ifdef CONFIG_USART6_RS485
   .rs485_dir_gpio = GPIO_USART6_RS485_DIR,
@@ -591,15 +1338,23 @@ static struct up_dev_s g_uart7priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_UART7_RXBUFSIZE,
+        .size    = sizeof(g_uart7rxbuffer),
         .buffer  = g_uart7rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_UART7_TXBUFSIZE,
+        .size    = sizeof(g_uart7txbuffer),
         .buffer  = g_uart7txbuffer,
       },
+#if defined(CONFIG_UART7_RXDMA) && defined(CONFIG_UART7_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_UART7_RXDMA) && !defined(CONFIG_UART7_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_UART7_RXDMA) && defined(CONFIG_UART7_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_uart7priv,
     },
 
@@ -621,6 +1376,13 @@ static struct up_dev_s g_uart7priv =
   .iflow         = true,
   .rts_gpio      = GPIO_UART7_RTS,
 #endif
+#ifdef CONFIG_UART7_TXDMA
+  .txdma_channel = DMAMAP_UART7_TX,
+#endif
+#ifdef CONFIG_UART7_RXDMA
+  .rxdma_channel = DMAMAP_UART7_RX,
+  .rxfifo        = g_uart7rxfifo,
+#endif
 
 #ifdef CONFIG_UART7_RS485
   .rs485_dir_gpio = GPIO_UART7_RS485_DIR,
@@ -645,15 +1407,23 @@ static struct up_dev_s g_uart8priv =
 #endif
       .recv      =
       {
-        .size    = CONFIG_UART8_RXBUFSIZE,
+        .size    = sizeof(g_uart8rxbuffer),
         .buffer  = g_uart8rxbuffer,
       },
       .xmit      =
       {
-        .size    = CONFIG_UART8_TXBUFSIZE,
+        .size    = sizeof(g_uart8txbuffer),
         .buffer  = g_uart8txbuffer,
       },
+#if defined(CONFIG_UART8_RXDMA) && defined(CONFIG_UART8_TXDMA)
+      .ops       = &g_uart_rxtxdma_ops,
+#elif defined(CONFIG_UART8_RXDMA) && !defined(CONFIG_UART8_TXDMA)
+      .ops       = &g_uart_rxdma_ops,
+#elif !defined(CONFIG_UART8_RXDMA) && defined(CONFIG_UART8_TXDMA)
+      .ops       = &g_uart_txdma_ops,
+#else
       .ops       = &g_uart_ops,
+#endif
       .priv      = &g_uart8priv,
     },
 
@@ -675,6 +1445,13 @@ static struct up_dev_s g_uart8priv =
   .iflow         = true,
   .rts_gpio      = GPIO_UART8_RTS,
 #endif
+#ifdef CONFIG_UART8_TXDMA
+  .txdma_channel = DMAMAP_UART8_TX,
+#endif
+#ifdef CONFIG_UART8_RXDMA
+  .rxdma_channel = DMAMAP_UART8_RX,
+  .rxfifo        = g_uart8rxfifo,
+#endif
 
 #ifdef CONFIG_UART8_RS485
   .rs485_dir_gpio = GPIO_UART8_RS485_DIR,
@@ -718,10 +1495,11 @@ static struct up_dev_s * const 
g_uart_devs[STM32_NSERIAL] =
 };
 
 #ifdef CONFIG_PM
-static  struct pm_callback_s g_serialcb =
+static struct pm_config_s g_serialpm =
 {
-  .notify  = up_pm_notify,
-  .prepare = up_pm_prepare,
+  .pm_cb.notify     = up_pm_notify,
+  .pm_cb.prepare    = up_pm_prepare,
+  .serial_suspended = false
 };
 #endif
 
@@ -779,6 +1557,9 @@ static inline void up_setusartint(struct up_dev_s *priv, 
uint16_t ie)
   cr = up_serialin(priv, STM32_USART_CR1_OFFSET);
   cr &= ~(USART_CR1_USED_INTS);
   cr |= (ie & (USART_CR1_USED_INTS));
+#ifdef SERIAL_HAVE_RXDMA
+  cr |= USART_CR1_IDLEIE;
+#endif
   up_serialout(priv, STM32_USART_CR1_OFFSET, cr);
 
   cr = up_serialin(priv, STM32_USART_CR3_OFFSET);
@@ -821,7 +1602,7 @@ static void up_disableusartint(struct up_dev_s *priv, 
uint16_t *ie)
        *
        * Enable             Status          Meaning                Usage
        * ---------------- -------------- ----------------------- ----------
-       * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected       (not used)
+       * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected
        * USART_CR1_RXNEIE USART_ISR_RXNE Received Data Ready
        *                                    to be Read
        * "              " USART_ISR_ORE  Overrun Error Detected
@@ -858,20 +1639,40 @@ static void up_disableusartint(struct up_dev_s *priv, 
uint16_t *ie)
 }
 
 /****************************************************************************
- * Name: up_set_format
+ * Name: up_dma_nextrx
  *
  * Description:
- *   Set the serial line format and speed.
+ *   Returns the index into the RX FIFO where the DMA will place the next
+ *   byte that it receives.
  *
  ****************************************************************************/
 
-#ifndef CONFIG_SUPPRESS_UART_CONFIG
-static void up_set_format(struct uart_dev_s *dev)
+#ifdef SERIAL_HAVE_RXDMA
+static int up_dma_nextrx(struct up_dev_s *priv)
 {
-  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
-  uint32_t regval;
-  uint32_t usartdiv8;
-  uint32_t cr1;
+  size_t dmaresidual;
+
+  dmaresidual = stm32_dmaresidual(priv->rxdma);
+
+  return (RXDMA_BUFFER_SIZE - (int)dmaresidual);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_set_format
+ *
+ * Description:
+ *   Set the serial line format and speed.
+ *
+ ****************************************************************************/
+
+#ifndef CONFIG_SUPPRESS_UART_CONFIG
+static void up_set_format(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  uint32_t regval;
+  uint32_t usartdiv8;
+  uint32_t cr1;
   uint32_t cr1_ue;
   uint32_t brr;
   irqstate_t flags;
@@ -1014,6 +1815,155 @@ static void up_set_format(struct uart_dev_s *dev)
 #endif /* CONFIG_SUPPRESS_UART_CONFIG */
 
 /****************************************************************************
+ * Name: up_setsuspend
+ *
+ * Description:
+ *   Suspend or resume serial peripheral.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static void up_setsuspend(struct uart_dev_s *dev, bool suspend)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  int passes;
+#ifdef SERIAL_HAVE_RXDMA
+  bool dmarestored = false;
+#endif
+
+  if (priv->suspended == suspend)
+    {
+      return;
+    }
+
+  priv->suspended = suspend;
+
+  if (suspend)
+    {
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+      if (priv->iflow)
+        {
+          /* Force RTS high to prevent further Rx. */
+
+          stm32_configgpio((priv->rts_gpio & ~GPIO_MODE_MASK)
+                           | (GPIO_OUTPUT | GPIO_OUTPUT_SET));
+        }
+#endif
+
+      /* Disable interrupts to prevent Tx. */
+
+      up_disableusartint(priv, &priv->suspended_ie);
+
+      /* Loop until last Tx has completed or,
+       * until we have been looping for a long time.
+       */
+
+      for (passes = 0; passes < 256; passes++)
+        {
+          if ((up_serialin(priv,
+                           STM32_USART_ISR_OFFSET) & USART_ISR_TC) != 0)
+            {
+              break;
+            }
+        }
+
+#ifdef SERIAL_HAVE_RXDMA
+      if (priv->rxdma != NULL && !priv->rxdmasusp)
+        {
+          /* Suspend Rx DMA. */
+
+          stm32_dmastop(priv->rxdma);
+          priv->rxdmasusp = true;
+        }
+#endif
+    }
+  else
+    {
+#ifdef SERIAL_HAVE_RXDMA
+      if (priv->rxdma != NULL  && priv->rxdmasusp)
+        {
+          /* Re-enable DMA. */
+
+          up_dma_reenable(priv);
+          priv->rxdmasusp = false;
+
+          dmarestored = true;
+        }
+#endif
+
+      /* Re-enable interrupts to resume Tx. */
+
+      up_restoreusartint(priv, priv->suspended_ie);
+
+#ifdef CONFIG_SERIAL_IFLOWCONTROL
+      if (priv->iflow)
+        {
+          /* Restore peripheral RTS control. */
+
+          stm32_configgpio(priv->rts_gpio);
+        }
+#endif
+    }
+
+#ifdef SERIAL_HAVE_RXDMA
+  if (dmarestored)
+    {
+      irqstate_t flags;
+
+      flags = enter_critical_section();
+
+      /* Perform initial Rx DMA buffer fetch to wake-up serial device
+       * activity.
+       */
+
+      if (priv->rxdma != NULL)
+        {
+          up_dma_rxcallback(priv->rxdma, 0, priv);
+        }
+
+      leave_critical_section(flags);
+    }
+#endif
+}
+#endif
+
+/****************************************************************************
+ * Name: up_pm_setsuspend
+ *
+ * Description:
+ *   Suspend or resume serial peripherals for/from deep-sleep/stop modes.
+ *
+ ****************************************************************************/
+
+#ifdef CONFIG_PM
+static void up_pm_setsuspend(bool suspend)
+{
+  int n;
+
+  /* Already in desired state? */
+
+  if (suspend == g_serialpm.serial_suspended)
+    {
+      return;
+    }
+
+  g_serialpm.serial_suspended = suspend;
+
+  for (n = 0; n < STM32H7_NUSART + STM32H7_NUART; n++)
+    {
+      struct up_dev_s *priv = g_uart_devs[n];
+
+      if (!priv || !priv->initialized)
+        {
+          continue;
+        }
+
+      up_setsuspend(&priv->dev, suspend);
+    }
+}
+#endif
+
+/****************************************************************************
  * Name: up_set_apb_clock
  *
  * Description:
@@ -1214,6 +2164,10 @@ 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);
+#ifdef SERIAL_HAVE_RXDMA
+  regval |= USART_CR1_IDLEIE;
+#endif
+
   regval |= USART_CR1_FIFOEN;
 
   up_serialout(priv, STM32_USART_CR1_OFFSET, regval);
@@ -1232,6 +2186,94 @@ static int up_setup(struct uart_dev_s *dev)
 }
 
 /****************************************************************************
+ * Name: up_dma_setup
+ *
+ * Description:
+ *   Configure the USART baud, bits, parity, etc. This method is called the
+ *   first time that the serial port is opened.
+ *
+ ****************************************************************************/
+
+#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA)
+static int up_dma_setup(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  int result;
+#if defined(SERIAL_HAVE_RXDMA)
+  struct stm32_dma_config_s rxdmacfg;
+#endif
+  /* Do the basic UART setup first, unless we are the console */
+
+  if (!dev->isconsole)
+    {
+      result = up_setup(dev);
+      if (result != OK)
+        {
+          return result;
+        }
+    }
+
+#if defined(SERIAL_HAVE_TXDMA)
+  /* Acquire the Tx DMA channel.  This should always succeed. */
+
+  if (priv->txdma_channel != INVALID_SERIAL_DMA_CHANNEL)
+    {
+      priv->txdma = stm32_dmachannel(priv->txdma_channel);
+
+      nxsem_init(&priv->txdmasem, 0, 0);
+      nxsem_set_protocol(&priv->txdmasem, SEM_PRIO_NONE);
+
+      /* Enable receive Tx DMA for the UART */
+
+      modifyreg32(priv->usartbase + STM32_USART_CR3_OFFSET,
+                  0, USART_CR3_DMAT);
+    }
+#endif
+
+#if defined(SERIAL_HAVE_RXDMA)
+  /* Acquire the Rx DMA channel.  This should always succeed. */
+
+  if (priv->rxdma_channel != INVALID_SERIAL_DMA_CHANNEL)
+    {
+      priv->rxdma = stm32_dmachannel(priv->rxdma_channel);
+
+      /* Configure for circular DMA reception into the RX FIFO */
+
+      rxdmacfg.paddr  = priv->usartbase + STM32_USART_RDR_OFFSET;
+      rxdmacfg.maddr  = (uint32_t)priv->rxfifo;
+      rxdmacfg.ndata  = RXDMA_BUFFER_SIZE;
+      rxdmacfg.cfg1   = SERIAL_RXDMA_CONTROL_WORD;
+      rxdmacfg.cfg2   = 0;
+      stm32_dmasetup(priv->rxdma, &rxdmacfg);
+
+      /* Reset our DMA shadow pointer and Rx data availability count to
+       * match the address just programmed above.
+       */
+
+      priv->rxdmanext = 0;
+#ifdef CONFIG_ARMV7M_DCACHE
+      priv->rxdmaavail = 0;
+#endif
+
+      /* Enable receive Rx DMA for the UART */
+
+      modifyreg32(priv->usartbase + STM32_USART_CR3_OFFSET,
+                  0, USART_CR3_DMAR);
+
+      /* 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);
+    }
+#endif
+
+  return OK;
+}
+#endif
+
+/****************************************************************************
  * Name: up_shutdown
  *
  * Description:
@@ -1298,6 +2340,54 @@ static void up_shutdown(struct uart_dev_s *dev)
 }
 
 /****************************************************************************
+ * Name: up_dma_shutdown
+ *
+ * Description:
+ *   Disable the USART.  This method is called when the serial
+ *   port is closed
+ *
+ ****************************************************************************/
+
+#if defined(SERIAL_HAVE_RXDMA) || defined(SERIAL_HAVE_TXDMA)
+static void up_dma_shutdown(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Perform the normal UART shutdown */
+
+  up_shutdown(dev);
+
+#if defined(SERIAL_HAVE_RXDMA)
+  /* Stop the RX DMA channel */
+
+  if (priv->rxdma_channel != INVALID_SERIAL_DMA_CHANNEL)
+    {
+      stm32_dmastop(priv->rxdma);
+
+      /* Release the RX DMA channel */
+
+      stm32_dmafree(priv->rxdma);
+      priv->rxdma = NULL;
+    }
+#endif
+
+#if defined(SERIAL_HAVE_TXDMA)
+  /* Stop the TX DMA channel */
+
+  if (priv->txdma_channel != INVALID_SERIAL_DMA_CHANNEL)
+    {
+      stm32_dmastop(priv->txdma);
+
+      /* Release the TX DMA channel */
+
+      stm32_dmafree(priv->txdma);
+      priv->txdma = NULL;
+    }
+#endif
+}
+#endif
+
+/****************************************************************************
  * Name: up_attach
  *
  * Description:
@@ -1365,8 +2455,6 @@ static void up_detach(struct uart_dev_s *dev)
 static int up_interrupt(int irq, void *context, FAR void *arg)
 {
   struct up_dev_s *priv = (struct up_dev_s *)arg;
-  int  passes;
-  bool handled;
 
   DEBUGASSERT(priv != NULL);
 
@@ -1376,100 +2464,101 @@ static int up_interrupt(int irq, void *context, FAR 
void *arg)
   pm_activity(PM_IDLE_DOMAIN, CONFIG_STM32H7_PM_SERIAL_ACTIVITY);
 #endif
 
-  /* Loop until there are no characters to be transferred or,
-   * until we have been looping for a long time.
-   */
+  /* Get the masked USART status word. */
 
-  handled = true;
-  for (passes = 0; passes < 256 && handled; passes++)
-    {
-      handled = false;
+  priv->sr = up_serialin(priv, STM32_USART_ISR_OFFSET);
 
-      /* Get the masked USART status word. */
+  /* USART interrupts:
+   *
+   * Enable           Status          Meaning                 Usage
+   * ---------------- -------------- ------------------------ ----------
+   * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected
+   * USART_CR1_RXNEIE USART_ISR_RXNE Received Data Ready
+   *                                    to be Read
+   * "              " USART_ISR_ORE  Overrun Error Detected
+   * USART_CR1_TCIE   USART_ISR_TC   Transmission Complete    (used only
+   *                                                          for RS-485)
+   * USART_CR1_TXEIE  USART_ISR_TXE  Transmit Data Register
+   *                                      Empty
+   * USART_CR1_PEIE   USART_ISR_PE   Parity Error
+   *
+   * USART_CR2_LBDIE  USART_ISR_LBD  Break Flag               (not used)
+   * USART_CR3_EIE    USART_ISR_FE   Framing Error
+   * "           "    USART_ISR_NF   Noise Error
+   * "           "    USART_ISR_ORE  Overrun Error Detected
+   * USART_CR3_CTSIE  USART_ISR_CTS  CTS flag                 (not used)
+   *
+   * NOTE:
+   * Some of these status bits must be cleared by explicitly writing zero
+   * to the SR register: USART_ISR_CTS, USART_ISR_LBD. Note of those are
+   * currently being used.
+   */
 
-      priv->sr = up_serialin(priv, STM32_USART_ISR_OFFSET);
+#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...
+   */
 
-      /* USART interrupts:
-       *
-       * Enable           Status          Meaning                 Usage
-       * ---------------- -------------- ------------------------ ----------
-       * USART_CR1_IDLEIE USART_ISR_IDLE Idle Line Detected       (not used)
-       * USART_CR1_RXNEIE USART_ISR_RXNE Received Data Ready
-       *                                    to be Read
-       * "              " USART_ISR_ORE  Overrun Error Detected
-       * USART_CR1_TCIE   USART_ISR_TC   Transmission Complete    (used only
-       *                                                          for RS-485)
-       * USART_CR1_TXEIE  USART_ISR_TXE  Transmit Data Register
-       *                                      Empty
-       * USART_CR1_PEIE   USART_ISR_PE   Parity Error
-       *
-       * USART_CR2_LBDIE  USART_ISR_LBD  Break Flag               (not used)
-       * USART_CR3_EIE    USART_ISR_FE   Framing Error
-       * "           "    USART_ISR_NF   Noise Error
-       * "           "    USART_ISR_ORE  Overrun Error Detected
-       * USART_CR3_CTSIE  USART_ISR_CTS  CTS flag                 (not used)
-       *
-       * NOTE:
-       * Some of these status bits must be cleared by explicitly writing zero
-       * to the SR register: USART_ISR_CTS, USART_ISR_LBD. Note of those are
-       * currently being used.
-       */
+  if ((priv->sr & USART_ISR_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
 
-#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...
-       */
+#ifdef SERIAL_HAVE_RXDMA
+  /* The line going to idle, deliver any fractions of RX data */
 
-      if ((priv->sr & USART_ISR_TC) != 0 &&
-          (priv->ie & USART_CR1_TCIE) != 0 &&
-          (priv->ie & USART_CR1_TXEIE) == 0)
+  if ((priv->sr & USART_ISR_IDLE) != 0)
+    {
+      up_serialout(priv, STM32_USART_ICR_OFFSET, USART_ICR_IDLECF);
+      if (priv->rxdma != 0)
         {
-          stm32_gpiowrite(priv->rs485_dir_gpio, !priv->rs485_dir_polarity);
-          up_restoreusartint(priv, priv->ie & ~USART_CR1_TCIE);
+          up_dma_rxcallback(priv->rxdma, 0, priv);
         }
+    }
 #endif
 
-      /* Handle incoming, receive bytes. */
+  /* Handle incoming, receive bytes. */
 
-      if ((priv->sr & USART_ISR_RXNE) != 0 &&
-          (priv->ie & USART_CR1_RXNEIE) != 0)
-        {
-          /* Received data ready... process incoming bytes.
-           *  NOTE the check for RXNEIE:  We cannot call uart_recvchards of
-           * RX interrupts are disabled.
-           */
+  if ((priv->sr & USART_ISR_RXNE) != 0 &&
+      (priv->ie & USART_CR1_RXNEIE) != 0)
+    {
+      /* Received data ready... process incoming bytes.
+       *  NOTE the check for RXNEIE:  We cannot call uart_recvchards of
+       * RX interrupts are disabled.
+       */
 
-          uart_recvchars(&priv->dev);
-          handled = true;
-        }
+      uart_recvchars(&priv->dev);
+    }
 
-      /* We may still have to read from the DR register to clear any pending
-       * error conditions.
-       */
+  /* We may still have to read from the DR register to clear any pending
+   * error conditions.
+   */
 
-      else if ((priv->sr &
-               (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE)) != 0)
-        {
-          /* These errors are cleared by writing the corresponding bit to the
-           * interrupt clear register (ICR).
-           */
+  else if ((priv->sr &
+           (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE)) != 0)
+    {
+      /* These errors are cleared by writing the corresponding bit to the
+       * interrupt clear register (ICR).
+       */
 
-          up_serialout(priv, STM32_USART_ICR_OFFSET,
-                      (USART_ICR_NCF | USART_ICR_ORECF | USART_ICR_FECF));
-        }
+      up_serialout(priv, STM32_USART_ICR_OFFSET,
+                  (USART_ICR_NCF | USART_ICR_ORECF | USART_ICR_FECF));
+    }
 
-      /* Handle outgoing, transmit bytes */
+  /* Handle outgoing, transmit bytes */
 
-      if ((priv->sr & USART_ISR_TXE) != 0 &&
-          (priv->ie & USART_CR1_TXEIE) != 0)
-        {
-          /* Transmit data register empty ... process outgoing bytes */
+  if ((priv->sr & USART_ISR_TXE) != 0 &&
+      (priv->ie & USART_CR1_TXEIE) != 0)
+    {
+      /* Transmit data register empty ... process outgoing bytes */
 
-          uart_xmitchars(&priv->dev);
-          handled = true;
-        }
+      uart_xmitchars(&priv->dev);
     }
 
   return OK;
@@ -1842,6 +2931,7 @@ static int up_ioctl(struct file *filep, int cmd, unsigned 
long arg)
  *
  ****************************************************************************/
 
+#ifndef SERIAL_HAVE_ONLY_RXDMA
 static int up_receive(struct uart_dev_s *dev, unsigned int *status)
 {
   struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
@@ -1860,6 +2950,7 @@ static int up_receive(struct uart_dev_s *dev, unsigned 
int *status)
 
   return rdr & 0xff;
 }
+#endif
 
 /****************************************************************************
  * Name: up_rxint
@@ -1869,6 +2960,7 @@ static int up_receive(struct uart_dev_s *dev, unsigned 
int *status)
  *
  ****************************************************************************/
 
+#ifndef SERIAL_HAVE_ONLY_RXDMA
 static void up_rxint(struct uart_dev_s *dev, bool enable)
 {
   struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
@@ -1917,6 +3009,7 @@ static void up_rxint(struct uart_dev_s *dev, bool enable)
   up_restoreusartint(priv, ie);
   leave_critical_section(flags);
 }
+#endif
 
 /****************************************************************************
  * Name: up_rxavailable
@@ -1926,11 +3019,13 @@ static void up_rxint(struct uart_dev_s *dev, bool 
enable)
  *
  ****************************************************************************/
 
+#ifndef SERIAL_HAVE_ONLY_RXDMA
 static bool up_rxavailable(struct uart_dev_s *dev)
 {
   struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
   return ((up_serialin(priv, STM32_USART_ISR_OFFSET) & USART_ISR_RXNE) != 0);
 }
+#endif
 
 /****************************************************************************
  * Name: up_rxflowcontrol
@@ -2029,30 +3124,368 @@ static bool up_rxflowcontrol(struct uart_dev_s *dev,
 #endif
 
 /****************************************************************************
- * Name: up_send
+ * Name: up_dma_receive
  *
  * Description:
- *   This method will send one byte on the USART
+ *   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'.
  *
  ****************************************************************************/
 
-static void up_send(struct uart_dev_s *dev, int ch)
+#ifdef SERIAL_HAVE_RXDMA
+static int up_dma_receive(struct uart_dev_s *dev, unsigned int *status)
 {
   struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  uint32_t nextrx = up_dma_nextrx(priv);
+  int c = 0;
 
-#ifdef HAVE_RS485
-  if (priv->rs485_dir_gpio != 0)
+  /* Check if more data is available */
+
+  if (nextrx != priv->rxdmanext)
     {
-      stm32_gpiowrite(priv->rs485_dir_gpio, priv->rs485_dir_polarity);
-    }
-#endif
+#ifdef CONFIG_ARMV7M_DCACHE
+      /* If the data cache is enabled, then we will also need to manage
+       * cache coherency.  Are any bytes available in the currently coherent
+       * region of the data cache?
+       */
 
-  up_serialout(priv, STM32_USART_TDR_OFFSET, (uint32_t)ch);
-}
+      if (priv->rxdmaavail == 0)
+        {
+          uint32_t rxdmaavail;
+          uintptr_t addr;
 
-/****************************************************************************
- * Name: up_txint
- *
+          /* No.. then we will have to invalidate additional space in the Rx
+           * DMA buffer.
+           */
+
+          if (nextrx > priv->rxdmanext)
+            {
+              /* Number of available bytes */
+
+              rxdmaavail = nextrx - priv->rxdmanext;
+            }
+          else
+            {
+              /* Number of available bytes up to the end of RXDMA buffer */
+
+              rxdmaavail = RXDMA_BUFFER_SIZE - priv->rxdmanext;
+            }
+
+          /* Invalidate the DMA buffer range */
+
+          addr = (uintptr_t)&priv->rxfifo[priv->rxdmanext];
+          up_invalidate_dcache(addr, addr + rxdmaavail);
+
+          /* We don't need to invalidate the data cache for the next
+           * rxdmaavail number of next bytes.
+           */
+
+          priv->rxdmaavail = rxdmaavail;
+        }
+
+      priv->rxdmaavail--;
+#endif
+
+      /* Now read from the DMA buffer */
+
+      c = priv->rxfifo[priv->rxdmanext];
+
+      priv->rxdmanext++;
+      if (priv->rxdmanext == RXDMA_BUFFER_SIZE)
+        {
+          priv->rxdmanext = 0;
+        }
+    }
+
+  /* NOTE:  If no data is available, then we would return NULL which is,
+   * of course, valid binary data.  The protocol is that the upper half
+   * driver must call up_dma_rxavailable prior to calling this function to
+   * assure that this never happens.
+   */
+
+  return c;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_reenable
+ *
+ * Description:
+ *   Call to re-enable RX DMA.
+ *
+ ****************************************************************************/
+
+#if defined(SERIAL_HAVE_RXDMA) && defined(CONFIG_PM)
+static void up_dma_reenable(struct up_dev_s *priv)
+{
+  struct stm32_dma_config_s rxdmacfg;
+
+  /* Configure for circular DMA reception into the RX FIFO */
+
+  rxdmacfg.paddr  = priv->usartbase + STM32_USART_RDR_OFFSET;
+  rxdmacfg.maddr  = (uint32_t)priv->rxfifo;
+  rxdmacfg.ndata  = RXDMA_BUFFER_SIZE;
+  rxdmacfg.cfg1   = SERIAL_RXDMA_CONTROL_WORD;
+  rxdmacfg.cfg2   = 0;
+  stm32_dmasetup(priv->rxdma, &rxdmacfg);
+
+  /* Reset our DMA shadow pointer and Rx data availability count to match
+   * the address just programmed above.
+   */
+
+  priv->rxdmanext  = 0;
+#ifdef CONFIG_ARMV7M_DCACHE
+  priv->rxdmaavail = 0;
+#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.
+   */
+
+  stm32_dmastart(priv->rxdma, up_dma_rxcallback, (void *)priv, true);
+
+  /* Clear DMA suspended flag. */
+
+  priv->rxdmasusp  = false;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_rxint
+ *
+ * Description:
+ *   Call to enable or disable RX interrupts
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static void up_dma_rxint(struct uart_dev_s *dev, bool enable)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Enable/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 up_dma_poll or
+   * DMA event.
+   */
+
+  priv->rxenable = enable;
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_rxavailable
+ *
+ * Description:
+ *   Return true if the receive register is not empty
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static bool up_dma_rxavailable(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* Compare our receive pointer to the current DMA pointer, if they
+   * do not match, then there are bytes to be received.
+   */
+
+  return (up_dma_nextrx(priv) != priv->rxdmanext);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_txcallback
+ *
+ * Description:
+ *   This function clears dma buffer at complete of DMA transfer and wakes up
+ *   threads waiting for space in buffer.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void up_dma_txcallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+  struct stm32_dma_config_s txdmacfg;
+  struct up_dev_s *priv = (struct up_dev_s *)arg;
+
+  /* Update 'nbytes' indicating number of bytes actually transferred by DMA.
+   * This is important to free TX buffer space by 'uart_xmitchars_done'.
+   */
+
+  if (status & DMA_SCR_HTIE)
+    {
+      priv->dev.dmatx.nbytes += priv->dev.dmatx.length / 2;
+    }
+  else if (status & DMA_SCR_TCIE)
+    {
+      priv->dev.dmatx.nbytes += priv->dev.dmatx.length;
+      if (priv->dev.dmatx.nlength)
+        {
+          /* Set up DMA on next buffer */
+
+          txdmacfg.paddr  = priv->usartbase + STM32_USART_TDR_OFFSET;
+          txdmacfg.maddr  = (uint32_t) priv->dev.dmatx.nbuffer;
+          txdmacfg.ndata  = (size_t) priv->dev.dmatx.nlength;
+          txdmacfg.cfg1   = SERIAL_TXDMA_CONTROL_WORD;
+          txdmacfg.cfg2   = 0;
+          stm32_dmasetup(priv->txdma, &txdmacfg);
+
+          /* Set length for next completion */
+
+          priv->dev.dmatx.length  = priv->dev.dmatx.nlength;
+          priv->dev.dmatx.nlength = 0;
+
+          /* Start transmission with the callback on DMA completion */
+
+          stm32_dmastart(priv->txdma, up_dma_txcallback,
+                        (void *)priv, false);
+
+          return;
+        }
+    }
+
+  nxsem_post(&priv->txdmasem);
+
+  /* Adjust the pointers */
+
+  uart_xmitchars_done(&priv->dev);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_txavailable
+ *
+ * Description:
+ *   Informs DMA that Tx data is available and is ready for transfer.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void up_dma_txavailable(struct uart_dev_s *dev)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+  size_t resid = 0;
+
+  resid = stm32_dmaresidual(priv->txdma);
+
+  /* Only send when the DMA is idle */
+
+  if (resid != 0)
+    {
+      nxsem_wait(&priv->txdmasem);
+    }
+
+  uart_xmitchars_dma(dev);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_dma_send
+ *
+ * Description:
+ *   Called (usually) from the interrupt level to start DMA transfer.
+ *   (Re-)Configures DMA Stream updating buffer and buffer length.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void up_dma_send(struct uart_dev_s *dev)
+{
+  struct stm32_dma_config_s txdmacfg;
+  struct up_dev_s *priv = (struct up_dev_s *)dev->priv;
+
+  /* We need to stop DMA before reconfiguration */
+
+  stm32_dmastop(priv->txdma);
+
+  /* Reset the number sent */
+
+  dev->dmatx.nbytes = 0;
+
+  /* Flush the contents of the TX buffer into physical memory */
+
+  up_clean_dcache((uintptr_t)dev->dmatx.buffer,
+                  (uintptr_t)dev->dmatx.buffer + dev->dmatx.length);
+
+  /* Is this a split transfer */
+
+  if (dev->dmatx.nbuffer)
+    {
+      /* Flush the contents of the next TX buffer into physical memory */
+
+      up_clean_dcache((uintptr_t)dev->dmatx.nbuffer,
+                      (uintptr_t)dev->dmatx.nbuffer + dev->dmatx.nlength);
+    }
+
+  /* Make use of setup function to update buffer and its length for next
+   * transfer
+   */
+
+  txdmacfg.paddr  = priv->usartbase + STM32_USART_TDR_OFFSET;
+  txdmacfg.maddr  = (uint32_t) dev->dmatx.buffer;
+  txdmacfg.ndata  = (size_t)  dev->dmatx.length;
+  txdmacfg.cfg1   = SERIAL_TXDMA_CONTROL_WORD;
+  txdmacfg.cfg2   = 0;
+  stm32_dmasetup(priv->txdma, &txdmacfg);
+
+  /* Start transmission with the callback on DMA completion */
+
+  stm32_dmastart(priv->txdma, up_dma_txcallback, (void *)priv, false);
+}
+#endif
+
+/****************************************************************************
+ * Name: up_send
+ *
+ * Description:
+ *   This method will send one byte on the USART
+ *
+ ****************************************************************************/
+
+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_TDR_OFFSET, (uint32_t)ch);
+}
+
+/****************************************************************************
+ * Name: up_dma_txint
+ *
+ * Description:
+ *   Call to enable or disable TX interrupts from the UART.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_TXDMA
+static void up_dma_txint(struct uart_dev_s *dev, bool enable)
+{
+  /* Nothing to do. */
+
+  /* In case of DMA transfer we do not want to make use of UART interrupts.
+   * Instead, we use DMA interrupts that are activated once during boot
+   * sequence. Furthermore we can use up_dma_txcallback() to handle staff at
+   * half DMA transfer or after transfer completion (depending configuration,
+   * see stm32_dmastart(...) ).
+   */
+}
+#endif
+
+/****************************************************************************
+ * Name: up_txint
+ *
  * Description:
  *   Call to enable or disable TX interrupts
  *
@@ -2134,6 +3567,44 @@ static bool up_txready(struct uart_dev_s *dev)
 }
 
 /****************************************************************************
+ * Name: up_dma_rxcallback
+ *
+ * Description:
+ *   This function checks the current DMA state and calls the generic
+ *   serial stack when bytes appear to be available.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+static void up_dma_rxcallback(DMA_HANDLE handle, uint8_t status, void *arg)
+{
+  struct up_dev_s *priv = (struct up_dev_s *)arg;
+
+  if (priv->rxenable && up_dma_rxavailable(&priv->dev))
+    {
+      uart_recvchars(&priv->dev);
+    }
+
+  /* Get the masked USART status word to check and clear error flags.
+   *
+   * When wake-up from low power mode was not fast enough, UART is resumed
+   * too late and sometimes exactly when character was coming over UART,
+   * resulting to frame error.
+   * If error flag is not cleared, Rx DMA will be stuck. Clearing errors
+   * will release Rx DMA.
+   */
+
+  priv->sr = up_serialin(priv, STM32_USART_ISR_OFFSET);
+
+  if ((priv->sr & (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE)) != 0)
+    {
+      up_serialout(priv, STM32_USART_ICR_OFFSET,
+                   (USART_ICR_NCF | USART_ICR_ORECF | USART_ICR_FECF));
+    }
+}
+#endif
+
+/****************************************************************************
  * Name: up_pm_notify
  *
  * Description:
@@ -2161,27 +3632,27 @@ static void up_pm_notify(struct pm_callback_s *cb, int 
domain,
 {
   switch (pmstate)
     {
-      case(PM_NORMAL):
+      case PM_NORMAL:
         {
-          /* Logic for PM_NORMAL goes here */
+          up_pm_setsuspend(false);
         }
         break;
 
-      case(PM_IDLE):
+      case PM_IDLE:
         {
-          /* Logic for PM_IDLE goes here */
+          up_pm_setsuspend(false);
         }
         break;
 
-      case(PM_STANDBY):
+      case PM_STANDBY:
         {
-          /* Logic for PM_STANDBY goes here */
+          up_pm_setsuspend(true);
         }
         break;
 
-      case(PM_SLEEP):
+      case PM_SLEEP:
         {
-          /* Logic for PM_SLEEP goes here */
+          up_pm_setsuspend(true);
         }
         break;
 
@@ -2231,8 +3702,77 @@ static void up_pm_notify(struct pm_callback_s *cb, int 
domain,
 static int up_pm_prepare(struct pm_callback_s *cb, int domain,
                          enum pm_state_e pmstate)
 {
+  int n;
+
   /* Logic to prepare for a reduced power state goes here. */
 
+  switch (pmstate)
+    {
+    case PM_NORMAL:
+    case PM_IDLE:
+      break;
+
+    case PM_STANDBY:
+    case PM_SLEEP:
+
+#ifdef SERIAL_HAVE_RXDMA
+      /* Flush Rx DMA buffers before checking state of serial device
+       * buffers.
+       */
+
+      stm32_serial_dma_poll();
+#endif
+
+      /* Check if any of the active ports have data pending on Tx/Rx
+       * buffers.
+       */
+
+      for (n = 0; n < STM32H7_NUSART + STM32H7_NUART; n++)
+        {
+          struct up_dev_s *priv = g_uart_devs[n];
+
+          if (!priv || !priv->initialized)
+            {
+              /* Not active, skip. */
+
+              continue;
+            }
+
+          if (priv->suspended)
+            {
+              /* Port already suspended, skip. */
+
+              continue;
+            }
+
+          if (priv->dev.isconsole)
+            {
+              /* Allow losing some debug traces. */
+
+              continue;
+            }
+
+          /* Check if port has data pending (Rx & Tx). */
+
+          if (priv->dev.xmit.head != priv->dev.xmit.tail)
+            {
+              return ERROR;
+            }
+
+          if (priv->dev.recv.head != priv->dev.recv.tail)
+            {
+              return ERROR;
+            }
+        }
+      break;
+
+    default:
+
+      /* Should not get here */
+
+      break;
+    }
+
   return OK;
 }
 #endif
@@ -2324,10 +3864,10 @@ void arm_serialinit(void)
   int ret;
 #endif
 
+#ifdef CONFIG_PM
   /* Register to receive power management callbacks */
 
-#ifdef CONFIG_PM
-  ret = pm_register(&g_serialcb);
+  ret = pm_register(&g_serialpm.pm_cb);
   DEBUGASSERT(ret == OK);
   UNUSED(ret);
 #endif
@@ -2346,6 +3886,11 @@ void arm_serialinit(void)
   minor = 1;
 #endif
 
+#if defined(SERIAL_HAVE_CONSOLE_RXDMA) || defined(SERIAL_HAVE_CONSOLE_TXDMA)
+  /* If we need to re-initialise the console to enable DMA do that here. */
+
+  up_dma_setup(&g_uart_devs[CONSOLE_UART - 1]->dev);
+#endif
 #endif /* CONSOLE_UART > 0 */
 
   /* Register all remaining USARTs */
@@ -2379,10 +3924,88 @@ void arm_serialinit(void)
 }
 
 /****************************************************************************
+ * Name: stm32_serial_dma_poll
+ *
+ * Description:
+ *   Checks receive DMA buffers for received bytes that have not accumulated
+ *   to the point where the DMA half/full interrupt has triggered.
+ *
+ *   This function should be called from a timer or other periodic context.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+void stm32_serial_dma_poll(void)
+{
+    irqstate_t flags;
+
+    flags = enter_critical_section();
+
+#ifdef CONFIG_USART1_RXDMA
+  if (g_usart1priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_usart1priv.rxdma, 0, &g_usart1priv);
+    }
+#endif
+
+#ifdef CONFIG_USART2_RXDMA
+  if (g_usart2priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_usart2priv.rxdma, 0, &g_usart2priv);
+    }
+#endif
+
+#ifdef CONFIG_USART3_RXDMA
+  if (g_usart3priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_usart3priv.rxdma, 0, &g_usart3priv);
+    }
+#endif
+
+#ifdef CONFIG_UART4_RXDMA
+  if (g_uart4priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_uart4priv.rxdma, 0, &g_uart4priv);
+    }
+#endif
+
+#ifdef CONFIG_UART5_RXDMA
+  if (g_uart5priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_uart5priv.rxdma, 0, &g_uart5priv);
+    }
+#endif
+
+#ifdef CONFIG_USART6_RXDMA
+  if (g_usart6priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_usart6priv.rxdma, 0, &g_usart6priv);
+    }
+#endif
+
+#ifdef CONFIG_UART7_RXDMA
+  if (g_uart7priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_uart7priv.rxdma, 0, &g_uart7priv);
+    }
+#endif
+
+#ifdef CONFIG_UART8_RXDMA
+  if (g_uart8priv.rxdma != NULL)
+    {
+      up_dma_rxcallback(g_uart8priv.rxdma, 0, &g_uart8priv);
+    }
+#endif
+
+  leave_critical_section(flags);
+}
+#endif
+
+/****************************************************************************
  * Name: up_putc
  *
  * Description:
- *   Provide priority, low-level access to support OS debug  writes
+ *   Provide priority, low-level access to support OS debug writes
  *
  ****************************************************************************/
 
diff --git a/arch/arm/src/stm32h7/stm32_uart.h 
b/arch/arm/src/stm32h7/stm32_uart.h
index d4e48c6..8a53fa8 100644
--- a/arch/arm/src/stm32h7/stm32_uart.h
+++ b/arch/arm/src/stm32h7/stm32_uart.h
@@ -168,6 +168,268 @@
 #  undef HAVE_CONSOLE
 #endif
 
+#if !defined(CONFIG_ARCH_DMA)
+#  undef CONFIG_USART1_RXDMA
+#  undef CONFIG_USART1_TXDMA
+#  undef CONFIG_USART2_RXDMA
+#  undef CONFIG_USART2_TXDMA
+#  undef CONFIG_USART3_RXDMA
+#  undef CONFIG_USART3_TXDMA
+#  undef CONFIG_UART4_RXDMA
+#  undef CONFIG_UART4_TXDMA
+#  undef CONFIG_UART5_RXDMA
+#  undef CONFIG_UART5_TXDMA
+#  undef CONFIG_USART6_RXDMA
+#  undef CONFIG_USART6_TXDMA
+#  undef CONFIG_UART7_RXDMA
+#  undef CONFIG_UART7_TXDMA
+#  undef CONFIG_UART8_RXDMA
+#  undef CONFIG_UART8_TXDMA
+#endif
+
+/* Disable the DMA configuration on all unused USARTs */
+
+#ifndef CONFIG_USART1_SERIALDRIVER
+#  undef CONFIG_USART1_RXDMA
+#  undef CONFIG_USART1_TXDMA
+#endif
+
+#ifndef CONFIG_USART2_SERIALDRIVER
+#  undef CONFIG_USART2_RXDMA
+#  undef CONFIG_USART2_TXDMA
+#endif
+
+#ifndef CONFIG_USART3_SERIALDRIVER
+#  undef CONFIG_USART3_RXDMA
+#  undef CONFIG_USART3_TXDMA
+#endif
+
+#ifndef CONFIG_UART4_SERIALDRIVER
+#  undef CONFIG_UART4_RXDMA
+#  undef CONFIG_UART4_TXDMA
+#endif
+
+#ifndef CONFIG_UART5_SERIALDRIVER
+#  undef CONFIG_UART5_RXDMA
+#  undef CONFIG_UART5_TXDMA
+#endif
+
+#ifndef CONFIG_USART6_SERIALDRIVER
+#  undef CONFIG_USART6_RXDMA
+#  undef CONFIG_USART6_TXDMA
+#endif
+
+#ifndef CONFIG_UART7_SERIALDRIVER
+#  undef CONFIG_UART7_RXDMA
+#  undef CONFIG_UART7_TXDMA
+#endif
+
+#ifndef CONFIG_UART8_SERIALDRIVER
+#  undef CONFIG_UART8_RXDMA
+#  undef CONFIG_UART8_TXDMA
+#endif
+
+/* Is DMA available on any (enabled) U[S]ART? */
+
+#undef SERIAL_HAVE_RXDMA
+#if defined(CONFIG_USART1_RXDMA) || defined(CONFIG_USART2_RXDMA) || \
+    defined(CONFIG_USART3_RXDMA) || defined(CONFIG_UART4_RXDMA)  || \
+    defined(CONFIG_UART5_RXDMA)  || defined(CONFIG_USART6_RXDMA) || \
+    defined(CONFIG_UART7_RXDMA)  || defined(CONFIG_UART8_RXDMA)
+#  define SERIAL_HAVE_RXDMA 1
+#endif
+
+/* Is TX DMA available on any (enabled)  U[S]ART?  */
+
+#undef SERIAL_HAVE_TXDMA
+#if defined(CONFIG_USART1_TXDMA) || defined(CONFIG_USART2_TXDMA) || \
+  defined(CONFIG_USART3_TXDMA) || defined(CONFIG_UART4_TXDMA)  ||   \
+  defined(CONFIG_UART5_TXDMA)  || defined(CONFIG_USART6_TXDMA) ||   \
+  defined(CONFIG_UART7_TXDMA)  || defined(CONFIG_UART8_TXDMA)
+#  define SERIAL_HAVE_TXDMA 1
+#endif
+
+/* Is RX DMA used on the console UART? */
+
+#undef SERIAL_HAVE_CONSOLE_RXDMA
+#if defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_USART1_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_USART2_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE) && defined(CONFIG_USART3_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_UART4_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_UART5_SERIAL_CONSOLE) && defined(CONFIG_UART5_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_USART6_SERIAL_CONSOLE) && defined(CONFIG_USART6_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_UART7_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#elif defined(CONFIG_UART8_SERIAL_CONSOLE) && defined(CONFIG_UART8_RXDMA)
+#  define SERIAL_HAVE_CONSOLE_RXDMA 1
+#endif
+
+/* Is TX DMA used on the console UART? */
+
+#undef SERIAL_HAVE_CONSOLE_TXDMA
+#if defined(CONFIG_USART1_SERIAL_CONSOLE) && defined(CONFIG_USART1_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_USART2_SERIAL_CONSOLE) && defined(CONFIG_USART2_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_USART3_SERIAL_CONSOLE) && defined(CONFIG_USART3_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_UART4_SERIAL_CONSOLE) && defined(CONFIG_UART4_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_UART5_SERIAL_CONSOLE) && defined(CONFIG_UART5_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_USART6_SERIAL_CONSOLE) && defined(CONFIG_USART6_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_UART7_SERIAL_CONSOLE) && defined(CONFIG_UART7_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#elif defined(CONFIG_UART8_SERIAL_CONSOLE) && defined(CONFIG_UART8_TXDMA)
+#  define SERIAL_HAVE_CONSOLE_TXDMA 1
+#endif
+
+/* Is RX DMA used on all (enabled) USARTs */
+
+#define SERIAL_HAVE_ONLY_RXDMA 1
+#if defined(CONFIG_STM32H7_USART1) && !defined(CONFIG_USART1_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_USART2) && !defined(CONFIG_USART2_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_USART3) && !defined(CONFIG_USART3_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_UART4) && !defined(CONFIG_UART4_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_UART5) && !defined(CONFIG_UART5_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_USART6) && !defined(CONFIG_USART6_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_UART7) && !defined(CONFIG_UART7_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#elif defined(CONFIG_STM32H7_UART8) && !defined(CONFIG_UART8_RXDMA)
+#  undef SERIAL_HAVE_ONLY_RXDMA
+#endif
+
+/* Is TX DMA used on all (enabled) USARTs */
+
+#define SERIAL_HAVE_ONLY_TXDMA 1
+#if defined(CONFIG_STM32H7_USART1) && !defined(CONFIG_USART1_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_USART2) && !defined(CONFIG_USART2_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_USART3) && !defined(CONFIG_USART3_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_UART4) && !defined(CONFIG_UART4_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_UART5) && !defined(CONFIG_UART5_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_USART6) && !defined(CONFIG_USART6_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_UART7) && !defined(CONFIG_UART7_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#elif defined(CONFIG_STM32H7_UART8) && !defined(CONFIG_UART8_TXDMA)
+#  undef SERIAL_HAVE_ONLY_TXDMA
+#endif
+
+#undef SERIAL_HAVE_ONLY_DMA
+#if defined(SERIAL_HAVE_ONLY_RXDMA) && defined(SERIAL_HAVE_ONLY_TXDMA)
+#  define SERIAL_HAVE_ONLY_DMA 1
+#endif
+
+/* No DMA ops */
+
+#undef SERIAL_HAVE_NODMA_OPS
+#if defined(CONFIG_STM32H7_USART1) && !defined(CONFIG_USART1_RXDMA) &&   \
+    !defined(CONFIG_USART1_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_USART2) && !defined(CONFIG_USART2_RXDMA) && \
+    !defined(CONFIG_USART2_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_USART3) && !defined(CONFIG_USART3_RXDMA) && \
+    !defined(CONFIG_USART3_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_UART4) && !defined(CONFIG_UART4_RXDMA) &&  \
+    !defined(CONFIG_UART4_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_UART5) && !defined(CONFIG_UART5_RXDMA) &&  \
+    !defined(CONFIG_UART5_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_USART6) && !defined(CONFIG_USART6_RXDMA) && \
+    !defined(CONFIG_USART6_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_UART7) && !defined(CONFIG_UART7_RXDMA) &&  \
+    !defined(CONFIG_UART7_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#elif defined(CONFIG_STM32H7_UART8) && !defined(CONFIG_UART8_RXDMA) &&  \
+    !defined(CONFIG_UART8_TXDMA)
+#  define SERIAL_HAVE_NODMA_OPS
+#endif
+
+/* RX+TX DMA ops */
+
+#undef SERIAL_HAVE_RXTXDMA_OPS
+#if defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_UART4_RXDMA) && defined(CONFIG_UART4_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_UART5_RXDMA) && defined(CONFIG_UART5_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_UART7_RXDMA) && defined(CONFIG_UART7_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#elif defined(CONFIG_UART8_RXDMA) && defined(CONFIG_UART8_TXDMA)
+#  define SERIAL_HAVE_RXTXDMA_OPS
+#endif
+
+/* TX DMA ops */
+
+#undef SERIAL_HAVE_TXDMA_OPS
+#if !defined(CONFIG_USART1_RXDMA) && defined(CONFIG_USART1_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_USART2_RXDMA) && defined(CONFIG_USART2_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_USART3_RXDMA) && defined(CONFIG_USART3_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_UART4_RXDMA) && defined(CONFIG_UART4_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_UART5_RXDMA) && defined(CONFIG_UART5_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_USART6_RXDMA) && defined(CONFIG_USART6_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_UART7_RXDMA) && defined(CONFIG_UART7_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#elif !defined(CONFIG_UART8_RXDMA) && defined(CONFIG_UART8_TXDMA)
+#  define SERIAL_HAVE_TXDMA_OPS
+#endif
+
+/* RX DMA ops */
+
+#undef SERIAL_HAVE_RXDMA_OPS
+#if defined(CONFIG_USART1_RXDMA) && !defined(CONFIG_USART1_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_USART2_RXDMA) && !defined(CONFIG_USART2_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_USART3_RXDMA) && !defined(CONFIG_USART3_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_UART4_RXDMA) && !defined(CONFIG_UART4_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_UART5_RXDMA) && !defined(CONFIG_UART5_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_USART6_RXDMA) && !defined(CONFIG_USART6_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_UART7_RXDMA) && !defined(CONFIG_UART7_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#elif defined(CONFIG_UART8_RXDMA) && !defined(CONFIG_UART8_TXDMA)
+#  define SERIAL_HAVE_RXDMA_OPS
+#endif
+
 /* Is RS-485 used? */
 
 #if defined(CONFIG_USART1_RS485) || defined(CONFIG_USART2_RS485) || \
@@ -180,7 +442,7 @@
 #ifdef HAVE_RS485
 #  define USART_CR1_USED_INTS    (USART_CR1_RXNEIE | USART_CR1_TXEIE | 
USART_CR1_PEIE | USART_CR1_TCIE)
 #else
-#  define USART_CR1_USED_INTS    (USART_CR1_RXNEIE | USART_CR1_TXEIE | 
USART_CR1_PEIE)
+#  define USART_CR1_USED_INTS    (USART_CR1_RXNEIE | USART_CR1_TXEIE | 
USART_CR1_PEIE | USART_CR1_IDLEIE)
 #endif
 
 /****************************************************************************
@@ -207,6 +469,23 @@ extern "C"
  ****************************************************************************/
 
 /****************************************************************************
+ * Name: stm32_serial_dma_poll
+ *
+ * Description:
+ *   Must be called periodically if any STM32 UART is configured for DMA.
+ *   The DMA callback is triggered for each fifo size/2 bytes, but this can
+ *   result in some bytes being transferred but not collected if the incoming
+ *   data is not a whole multiple of half the FIFO size.
+ *
+ *   May be safely called from either interrupt or thread context.
+ *
+ ****************************************************************************/
+
+#ifdef SERIAL_HAVE_RXDMA
+void stm32_serial_dma_poll(void);
+#endif
+
+/****************************************************************************
  * Name: stm32_serial_get_uart
  *
  * Description:

Reply via email to