You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nuttx.apache.org by ag...@apache.org on 2020/06/06 18:17:21 UTC

[incubator-nuttx] branch master updated: stm32h7:DMA Add BDMA support

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

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


The following commit(s) were added to refs/heads/master by this push:
     new a793369  stm32h7:DMA Add BDMA support
a793369 is described below

commit a79336981582043d760590b5f8de95b00d474f7e
Author: David Sidrane <Da...@NscDg.com>
AuthorDate: Fri Jun 5 09:03:32 2020 -0700

    stm32h7:DMA Add BDMA support
    
    Apply suggestions from code review
    
    Co-authored-by: Mateusz Szafoni <ra...@gmail.com>
---
 arch/arm/src/stm32h7/hardware/stm32_bdma.h |  40 +++--
 arch/arm/src/stm32h7/hardware/stm32_dma.h  |  18 ++-
 arch/arm/src/stm32h7/stm32_dma.c           | 229 ++++++++++++++++++++++++++---
 3 files changed, 247 insertions(+), 40 deletions(-)

diff --git a/arch/arm/src/stm32h7/hardware/stm32_bdma.h b/arch/arm/src/stm32h7/hardware/stm32_bdma.h
index b989a46..56fc68c 100644
--- a/arch/arm/src/stm32h7/hardware/stm32_bdma.h
+++ b/arch/arm/src/stm32h7/hardware/stm32_bdma.h
@@ -49,17 +49,20 @@
 
 /* Register Offsets *****************************************************************/
 
-#define STM32_BDMA_OFFSET(x)        (0x08+0x14*(x))
 #define STM32_BDMA_ISR_OFFSET       0x0000 /* BDMA interrupt status register */
 #define STM32_BDMA_IFCR_OFFSET      0x0004 /* BDMA interrupt flag clear register */
 
-#define STM32_BDMACH_CCR_OFFSET     0x0008
-#define STM32_BDMACH_CNDTR_OFFSET   0x000C
-#define STM32_BDMACH_CPAR_OFFSET    0x0010
-#define STM32_BDMACH_CM0AR_OFFSET   0x0014
-#define STM32_BDMACH_CM1AR_OFFSET   0x0018
+#define STM32_BDMACH_CCR_OFFSET     0x0008 /* BDMA channel x configuration register */
+#define STM32_BDMACH_CNDTR_OFFSET   0x000C /* BDMA channel x number of data to transfer register */
+#define STM32_BDMACH_CPAR_OFFSET    0x0010 /* BDMA channel x peripheral address register */
+#define STM32_BDMACH_CM0AR_OFFSET   0x0014 /* BDMA channel x memory 0 address register */
+#define STM32_BDMACH_CM1AR_OFFSET   0x0018 /* BDMA channel x memory 1 address register */
 
-#define STM32_BDMA_CCRX_OFFSET(x)   (0x0008+(x*0x0014)) /* BDMA channel x configuration register */
+#define STM32_BDMA_SPACING          0x14
+#define STM32_BDMA_OFFSET(x)        (STM32_BDMA_SPACING * (x))
+
+#define STM32_BDMA_CCRX_OFFSET(x)   (STM32_BDMACH_CCR_OFFSET + \
+                                    STM32_BDMA_OFFSET(x))
 #define STM32_BDMA_CCR0_OFFSET      STM32_BDMA_CCRX_OFFSET(0)
 #define STM32_BDMA_CCR1_OFFSET      STM32_BDMA_CCRX_OFFSET(1)
 #define STM32_BDMA_CCR2_OFFSET      STM32_BDMA_CCRX_OFFSET(2)
@@ -69,7 +72,8 @@
 #define STM32_BDMA_CCR6_OFFSET      STM32_BDMA_CCRX_OFFSET(6)
 #define STM32_BDMA_CCR7_OFFSET      STM32_BDMA_CCRX_OFFSET(7)
 
-#define STM32_BDMA_CNDTRX_OFFSET(x) (0x000C+(x*0x0014)) /* BDMA channel x number of data to transfer register */
+#define STM32_BDMA_CNDTRX_OFFSET(x) (STM32_BDMACH_CNDTR_OFFSET + \
+                                    STM32_BDMA_OFFSET(x))
 #define STM32_BDMA_CNDTR0_OFFSET    STM32_BDMA_CNDTRX_OFFSET(0)
 #define STM32_BDMA_CNDTR1_OFFSET    STM32_BDMA_CNDTRX_OFFSET(1)
 #define STM32_BDMA_CNDTR2_OFFSET    STM32_BDMA_CNDTRX_OFFSET(2)
@@ -79,7 +83,8 @@
 #define STM32_BDMA_CNDTR6_OFFSET    STM32_BDMA_CNDTRX_OFFSET(6)
 #define STM32_BDMA_CNDTR7_OFFSET    STM32_BDMA_CNDTRX_OFFSET(7)
 
-#define STM32_BDMA_CPARX_OFFSET(x)  (0x0010+(x*0x0014)) /* BDMA channel x peripheral address register */
+#define STM32_BDMA_CPARX_OFFSET(x)  (STM32_BDMACH_CPAR_OFFSET + \
+                                    STM32_BDMA_OFFSET(x))
 #define STM32_BDMA_CPAR0_OFFSET     STM32_BDMA_CPARX_OFFSET(0)
 #define STM32_BDMA_CPAR1_OFFSET     STM32_BDMA_CPARX_OFFSET(1)
 #define STM32_BDMA_CPAR2_OFFSET     STM32_BDMA_CPARX_OFFSET(2)
@@ -89,7 +94,8 @@
 #define STM32_BDMA_CPAR6_OFFSET     STM32_BDMA_CPARX_OFFSET(6)
 #define STM32_BDMA_CPAR7_OFFSET     STM32_BDMA_CPARX_OFFSET(7)
 
-#define STM32_BDMA_CM0ARX_OFFSET(x) (0x0014+(x*0x0014)) /* BDMA channel x memory 0 address register */
+#define STM32_BDMA_CM0ARX_OFFSET(x) (STM32_BDMACH_CM0AR_OFFSET + \
+                                    STM32_BDMA_OFFSET(x))
 #define STM32_BDMA_CM0AR0_OFFSET    STM32_BDMA_CM0ARX_OFFSET(0)
 #define STM32_BDMA_CM0AR1_OFFSET    STM32_BDMA_CM0ARX_OFFSET(1)
 #define STM32_BDMA_CM0AR2_OFFSET    STM32_BDMA_CM0ARX_OFFSET(2)
@@ -99,7 +105,8 @@
 #define STM32_BDMA_CM0AR6_OFFSET    STM32_BDMA_CM0ARX_OFFSET(6)
 #define STM32_BDMA_CM0AR7_OFFSET    STM32_BDMA_CM0ARX_OFFSET(7)
 
-#define STM32_BDMA_CM1ARX_OFFSET(x) (0x0018+(x*0x0014)) /* BDMA channel x memory 1 address register */
+#define STM32_BDMA_CM1ARX_OFFSET(x) (STM32_BDMACH_CM1AR_OFFSET + \
+                                    STM32_BDMA_OFFSET(x))
 #define STM32_BDMA_CM1AR0_OFFSET    STM32_BDMA_CM1ARX_OFFSET(0)
 #define STM32_BDMA_CM1AR1_OFFSET    STM32_BDMA_CM1ARX_OFFSET(1)
 #define STM32_BDMA_CM1AR2_OFFSET    STM32_BDMA_CM1ARX_OFFSET(2)
@@ -172,6 +179,7 @@
 #define BDMA_CHAN_TCIF             (1 << 1) /* Bit 1: Transfer complete flag */
 #define BDMA_CHAN_HTIF             (1 << 2) /* Bit 2: half transfer complete flag */
 #define BDMA_CHAN_TEIF             (1 << 3) /* Bit 3: Transfer error flag */
+#define BDMA_CCR_ALLINTS           (BDMA_CHAN_TCIF | BDMA_CHAN_HTIF | BDMA_CHAN_TEIF)
 
 /* BDMA interrupt status register */
 
@@ -240,20 +248,20 @@
 #  define BDMA_CCR_PSIZE_8BITS     (0 << BDMA_CCR_PSIZE_SHIFT) /* 00: 8-bits */
 #  define BDMA_CCR_PSIZE_16BITS    (1 << BDMA_CCR_PSIZE_SHIFT) /* 01: 16-bits */
 #  define BDMA_CCR_PSIZE_32BITS    (2 << BDMA_CCR_PSIZE_SHIFT) /* 10: 32-bits */
-#define BDMA_CCR_MSIZE_SHIFT       (10)      /* Bits 10-11: Memory size*/
+#define BDMA_CCR_MSIZE_SHIFT       (10)                        /* Bits 10-11: Memory size*/
 #define BDMA_CCR_MSIZE_MASK        (3 << BDMA_CCR_MSIZE_SHIFT)
 #  define BDMA_CCR_MSIZE_8BITS     (0 << BDMA_CCR_MSIZE_SHIFT) /* 00: 8-bits */
 #  define BDMA_CCR_MSIZE_16BITS    (1 << BDMA_CCR_MSIZE_SHIFT) /* 01: 16-bits */
 #  define BDMA_CCR_MSIZE_32BITS    (2 << BDMA_CCR_MSIZE_SHIFT) /* 10: 32-bits */
-#define BDMA_CCR_PL_SHIFT          (12)      /* Bits 12-13: Priority level */
+#define BDMA_CCR_PL_SHIFT          (12)                        /* Bits 12-13: Priority level */
 #define BDMA_CCR_PL_MASK           (3 << BDMA_CCR_PL_SHIFT)
 #  define BDMA_CCR_PRILO           (0 << BDMA_CCR_PL_SHIFT) /* 00: Low */
 #  define BDMA_CCR_PRIMED          (1 << BDMA_CCR_PL_SHIFT) /* 01: Medium */
 #  define BDMA_CCR_PRIHI           (2 << BDMA_CCR_PL_SHIFT) /* 10: High */
 #  define BDMA_CCR_PRIVERYHI       (3 << BDMA_CCR_PL_SHIFT) /* 11: Very high */
-#define BDMA_CCR_M2M               (1 << 14) /* Bit 14: Memory-to-memory mode */
-#define BDMA_CCR_DBM               (1 << 15) /* Bit 15: dobule buffer mode*/
-#define BDMA_CCR_CT                (1 << 16) /* Bit 16: Current target */
+#define BDMA_CCR_M2M               (1 << 14)                /* Bit 14: Memory-to-memory mode */
+#define BDMA_CCR_DBM               (1 << 15)                /* Bit 15: dobule buffer mode*/
+#define BDMA_CCR_CT                (1 << 16)                /* Bit 16: Current target */
 
 /* BDMA channel x number of data to transfer register */
 
diff --git a/arch/arm/src/stm32h7/hardware/stm32_dma.h b/arch/arm/src/stm32h7/hardware/stm32_dma.h
index 94d7ed7..ffb672b 100644
--- a/arch/arm/src/stm32h7/hardware/stm32_dma.h
+++ b/arch/arm/src/stm32h7/hardware/stm32_dma.h
@@ -47,7 +47,7 @@
  * Pre-processor Definitions
  ************************************************************************************/
 
-/* 2 DMA controllers + 1 MDMA + 1 BDMA*/
+/* 2 DMA controllers + 1 MDMA + 1 BDMA */
 
 #define MDMA                      (0)
 #define DMA1                      (1)
@@ -275,7 +275,7 @@
 #define DMA_STREAM_HTIF_BIT       (1 << 4)  /* Bit 4: Stream Half Transfer flag */
 #define DMA_STREAM_TCIF_BIT       (1 << 5)  /* Bit 5: Stream Transfer Complete flag */
 
-/* DMA interrupt status register and interrupt flag clear register field definitions */
+/* DMA interrupt status and interrupt clear register field definitions */
 
 #define DMA_INT_STREAM0_SHIFT     (0)       /* Bits 0-5:   DMA Stream 0 interrupt */
 #define DMA_INT_STREAM0_MASK      (DMA_STREAM_MASK <<  DMA_INT_STREAM0_SHIFT)
@@ -308,6 +308,7 @@
 #  define DMA_SCR_DIR_P2M         (0 << DMA_SCR_DIR_SHIFT) /* 00: Peripheral-to-memory */
 #  define DMA_SCR_DIR_M2P         (1 << DMA_SCR_DIR_SHIFT) /* 01: Memory-to-peripheral */
 #  define DMA_SCR_DIR_M2M         (2 << DMA_SCR_DIR_SHIFT) /* 10: Memory-to-memory */
+
 #define DMA_SCR_CIRC              (1 << 8)  /* Bit 8:  Circular mode */
 #define DMA_SCR_PINC              (1 << 9)  /* Bit 9:  Peripheral increment mode */
 #define DMA_SCR_MINC              (1 << 10) /* Bit 10: Memory increment mode */
@@ -316,11 +317,13 @@
 #  define DMA_SCR_PSIZE_8BITS     (0 << DMA_SCR_PSIZE_SHIFT) /* 00: 8-bits */
 #  define DMA_SCR_PSIZE_16BITS    (1 << DMA_SCR_PSIZE_SHIFT) /* 01: 16-bits */
 #  define DMA_SCR_PSIZE_32BITS    (2 << DMA_SCR_PSIZE_SHIFT) /* 10: 32-bits */
+
 #define DMA_SCR_MSIZE_SHIFT       (13)      /* Bits 13-14: Memory size */
 #define DMA_SCR_MSIZE_MASK        (3 << DMA_SCR_MSIZE_SHIFT)
 #  define DMA_SCR_MSIZE_8BITS     (0 << DMA_SCR_MSIZE_SHIFT) /* 00: 8-bits */
 #  define DMA_SCR_MSIZE_16BITS    (1 << DMA_SCR_MSIZE_SHIFT) /* 01: 16-bits */
 #  define DMA_SCR_MSIZE_32BITS    (2 << DMA_SCR_MSIZE_SHIFT) /* 10: 32-bits */
+
 #define DMA_SCR_PINCOS            (1 << 15) /* Bit 15: Peripheral increment offset size */
 #define DMA_SCR_PL_SHIFT          (16)      /* Bits 16-17: Stream Priority level */
 #define DMA_SCR_PL_MASK           (3 << DMA_SCR_PL_SHIFT)
@@ -328,6 +331,7 @@
 #  define DMA_SCR_PRIMED          (1 << DMA_SCR_PL_SHIFT) /* 01: Medium */
 #  define DMA_SCR_PRIHI           (2 << DMA_SCR_PL_SHIFT) /* 10: High */
 #  define DMA_SCR_PRIVERYHI       (3 << DMA_SCR_PL_SHIFT) /* 11: Very high */
+
 #define DMA_SCR_DBM               (1 << 18) /* Bit 15: Double buffer mode */
 #define DMA_SCR_CT                (1 << 19) /* Bit 19: Current target */
                                             /* Bit 20: Reserved */
@@ -337,13 +341,14 @@
 #  define DMA_SCR_PBURST_INCR4    (1 << DMA_SCR_PBURST_SHIFT) /* 01: Incremental burst of 4 beats */
 #  define DMA_SCR_PBURST_INCR8    (2 << DMA_SCR_PBURST_SHIFT) /* 10: Incremental burst of 8 beats */
 #  define DMA_SCR_PBURST_INCR16   (3 << DMA_SCR_PBURST_SHIFT) /* 11: Incremental burst of 16 beats */
+
 #define DMA_SCR_MBURST_SHIFT      (23)      /* Bits 23-24: Memory burst transfer configuration */
 #define DMA_SCR_MBURST_MASK       (3 << DMA_SCR_MBURST_SHIFT)
 #  define DMA_SCR_MBURST_SINGLE   (0 << DMA_SCR_MBURST_SHIFT) /* 00: Single transfer */
 #  define DMA_SCR_MBURST_INCR4    (1 << DMA_SCR_MBURST_SHIFT) /* 01: Incremental burst of 4 beats */
 #  define DMA_SCR_MBURST_INCR8    (2 << DMA_SCR_MBURST_SHIFT) /* 10: Incremental burst of 8 beats */
 #  define DMA_SCR_MBURST_INCR16   (3 << DMA_SCR_MBURST_SHIFT) /* 11: Incremental burst of 16 beats */
-                                            /* Bits 25-31: Reserved */
+                                                              /* Bits 25-31: Reserved */
 
 #define DMA_SCR_ALLINTS           (DMA_SCR_DMEIE|DMA_SCR_TEIE|DMA_SCR_HTIE|DMA_SCR_TCIE)
 
@@ -360,6 +365,7 @@
 #  define DMA_SFCR_FTH_HALF       (1 << DMA_SFCR_FTH_SHIFT) /* 1/2 full FIFO */
 #  define DMA_SFCR_FTH_3QUARTER   (2 << DMA_SFCR_FTH_SHIFT) /* 3/4 full FIFO */
 #  define DMA_SFCR_FTH_FULL       (3 << DMA_SFCR_FTH_SHIFT) /* full FIFO */
+
 #define DMA_SFCR_DMDIS            (1 << 2)  /* Bit 2:  Direct mode disable */
 #define DMA_SFCR_FS_SHIFT         (3)       /* Bits 3-5: FIFO status */
 #define DMA_SFCR_FS_MASK          (7 << DMA_SFCR_FS_SHIFT)
@@ -369,8 +375,8 @@
 #  define DMA_SFCR_FS_ALMOSTFULL  (3 << DMA_SFCR_FS_SHIFT) /* 3/4 = fifo_level < full */
 #  define DMA_SFCR_FS_EMPTY       (4 << DMA_SFCR_FS_SHIFT) /* FIFO is empty */
 #  define DMA_SFCR_FS_FULL        (5 << DMA_SFCR_FS_SHIFT) /* FIFO is full */
-                                            /* Bit 6:  Reserved */
-#define DMA_SFCR_FEIE             (1 << 7)  /* Bit 7:  FIFO error interrupt enable */
-                                            /* Bits 8-31: Reserved */
+                                                           /* Bit 6:  Reserved */
+#define DMA_SFCR_FEIE             (1 << 7)                 /* Bit 7:  FIFO error interrupt enable */
+                                                           /* Bits 8-31: Reserved */
 
 #endif /* __ARCH_ARM_SRC_STM32H7_HARDWARE_STM32_DMA_H */
diff --git a/arch/arm/src/stm32h7/stm32_dma.c b/arch/arm/src/stm32h7/stm32_dma.c
index bfa4f0d..80d4ec1 100644
--- a/arch/arm/src/stm32h7/stm32_dma.c
+++ b/arch/arm/src/stm32h7/stm32_dma.c
@@ -1381,8 +1381,8 @@ static void stm32_sdma_start(DMA_HANDLE handle, dma_callback_t callback,
   DMA_CHANNEL dmachan = (DMA_CHANNEL)handle;
   uint32_t scr = 0;
 
-  DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2);
   DEBUGASSERT(handle != NULL);
+  DEBUGASSERT(dmachan->ctrl == DMA1 || dmachan->ctrl == DMA2);
 
   /* Save the callback info.  This will be invoked when the DMA completes */
 
@@ -1714,12 +1714,23 @@ static void stm32_sdma_dump(DMA_HANDLE handle, const char *msg)
 
 static void stm32_bdma_disable(DMA_CHANNEL dmachan)
 {
-  DMA_CHANNEL dmachan    = (DMA_CHANNEL)handle;
-  uint8_t     controller = dmachan->ctrl;
+  uint32_t regval = 0;
 
-  DEBUGASSERT(controller == BDMA);
+  DEBUGASSERT(dmachan->ctrl == BDMA);
+  DEBUGASSERT(dmachan->chan < BDMA_NCHAN);
+
+  /* Disable all interrupts at the DMA controller */
+
+  regval = dmachan_getreg(dmachan, STM32_BDMACH_CCR_OFFSET);
+  regval &= ~BDMA_CCR_ALLINTS;
+
+  /* Disable the DMA stream */
+
+  regval &= ~BDMA_CCR_EN;
+  dmachan_putreg(dmachan, STM32_BDMACH_CCR_OFFSET, regval);
 
-#warning stm32_bdma_disable not implemented
+  dmabase_putreg(dmachan, STM32_BDMA_IFCR_OFFSET,
+                   (BDMA_CHAN_MASK << dmachan->shift));
 }
 
 /****************************************************************************
@@ -1732,7 +1743,66 @@ static void stm32_bdma_disable(DMA_CHANNEL dmachan)
 
 static int stm32_bdma_interrupt(int irq, void *context, FAR void *arg)
 {
-#warning stm32_bdma_interrupt not implemented
+  DMA_CHANNEL dmachan     = NULL;
+  uint32_t    status      = 0;
+  uint32_t    scrstatus   = 0;
+  uint8_t     stream      = irq - STM32_IRQ_BDMACH1;
+  uint8_t     controller  = BDMA;
+
+  /* Get the channel structure from the stream and controller numbers */
+
+  dmachan = stm32_dma_channel_get(stream, controller);
+
+  /* Get the interrupt status for this stream */
+
+  status = (dmabase_getreg(dmachan, STM32_BDMA_ISR_OFFSET) >> dmachan->shift)
+            & BDMA_CHAN_MASK;
+
+  dmabase_putreg(dmachan, STM32_BDMA_IFCR_OFFSET,
+                 (status << dmachan->shift));
+
+  /* Invoke the callback */
+
+  if (dmachan->callback)
+    {
+      /* Map to the SDMA status */
+
+      scrstatus  = (status & BDMA_CHAN_TEIF) ? DMA_STREAM_FEIF_BIT : 0;
+      scrstatus |= (status & BDMA_CHAN_TCIF) ? DMA_STREAM_TCIF_BIT : 0;
+      scrstatus |= (status & BDMA_CHAN_HTIF) ? DMA_STREAM_HTIF_BIT : 0;
+      dmachan->callback(dmachan, scrstatus, dmachan->arg);
+    }
+
+  return OK;
+}
+
+/****************************************************************************
+ * Name: stm32_sdma_scr_2_bdma_ccr
+ *
+ * Description:
+ *   Maps the DMA SCR bits to the BDMA CCR bits
+ *
+ ****************************************************************************/
+
+static inline int32_t stm32_sdma_scr_2_bdma_ccr(int32_t scr)
+{
+  uint32_t ccr = 0;
+  ccr |= (scr & DMA_SCR_CT) ? BDMA_CCR_CT : 0;
+  ccr |= (scr & DMA_SCR_DBM) ? BDMA_CCR_DBM : 0;
+  ccr |= (scr & DMA_SCR_PL_MASK) >> (DMA_SCR_PL_SHIFT - BDMA_CCR_PRILO);
+  ccr |= (scr & DMA_SCR_MSIZE_MASK) >>
+               (DMA_SCR_MSIZE_SHIFT - BDMA_CCR_MSIZE_SHIFT);
+  ccr |= (scr & DMA_SCR_PSIZE_MASK) >>
+               (DMA_SCR_PSIZE_SHIFT - BDMA_CCR_PSIZE_SHIFT);
+  ccr |= (scr & DMA_SCR_MINC) ? BDMA_CCR_MINC : 0;
+  ccr |= (scr & DMA_SCR_PINC) ? BDMA_CCR_PINC : 0;
+  ccr |= (scr & DMA_SCR_CIRC) ? BDMA_CCR_CIRC : 0;
+  ccr |= (scr & DMA_SCR_DIR_M2P) ? BDMA_CCR_DIR : 0;
+  ccr |= (scr & DMA_SCR_DIR_M2M) ? BDMA_CCR_M2M : 0;
+  ccr |= (scr & DMA_SCR_TCIE) ? BDMA_CCR_TCIE : 0;
+  ccr |= (scr & DMA_SCR_HTIE) ? BDMA_CCR_HTIE : 0;
+  ccr |= (scr & DMA_SCR_TEIE) ? BDMA_CCR_TEIE : 0;
+  return ccr;
 }
 
 /****************************************************************************
@@ -1746,11 +1816,89 @@ static int stm32_bdma_interrupt(int irq, void *context, FAR void *arg)
 static void stm32_bdma_setup(DMA_HANDLE handle, FAR stm32_dmacfg_t *cfg)
 {
   DMA_CHANNEL dmachan    = (DMA_CHANNEL)handle;
-  uint8_t     controller = dmachan->ctrl;
+  uint32_t    regval     = 0;
+  uint32_t    scr        = cfg->cfg1;
+  uint32_t    ccr        = 0;
 
-  DEBUGASSERT(controller == BDMA);
+  DEBUGASSERT(handle != NULL);
+  DEBUGASSERT(dmachan->ctrl == BDMA);
+
+  dmainfo("paddr: %08x maddr: %08x ndata: %d scr: %08x\n",
+          cfg->paddr, cfg->maddr, cfg->ndata, cfg->cfg1);
+
+#ifdef CONFIG_STM32H7_DMACAPABLE
+  DEBUGASSERT(stm32_bdma_capable(cfg));
+#endif
+
+  /* "If the stream is enabled, disable it by resetting the EN bit in the
+   * DMA_SxCR register, then read this bit in order to confirm that there is
+   * no ongoing stream operation. Writing this bit to 0 is not immediately
+   * effective since it is actually written to 0 once all the current
+   * transfers have finished. When the EN bit is read as 0, this means that
+   * the stream is ready to be configured. It is therefore necessary to wait
+   * for the EN bit to be cleared before starting any stream configuration."
+   */
+
+  while ((dmachan_getreg(dmachan, STM32_BDMACH_CCR_OFFSET) &
+          BDMA_CCR_EN) != 0);
 
-#warning stm32_bdma_setup not implemented
+  /* "... All the stream dedicated bits set in the status register BDMA_ISR
+   * from the previous data block DMA transfer should be cleared before the
+   * stream can be re-enabled."
+   *
+   * Clear pending stream interrupts by setting bits in the BDMA_IFCR
+   * register.
+   */
+
+  dmabase_putreg(dmachan, STM32_BDMA_IFCR_OFFSET,
+                 (BDMA_CHAN_MASK << dmachan->shift));
+
+  /* "Set the peripheral register address in the BDMA_SPARx register. The
+   * data will be moved from/to this address to/from the memory after the
+   *  peripheral event.
+   */
+
+  dmachan_putreg(dmachan, STM32_BDMACH_CPAR_OFFSET, cfg->paddr);
+
+  /* "Set the memory address in the BDMA_CM1ARx register. The data will be
+   *  written to or read from this memory after the peripheral event."
+   *
+   * Note that in double-buffered mode it is explicitly assumed that the
+   * second buffer immediately follows the first.
+   */
+
+  dmachan_putreg(dmachan, STM32_BDMACH_CM0AR_OFFSET, cfg->maddr);
+  if (scr & DMA_SCR_DBM)
+    {
+      dmachan_putreg(dmachan, STM32_BDMACH_CM1AR_OFFSET,
+                     cfg->maddr + cfg->ndata);
+    }
+
+  /* "Configure the total number of data items to be transferred in the
+   *  BDMA_CNDTRx register.  After each peripheral event, this value will be
+   *  decremented."
+   */
+
+  dmachan_putreg(dmachan, STM32_BDMACH_CNDTR_OFFSET, cfg->ndata);
+
+  /* "Configure the stream priority using the PL[1:0] bits, data transfer
+   *  direction, circular mode, peripheral & memory incremented mode,
+   *  peripheral & memory data size, and interrupt after
+   *  half and/or full transfer in the BDMACH_CCRx register."
+   *
+   * Note: The CT bit is always reset.
+   */
+
+  regval  = dmachan_getreg(dmachan, STM32_BDMACH_CCR_OFFSET);
+  regval &= ~(BDMA_CCR_DIR | BDMA_CCR_CIRC | BDMA_CCR_PINC |
+              BDMA_CCR_MINC | BDMA_CCR_PSIZE_MASK | BDMA_CCR_MSIZE_MASK |
+              BDMA_CCR_PL_MASK | BDMA_CCR_M2M | BDMA_CCR_DBM | BDMA_CCR_CT);
+  ccr = stm32_sdma_scr_2_bdma_ccr(scr);
+  ccr    &=  (BDMA_CCR_DIR | BDMA_CCR_CIRC | BDMA_CCR_PINC |
+              BDMA_CCR_MINC | BDMA_CCR_PSIZE_MASK | BDMA_CCR_MSIZE_MASK |
+              BDMA_CCR_PL_MASK | BDMA_CCR_M2M | BDMA_CCR_DBM);
+  regval |= ccr;
+  dmachan_putreg(dmachan, STM32_BDMACH_CCR_OFFSET, regval);
 }
 
 /****************************************************************************
@@ -1764,12 +1912,59 @@ static void stm32_bdma_setup(DMA_HANDLE handle, FAR stm32_dmacfg_t *cfg)
 static void stm32_bdma_start(DMA_HANDLE handle, dma_callback_t callback,
                              void *arg, bool half)
 {
-  DMA_CHANNEL dmachan    = (DMA_CHANNEL)handle;
-  uint8_t     controller = dmachan->ctrl;
+  DMA_CHANNEL dmachan = (DMA_CHANNEL)handle;
+  uint32_t ccr = 0;
 
-  DEBUGASSERT(controller == BDMA);
+  DEBUGASSERT(handle != NULL);
+  DEBUGASSERT(dmachan->ctrl == BDMA);
+
+  /* Save the callback info.  This will be invoked when the DMA completes */
+
+  dmachan->callback = callback;
+  dmachan->arg      = arg;
+
+  /* Activate the stream by setting the ENABLE bit in the DMA_SCRx register.
+   * As soon as the stream is enabled, it can serve any DMA request from the
+   * peripheral connected on the stream.
+   */
+
+  ccr  = dmachan_getreg(dmachan, STM32_BDMACH_CCR_OFFSET);
+  ccr |= BDMA_CCR_EN;
 
-#warning stm32_bdma_start not implemented
+  /* In normal mode, interrupt at either half or full completion. In circular
+   * and double-buffered modes, always interrupt on buffer wrap, and
+   * optionally interrupt at the halfway point.
+   */
+
+  if ((ccr & (BDMA_CCR_DBM | BDMA_CCR_CIRC)) == 0)
+    {
+      /* Once half of the bytes are transferred, the half-transfer flag
+       * (HTIF) is set and an interrupt is generated if the
+       * Half-Transfer Interrupt Enable bit (HTIE) is set. At the end of the
+       * transfer, the Transfer Complete Flag (TCIF) is set and an interrupt
+       * is generated if the Transfer Complete Interrupt Enable bit (TCIE) is
+       * set.
+       */
+
+      ccr |= (half ? (BDMA_CCR_HTIE | BDMA_CCR_TEIE) :
+                     (BDMA_CCR_TCIE | BDMA_CCR_TEIE));
+    }
+  else
+    {
+      /* In non-stop modes, when the transfer completes it immediately resets
+       * and starts again.  The transfer-complete interrupt is thus always
+       * enabled, and the half-complete interrupt can be used in circular
+       * mode to determine when the buffer is half-full, or in
+       * double-buffered mode to determine when one of the two buffers is
+       * full
+       */
+
+      ccr |= (half ? BDMA_CCR_HTIE : 0) | BDMA_CCR_TCIE | BDMA_CCR_TEIE;
+    }
+
+  dmachan_putreg(dmachan, STM32_BDMACH_CCR_OFFSET, ccr);
+
+  stm32_dmadump(handle, "DMA after start");
 }
 
 /****************************************************************************
@@ -1779,10 +1974,10 @@ static void stm32_bdma_start(DMA_HANDLE handle, dma_callback_t callback,
 static size_t stm32_bdma_residual(DMA_HANDLE handle)
 {
   DMA_CHANNEL dmachan    = (DMA_CHANNEL)handle;
-  uint8_t     controller = dmachan->ctrl;
   uint32_t    residual   = 0
 
-  DEBUGASSERT(controller == BDMA);
+  DEBUGASSERT(handle != NULL);
+  DEBUGASSERT(dmachan->ctrl == BDMA);
 
   /* Fetch the count of bytes remaining to be transferred */
 
@@ -1804,10 +1999,8 @@ static bool stm32_bdma_capable(FAR stm32_dmacfg_t *cfg)
 
   dmainfo("0x%08x/%u 0x%08x\n", cfg->maddr, cfg->ndata, cfg->cfg1);
 
-#warning REVISIT
-
   /* Verify that the address conforms to the memory transfer size.
-   * Transfers to/from memory performed by the DMA controller are
+   * Transfers to/from memory performed by the BDMA controller are
    * required to be aligned to their size.
    *
    * See ST RM0090 rev4, section 9.3.11