stm32h7:DMA Add BDMA support

Apply suggestions from code review

Co-authored-by: Mateusz Szafoni <raiden00pl@gmail.com>
This commit is contained in:
David Sidrane 2020-06-05 09:03:32 -07:00 committed by Abdelatif Guettouche
parent a7a272661e
commit a793369815
3 changed files with 247 additions and 40 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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);
#warning stm32_bdma_disable not implemented
/* 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);
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);
#warning stm32_bdma_setup not implemented
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);
/* "... 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);
#warning stm32_bdma_start not implemented
/* 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;
/* 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