Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cpu/stm32: fix periph_dma #18711

Merged
merged 3 commits into from
Oct 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <[email protected]>
* @author Vincent Dupont <[email protected]>
* @author Joshua DeWeese <[email protected]>
*/

#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 <[email protected]>
* @author Joshua DeWeese <[email protected]>
*
* @}
*/
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)
benpicco marked this conversation as resolved.
Show resolved Hide resolved

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));
benpicco marked this conversation as resolved.
Show resolved Hide resolved
}
#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));
benpicco marked this conversation as resolved.
Show resolved Hide resolved
#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