Skip to content

Commit

Permalink
Merge pull request #18711 from Enoch247/cpu-stm32-dma-fixes
Browse files Browse the repository at this point in the history
cpu/stm32: fix periph_dma
  • Loading branch information
benpicco authored Oct 27, 2022
2 parents 4ebece5 + 4e2c63c commit 578d328
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 18 deletions.
23 changes: 11 additions & 12 deletions cpu/stm32/include/periph/cpu_dma.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
*
* @author Hauke Petersen <hauke.petersen@fu-berlin.de>
* @author Vincent Dupont <vincent@otakeys.com>
* @author Joshua DeWeese <jdeweese@primecontrols.com>
*/

#ifndef PERIPH_CPU_DMA_H
Expand All @@ -38,7 +39,7 @@ typedef struct {
* - 8: DAM2 / Stream0
* - ...
* - 15: DMA2 / Stream7
* STM32F0/1/L0/1/4:
* STM32F0/1/3/L0/1/4:
* - 0: DMA1 / Channel1
* - ...
* - 4: DMA1 / Channel5
Expand Down Expand Up @@ -88,10 +89,8 @@ typedef enum {
* @{
*/
#define DMA_DATA_WIDTH_BYTE (0x00) /**< Byte width */
#define DMA_DATA_WIDTH_HALF_WORD (0x01) /**< Half word width */
#define DMA_DATA_WIDTH_WORD (0x02) /**< Word width */
#define DMA_DATA_WIDTH_MASK (0x03) /**< Width mask */
#define DMA_DATA_WIDTH_SHIFT (0) /**< Width position */
#define DMA_DATA_WIDTH_HALF_WORD (0x01) /**< Half word width (2 bytes)*/
#define DMA_DATA_WIDTH_WORD (0x02) /**< Word width (4 bytes)*/
/** @} */

#ifdef MODULE_PERIPH_DMA
Expand All @@ -115,7 +114,7 @@ void dma_init(void);
* @param[in] chan DMA channel (on stm32f2/4/7, CxS or unused on others)
* @param[in] src source buffer
* @param[out] dst destination buffer
* @param[in] len length to transfer
* @param[in] len number of transfers to perform
* @param[in] mode DMA mode
* @param[in] flags DMA configuration
*
Expand Down Expand Up @@ -153,15 +152,15 @@ void dma_start(dma_t dma);
*
* @param[in] dma logical DMA stream
*
* @return the remaining number of bytes to transfer
* @return the remaining number of transfers to perform
*/
uint16_t dma_suspend(dma_t dma);

/**
* @brief Resume a suspended DMA transfer on a stream
*
* @param[in] dma logical DMA stream
* @param[in] reamaining the remaining number of bytes to transfer
* @param[in] reamaining the remaining number of transfers to perform
*/
void dma_resume(dma_t dma, uint16_t remaining);

Expand All @@ -186,7 +185,7 @@ void dma_wait(dma_t dma);
* @param[in] chan DMA channel (on stm32f2/4/7, CxS or unused on others)
* @param[in] src source buffer
* @param[out] dst destination buffer
* @param[in] len length to transfer
* @param[in] len number of transfers to perform
* @param[in] mode DMA mode
* @param[in] flags DMA configuration
*
Expand All @@ -206,7 +205,7 @@ int dma_configure(dma_t dma, int chan, const volatile void *src, volatile void *
* @param[in] chan DMA channel (on stm32f2/4/7, CxS or unused on others)
* @param[in] periph_addr Peripheral register address
* @param[in] mode DMA direction mode
* @param[in] width DMA transfer width
* @param[in] width DMA transfer width (one of DMA_DATA_WIDTH_*)
* @param[in] inc_periph Increment peripheral address after read/write
*/
void dma_setup(dma_t dma, int chan, void *periph_addr, dma_mode_t mode,
Expand All @@ -217,8 +216,8 @@ void dma_setup(dma_t dma, int chan, void *periph_addr, dma_mode_t mode,
*
* @param[in] dma Logical DMA stream
* @param[in] mem Memory address
* @param[in] len Transfer length
* @param[in] inc_mem Increment the memory address after read/write
* @param[in] len Number of transfers to perform
* @param[in] inc_mem Increment the memory address (by the transfer width) after read/write
*/
void dma_prepare(dma_t dma, void *mem, size_t len, bool incr_mem);

Expand Down
42 changes: 36 additions & 6 deletions cpu/stm32/periph/dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
* @brief Low-level DMA driver implementation
*
* @author Vincent Dupont <vincent@otakeys.com>
* @author Joshua DeWeese <jdeweese@primecontrols.com>
*
* @}
*/
Expand Down Expand Up @@ -84,6 +85,9 @@
#endif
#endif /* CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7 */

#define DMA_DATA_WIDTH_MASK (0x03)
#define DMA_DATA_WIDTH_SHIFT (0)

struct dma_ctx {
STM32_DMA_Stream_Type *stream;
mutex_t conf_lock;
Expand Down Expand Up @@ -193,22 +197,28 @@ static IRQn_Type dma_get_irqn(int stream)
return ((IRQn_Type)((int)DMA1_Channel1_IRQn + stream));
}
#if defined(DMA2_BASE)
/* stream 7 is invalid for these CPU families */
else if (stream == 7) {
return -1;
}
#if defined(CPU_FAM_STM32F1)
else if (stream < 11) {
#else
else if (stream < 13 ) {
#endif
return ((IRQn_Type)((int)DMA2_Channel1_IRQn + stream));
/* magic number 8 is first DMA2 stream */
return ((IRQn_Type)((int)DMA2_Channel1_IRQn + stream - 8));
}
#if !defined(CPU_FAM_STM32L1)
#if !defined(CPU_FAM_STM32L1) && !defined(CPU_FAM_STM32F3)
else {
#if defined(CPU_FAM_STM32F1)
return (DMA2_Channel4_5_IRQn);
#else
return ((IRQn_Type)((int)DMA2_Channel6_IRQn + stream));
/* magic number 13 is 8 (first DMA2 stream) + 5 (Channel6) */
return ((IRQn_Type)((int)DMA2_Channel6_IRQn + stream - 13));
#endif
}
#endif /* !defined(CPU_FAM_STM32L1) */
#endif /* !defined(CPU_FAM_STM32L1) && !defined(CPU_FAM_STM32F3) */
#endif /* defined(DMA2_BASE) */
#endif

Expand Down Expand Up @@ -392,7 +402,7 @@ void dma_prepare(dma_t dma, void *mem, size_t len, bool incr_mem)
STM32_DMA_Stream_Type *stream = dma_ctx[dma].stream;
uint32_t ctr_reg = stream->CONTROL_REG;

#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
#ifdef DMA_SxCR_MINC
stream->CONTROL_REG = (ctr_reg & ~(DMA_SxCR_MINC)) |
(incr_mem << DMA_SxCR_MINC_Pos);
#else
Expand Down Expand Up @@ -479,10 +489,30 @@ void dma_resume(dma_t dma, uint16_t remaining)
int stream_n = dma_config[dma].stream;
STM32_DMA_Stream_Type *stream = dma_ctx[dma].stream;

#ifdef DMA_SxCR_MINC
const bool mem_inc = stream->CONTROL_REG & DMA_SxCR_MINC;
const bool periph_inc = stream->CONTROL_REG & DMA_SxCR_PINC;
const int msize_reg =
(stream->CONTROL_REG & DMA_SxCR_MSIZE) >> DMA_SxCR_MSIZE_Pos;
const int psize_reg =
(stream->CONTROL_REG & DMA_SxCR_MSIZE) >> DMA_SxCR_MSIZE_Pos;
#else
const bool mem_inc = stream->CONTROL_REG & DMA_CCR_MINC;
const bool periph_inc = stream->CONTROL_REG & DMA_CCR_PINC;
const int msize_reg =
(stream->CONTROL_REG & DMA_CCR_MSIZE) >> DMA_CCR_MSIZE_Pos;
const int psize_reg =
(stream->CONTROL_REG & DMA_CCR_PSIZE) >> DMA_CCR_PSIZE_Pos;
#endif

const int mpitch = (mem_inc) ? msize_reg + 1 : 0;
const int ppitch = (periph_inc) ? psize_reg + 1 : 0;

if (remaining > 0) {
dma_isr_enable(stream_n);
stream->NDTR_REG = remaining;
stream->MEM_ADDR += dma_ctx[dma].len - remaining;
stream->MEM_ADDR += mpitch * (dma_ctx[dma].len - remaining);
stream->PERIPH_ADDR += ppitch * (dma_ctx[dma].len - remaining);
dma_ctx[dma].len = remaining;
stream->CONTROL_REG |= DMA_EN;
}
Expand Down

0 comments on commit 578d328

Please sign in to comment.