Skip to content

Commit

Permalink
cpu/stm32/periph/dma: dma_setup_ext for extended configuration
Browse files Browse the repository at this point in the history
The function configures additional features of the DMA stream for F2/F4/F7.
`dma_setup_ext` added to configure F2/F4/F7 specific additional features like `MBURST`, `PBURST`, `FIFO` and Peripheral flow controller. It is supposed to be used after `dma_setup` and `dma_prepare`.
  • Loading branch information
gschorcht committed Jun 24, 2023
1 parent 9ba1d78 commit 9ea2270
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 0 deletions.
43 changes: 43 additions & 0 deletions cpu/stm32/include/periph/cpu_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,26 @@ typedef enum {
DMA_MEM_TO_MEM = 2, /**< Memory to memory */
} dma_mode_t;

/**
* @brief Burst Transfer modes for F2/F4/F7
*/
typedef enum {
DMA_BURST_SINGLE = 0, /**< single transfer */
DMA_BURST_INCR4 = 1, /**< incremental burst of 4 beats */
DMA_BURST_INCR8 = 2, /**< incremental burst of 8 beats */
DMA_BURST_INCR16 = 3, /**< incremental burst of 16 beats */
} dma_burst_t;

/**
* @brief Threshold selection in FIFO mode for F2/F4F7
*/
typedef enum {
DMA_FIFO_FULL_1_4 = 0, /**< 1/4 full FIFO */
DMA_FIFO_FULL_1_2 = 1, /**< 1/2 full FIFO */
DMA_FIFO_FULL_3_4 = 2, /**< 3/4 full FIFO */
DMA_FIFO_FULL = 3, /**< Full FIFO */
} dma_fifo_thresh_t;

/**
* @brief DMA channel/trigger configuration for DMA peripherals without
* channel/trigger filtering such as the stm32f1 and stm32f3.
Expand Down Expand Up @@ -211,6 +231,29 @@ int dma_configure(dma_t dma, int chan, const volatile void *src, volatile void *
void dma_setup(dma_t dma, int chan, void *periph_addr, dma_mode_t mode,
uint8_t width, bool inc_periph);

/**
* @brief Low level extended initial DMA stream configuration for F2/F4/F7
*
* The function configures additional features of the DMA stream for F2/F4/F7.
* It is supposed to be used after @ref dma_setup and before @ref dma_prepare.
*
* @note This function is only implemented for F2/F4/F7. For other families
* it is only a dummy. It is not used by @ref dma_configure or the
* convenience function @ref dma_transfer.
*
* @warn The combination of FIFO threshold and the memory burst transfer
* has to be valid.
*
* @param[in] dma Logical DMA stream
* @param[in] pburst Peripeheral burst transfer configuration
* @param[in] mburst Memory burst transfer configuration
* @param[in] fifo FIFO mode enable
* @param[in] thresh FIFO threshold
* @param[in] pfctrl Peripheral used as flow controller
*/
void dma_setup_ext(dma_t dma, dma_burst_t pburst, dma_burst_t mburst,
bool fifo, dma_fifo_thresh_t thresh, bool pfctrl);

/**
* @brief Low level DMA transfer configuration
*
Expand Down
72 changes: 72 additions & 0 deletions cpu/stm32/periph/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,78 @@ void dma_prepare(dma_t dma, void *mem, size_t len, bool incr_mem)
dma_ctx[dma].len = len;
}

void dma_setup_ext(dma_t dma, dma_burst_t pburst, dma_burst_t mburst,
bool fifo, dma_fifo_thresh_t thresh, bool pfctrl)
{
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
STM32_DMA_Stream_Type *stream = dma_ctx[dma].stream;

/* configuraition can be done only if DMA stream is disabled */
assert((stream->CR & DMA_EN) == 0);

/* FIFO configuration if enabled */
if (fifo) {
uint8_t width = (stream->CR & DMA_SxCR_MSIZE_Msk) >> DMA_SxCR_MSIZE_Pos;

/* check valid combinations of MSIZE, MBURST and FIFO threshold level */
switch (width) {
case DMA_DATA_WIDTH_BYTE:
switch (thresh) {
case DMA_FIFO_FULL_1_4:
/* fall through */
case DMA_FIFO_FULL_3_4:
assert(mburst == DMA_BURST_INCR4);
break;
case DMA_FIFO_FULL_1_2:
assert((mburst == DMA_BURST_INCR4) || (mburst == DMA_BURST_INCR8));
break;
case DMA_FIFO_FULL: /* all mburst values are valid */
break;
}
break;

case DMA_DATA_WIDTH_HALF_WORD:
switch (thresh) {
case DMA_FIFO_FULL_1_2:
assert(mburst == DMA_BURST_INCR4);
break;
case DMA_FIFO_FULL:
assert((mburst == DMA_BURST_INCR4) || (mburst == DMA_BURST_INCR8));
break;
default:
assert(false); /* all other combinations are invalid) */
break;
}
break;

case DMA_DATA_WIDTH_WORD:
assert((thresh == DMA_FIFO_FULL) && (mburst == DMA_BURST_INCR4));
break;
}

stream->FCR = (fifo << DMA_SxFCR_DMDIS_Pos) |
(thresh << DMA_SxFCR_FTH_Pos);
}
else {
stream->FCR = 0;
}

stream->CR &= ~(DMA_SxCR_PFCTRL | DMA_SxCR_MBURST | DMA_SxCR_PBURST);
stream->CR |= pfctrl ? DMA_SxCR_PFCTRL : 0;
stream->CR |= (mburst << DMA_SxCR_MBURST_Pos);
stream->CR |= (pburst << DMA_SxCR_PBURST_Pos);

#else
(void)dma;
(void)pburst;
(void)pburst;
(void)mburst;
(void)fifo;
(void)thresh;
(void)pfctrl;
#endif
}

int dma_configure(dma_t dma, int chan, const volatile void *src, volatile void *dst, size_t len,
dma_mode_t mode, uint8_t flags)
{
Expand Down

0 comments on commit 9ea2270

Please sign in to comment.