1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-01-17 04:52:59 +01:00

cpu/stm32_common: adapt DMA driver for f0/1/3/l0/1/4

This commit is contained in:
Vincent Dupont 2018-05-23 19:08:03 +02:00
parent a9a30c0c0f
commit 021697ae94
4 changed files with 380 additions and 195 deletions

View File

@ -241,7 +241,29 @@ typedef enum {
* @brief DMA configuration
*/
typedef struct {
int stream; /**< DMA stream */
/** DMA stream on stm32f2/4/7, channel on others
* STM32F2/4/7:
* - 0: DMA1 / Stream0
* - 1: DMA1 / Stream1
* - ...
* - 7: DMA1 / Stream7
* - 8: DAM2 / Stream0
* - ...
* - 15: DMA2 / Stream7
* STM32F0/1/L0/1/4:
* - 0: DMA1 / Channel1
* - ...
* - 4: DMA1 / Channel5
* - ...
* - 6: DMA1 / Channel7
* - 7: Reserved
* - 8: DMA2 / Channel1
* - ...
* - 12: DMA2 / Channel5
* - ...
* - 14: DMA2 / Channel7
*/
int stream;
} dma_conf_t;
/**
@ -536,7 +558,7 @@ void dma_init(void);
* function which configure, start, wait and stop a DMA transfer.
*
* @param[in] dma logical DMA stream
* @param[in] chan DMA channel
* @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
@ -545,7 +567,7 @@ void dma_init(void);
*
* @return < 0 on error, the number of transfered bytes otherwise
*/
int dma_transfer(dma_t dma, int chan, const void *src, void *dst, size_t len,
int dma_transfer(dma_t dma, int chan, const volatile void *src, volatile void *dst, size_t len,
dma_mode_t mode, uint8_t flags);
/**
@ -607,7 +629,7 @@ void dma_wait(dma_t dma);
* @brief Configure a DMA stream for a new transfer
*
* @param[in] dma logical DMA stream
* @param[in] chan DMA channel
* @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
@ -616,147 +638,9 @@ void dma_wait(dma_t dma);
*
* @return < 0 on error, 0 on success
*/
int dma_configure(dma_t dma, int chan, const void *src, void *dst, size_t len,
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);
/**
* @brief Get DMA base register
*
* For simplifying DMA stream handling, we map the DMA channels transparently to
* one integer number, such that DMA1 stream0 equals 0, DMA2 stream0 equals 8,
* DMA2 stream 7 equals 15 and so on.
*
* @param[in] stream physical DMA stream
*/
static inline DMA_TypeDef *dma_base(int stream)
{
return (stream < 8) ? DMA1 : DMA2;
}
/**
* @brief Power on the DMA device the given stream belongs to
*
* @param[in] stream physical DMA stream
*/
static inline void dma_poweron(int stream)
{
if (stream < 8) {
periph_clk_en(AHB1, RCC_AHB1ENR_DMA1EN);
}
else {
periph_clk_en(AHB1, RCC_AHB1ENR_DMA2EN);
}
}
/**
* @brief Get the DMA stream base address
*
* @param[in] stream physical DMA stream
*
* @return base address for the selected DMA stream
*/
static inline DMA_Stream_TypeDef *dma_stream(int stream)
{
uint32_t base = (uint32_t)dma_base(stream);
return (DMA_Stream_TypeDef *)(base + (0x10 + (0x18 * (stream & 0x7))));
}
/**
* @brief Select high or low DMA interrupt register based on stream number
*
* @param[in] stream physical DMA stream
*
* @return 0 for streams 0-3, 1 for streams 3-7
*/
static inline int dma_hl(int stream)
{
return ((stream & 0x4) >> 2);
}
/**
* @brief Get the interrupt flag clear bit position in the DMA LIFCR register
*
* @param[in] stream physical DMA stream
*/
static inline uint32_t dma_ifc(int stream)
{
switch (stream & 0x3) {
case 0:
return (1 << 5);
case 1:
return (1 << 11);
case 2:
return (1 << 21);
case 3:
return (1 << 27);
default:
return 0;
}
}
/**
* @brief Enable the interrupt of a given stream
*
* @param[in] stream physical DMA stream
*/
static inline void dma_isr_enable(int stream)
{
if (stream < 7) {
NVIC_EnableIRQ((IRQn_Type)((int)DMA1_Stream0_IRQn + stream));
}
else if (stream == 7) {
NVIC_EnableIRQ(DMA1_Stream7_IRQn);
}
else if (stream < 13) {
NVIC_EnableIRQ((IRQn_Type)((int)DMA2_Stream0_IRQn + (stream - 8)));
}
else if (stream < 16) {
NVIC_EnableIRQ((IRQn_Type)((int)DMA2_Stream5_IRQn + (stream - 13)));
}
}
/**
* @brief Disable the interrupt of a given stream
*
* @param[in] stream physical DMA stream
*/
static inline void dma_isr_disable(int stream)
{
if (stream < 7) {
NVIC_DisableIRQ((IRQn_Type)((int)DMA1_Stream0_IRQn + stream));
}
else if (stream == 7) {
NVIC_DisableIRQ(DMA1_Stream7_IRQn);
}
else if (stream < 13) {
NVIC_DisableIRQ((IRQn_Type)((int)DMA2_Stream0_IRQn + (stream - 8)));
}
else if (stream < 16) {
NVIC_DisableIRQ((IRQn_Type)((int)DMA2_Stream5_IRQn + (stream - 13)));
}
}
/**
* @brief Clear the interrupt of a given stream
*
* @param[in] stream physical DMA stream
*/
static inline void dma_isr_clear(int stream)
{
if (stream < 7) {
NVIC_ClearPendingIRQ((IRQn_Type)((int)DMA1_Stream0_IRQn + stream));
}
else if (stream == 7) {
NVIC_ClearPendingIRQ((IRQn_Type)DMA1_Stream7_IRQn);
}
else if (stream < 13) {
NVIC_ClearPendingIRQ((IRQn_Type)((int)DMA2_Stream0_IRQn + (stream - 8)));
}
else if (stream < 16) {
NVIC_ClearPendingIRQ((IRQn_Type)((int)DMA2_Stream5_IRQn + (stream - 13)));
}
}
#endif /* MODULE_PERIPH_DMA */
#ifdef __cplusplus

View File

@ -24,14 +24,75 @@
#include "periph_conf.h"
#include "mutex.h"
#include "assert.h"
#include "pm_layered.h"
#if !(defined(CPU_FAM_STM32F2) || defined(CPU_FAM_STM32F4) || defined(CPU_FAM_STM32F7))
#error "DMA is not supported for target CPU"
#if CPU_FAM_STM32F3
#error "DMA is not supported on STM32F3"
#endif
#define DMA_STREAM_IT_MASK (DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 | \
DMA_LISR_TEIF0 | DMA_LISR_HTIF0 | \
DMA_LISR_TCIF0)
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
#define STM32_DMA_Stream_Type DMA_Stream_TypeDef
#define CLOCK AHB1
#define PERIPH_ADDR PAR
#define MEM_ADDR M0AR
#define NDTR_REG NDTR
#define CONTROL_REG CR
#define RCC_MASK_DMA1 RCC_AHB1ENR_DMA1EN
#define RCC_MASK_DMA2 RCC_AHB1ENR_DMA2EN
#define DMA_STREAM_IT_MASK (DMA_LISR_FEIF0 | DMA_LISR_DMEIF0 | \
DMA_LISR_TEIF0 | DMA_LISR_HTIF0 | \
DMA_LISR_TCIF0)
#define DMA_EN DMA_SxCR_EN
#else /* CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7 */
#define STM32_DMA_Stream_Type DMA_Channel_TypeDef
#if CPU_FAM_STM32L4
#define CLOCK AHB1
#define RCC_MASK_DMA1 RCC_AHB1ENR_DMA1EN
#define RCC_MASK_DMA2 RCC_AHB1ENR_DMA2EN
#else /* CPU_FAM_STM32L4 */
#define CLOCK AHB
#if CPU_FAM_STM32F1 || CPU_FAM_STM32L1
#define RCC_MASK_DMA1 RCC_AHBENR_DMA1EN
#else /* CPU_FAM_STM32F1 || CPU_FAM_STM32L1 */
#define RCC_MASK_DMA1 RCC_AHBENR_DMAEN
#endif /* CPU_FAM_STM32F1 || CPU_FAM_STM32L1 */
#define RCC_MASK_DMA2 RCC_AHBENR_DMA2EN
#endif /* CPU_FAM_STM32L4 */
#define PERIPH_ADDR CPAR
#define MEM_ADDR CMAR
#define NDTR_REG CNDTR
#define CONTROL_REG CCR
#if CPU_FAM_STM32L1
#define DMA_CCR_TCIE DMA_CCR1_TCIE
#define DMA_CCR_TEIE DMA_CCR1_TEIE
#define DMA_EN DMA_CCR1_EN
#else /* CPU_FAM_STM32L1 */
#define DMA_EN DMA_CCR_EN
#endif /* CPU_FAM_STM32L1 */
#define DMA_STREAM_IT_MASK (DMA_IFCR_CGIF1 | DMA_IFCR_CTCIF1 | \
DMA_IFCR_CHTIF1 | DMA_IFCR_CTEIF1)
#ifndef DMA_CCR_MSIZE_Pos
#define DMA_CCR_MSIZE_Pos (10)
#endif
#ifndef DMA_CCR_PSIZE_Pos
#define DMA_CCR_PSIZE_Pos (8)
#endif
#ifndef DMA_CCR_MINC_Pos
#define DMA_CCR_MINC_Pos (7)
#endif
#ifndef DMA_CCR_PINC_Pos
#define DMA_CCR_PINC_Pos (6)
#endif
#ifndef DMA_CCR_DIR_Pos
#define DMA_CCR_DIR_Pos (4)
#endif
#ifndef DMA_CCR_MEM2MEM_Pos
#define DMA_CCR_MEM2MEM_Pos (14)
#endif
#if defined(CPU_FAM_STM32F0) && !defined(DMA1_Channel4_5_6_7_IRQn)
#define DMA1_Channel4_5_6_7_IRQn DMA1_Channel4_5_IRQn
#endif
#endif /* CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7 */
struct dma_ctx {
mutex_t conf_lock;
@ -41,10 +102,161 @@ struct dma_ctx {
static struct dma_ctx dma_ctx[DMA_NUMOF];
/**
* @brief Get DMA base register
*
* For simplifying DMA stream handling, we map the DMA channels transparently to
* one integer number, such that DMA1 stream0 equals 0, DMA2 stream0 equals 8,
* DMA2 stream 7 equals 15 and so on.
*
* @param[in] stream physical DMA stream
*/
static inline DMA_TypeDef *dma_base(int stream)
{
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
return (stream < 8) ? DMA1 : DMA2;
#elif defined(DMA2)
return (stream < 7) ? DMA1 : DMA2;
#else
(void)stream;
return DMA1;
#endif
}
#ifdef CPU_FAM_STM32F0
static inline DMA_TypeDef *dma_req(int stream_n)
{
return dma_base(stream_n);
}
#elif CPU_FAM_STM32L0 || CPU_FAM_STM32L4
static inline DMA_Request_TypeDef *dma_req(int stream_n)
{
#ifdef DMA2
return (stream_n < 7) ? DMA1_CSELR : DMA2_CSELR;
#else
(void)stream_n;
return DMA1_CSELR;
#endif
}
#endif
/**
* @brief Get the DMA stream base address
*
* @param[in] stream physical DMA stream
*
* @return base address for the selected DMA stream
*/
static inline STM32_DMA_Stream_Type *dma_stream(int stream)
{
uint32_t base = (uint32_t)dma_base(stream);
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
return (DMA_Stream_TypeDef *)(base + (0x10 + (0x18 * (stream & 0x7))));
#else
return (DMA_Channel_TypeDef *)(base + (0x08 + (0x14 * (stream & 0x7))));
#endif
}
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
/**
* @brief Select high or low DMA interrupt register based on stream number
*
* @param[in] stream physical DMA stream
*
* @return 0 for streams 0-3, 1 for streams 3-7
*/
static inline int dma_hl(int stream)
{
return ((stream & 0x4) >> 2);
}
#endif
static IRQn_Type dma_get_irqn(int stream)
{
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
if (stream < 7) {
return ((IRQn_Type)((int)DMA1_Stream0_IRQn + stream));
}
else if (stream == 7) {
return DMA1_Stream7_IRQn;
}
else if (stream < 13) {
return ((IRQn_Type)((int)DMA2_Stream0_IRQn + (stream - 8)));
}
else if (stream < 16) {
return ((IRQn_Type)((int)DMA2_Stream5_IRQn + (stream - 13)));
}
#elif CPU_FAM_STM32F0 || CPU_FAM_STM32L0
if (stream == 0) {
return (DMA1_Channel1_IRQn);
}
else if (stream < 3 || (stream >= 8 && stream < 11)) {
return (DMA1_Channel2_3_IRQn);
}
else if (stream < 7 || stream >= 11) {
return (DMA1_Channel4_5_6_7_IRQn);
}
#else
if (stream < 7) {
return ((IRQn_Type)((int)DMA1_Channel1_IRQn + stream));
}
#if defined(CPU_FAM_STM32F1)
else if (stream < 11) {
#else
else if (stream < 13 ) {
#endif
return ((IRQn_Type)((int)DMA2_Channel1_IRQn + stream));
}
#if !defined(CPU_FAM_STM32L1)
else {
#if defined(CPU_FAM_STM32F1)
return (DMA2_Channel4_5_IRQn);
#else
return ((IRQn_Type)((int)DMA2_Channel6_IRQn + stream));
#endif
}
#endif
#endif
return -1;
}
/**
* @brief Disable the interrupt of a given stream
*
* @param[in] stream physical DMA stream
*/
static inline void dma_isr_disable(int stream)
{
NVIC_DisableIRQ(dma_get_irqn(stream));
}
/**
* @brief Clear the interrupt of a given stream
*
* @param[in] stream physical DMA stream
*/
static inline void dma_isr_clear(int stream)
{
NVIC_ClearPendingIRQ(dma_get_irqn(stream));
}
/**
* @brief Enable the interrupt of a given stream
*
* @param[in] stream physical DMA stream
*/
static inline void dma_isr_enable(int stream)
{
NVIC_EnableIRQ(dma_get_irqn(stream));
}
static inline uint32_t dma_all_flags(dma_t dma)
{
assert(dma < DMA_NUMOF);
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
switch (dma_config[dma].stream & 0x3) {
case 0: /* 0 and 4 */
return (DMA_STREAM_IT_MASK);
@ -57,24 +269,30 @@ static inline uint32_t dma_all_flags(dma_t dma)
default:
return 0;
}
#else
return DMA_STREAM_IT_MASK << ((dma_config[dma].stream & 0x7) * 4);
#endif
}
static void dma_clear_all_flags(dma_t dma)
{
assert(dma < DMA_NUMOF);
DMA_TypeDef *stream = dma_base(dma_config[dma].stream);
DMA_TypeDef *dma_dev = dma_base(dma_config[dma].stream);
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
/* Clear all flags */
if (dma_hl(dma_config[dma].stream) == 0) {
stream->LIFCR = dma_all_flags(dma);
dma_dev->LIFCR = dma_all_flags(dma);
}
else {
stream->HIFCR = dma_all_flags(dma);
dma_dev->HIFCR = dma_all_flags(dma);
}
#else
dma_dev->IFCR = dma_all_flags(dma);
#endif
}
void dma_init(void)
{
for (unsigned i = 0; i < DMA_NUMOF; i++) {
@ -84,7 +302,20 @@ void dma_init(void)
}
}
int dma_transfer(dma_t dma, int chan, const void *src, void *dst, size_t len,
static void dma_poweron(int stream)
{
if (stream < 8) {
periph_clk_en(CLOCK, RCC_MASK_DMA1);
}
#if defined(DMA2)
else {
periph_clk_en(CLOCK, RCC_MASK_DMA2);
}
#endif
}
int dma_transfer(dma_t dma, int chan, const volatile void *src, volatile void *dst, size_t len,
dma_mode_t mode, uint8_t flags)
{
int ret = dma_configure(dma, chan, src, dst, len, mode, flags);
@ -103,16 +334,24 @@ void dma_acquire(dma_t dma)
assert(dma < DMA_NUMOF);
mutex_lock(&dma_ctx[dma].conf_lock);
#ifdef STM32_PM_STOP
/* block STOP mode */
pm_block(STM32_PM_STOP);
#endif
}
void dma_release(dma_t dma)
{
assert(dma < DMA_NUMOF);
#ifdef STM32_PM_STOP
/* unblock STOP mode */
pm_unblock(STM32_PM_STOP);
#endif
mutex_unlock(&dma_ctx[dma].conf_lock);
}
int dma_configure(dma_t dma, int chan, const void *src, void *dst, size_t len,
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)
{
assert(src != NULL);
@ -122,22 +361,22 @@ int dma_configure(dma_t dma, int chan, const void *src, void *dst, size_t len,
int stream_n = dma_config[dma].stream;
uint32_t inc_periph;
uint32_t inc_mem;
STM32_DMA_Stream_Type *stream = dma_stream(stream_n);
DMA_Stream_TypeDef *stream = dma_stream(stream_n);
dma_poweron(stream_n);
dma_clear_all_flags(dma);
switch (mode) {
case DMA_MEM_TO_MEM:
case DMA_PERIPH_TO_MEM:
stream->PAR = (uint32_t)src;
stream->M0AR = (uint32_t)dst;
stream->PERIPH_ADDR = (uint32_t)src;
stream->MEM_ADDR = (uint32_t)dst;
inc_periph = (flags & DMA_INC_SRC_ADDR);
inc_mem = (flags & DMA_INC_DST_ADDR) >> 1;
break;
case DMA_MEM_TO_PERIPH:
stream->PAR = (uint32_t)dst;
stream->M0AR = (uint32_t)src;
stream->PERIPH_ADDR = (uint32_t)dst;
stream->MEM_ADDR = (uint32_t)src;
inc_periph = (flags & DMA_INC_DST_ADDR) >> 1;
inc_mem = (flags & DMA_INC_SRC_ADDR);
break;
@ -146,6 +385,7 @@ int dma_configure(dma_t dma, int chan, const void *src, void *dst, size_t len,
}
uint32_t width = (flags & DMA_DATA_WIDTH_MASK) >> DMA_DATA_WIDTH_SHIFT;
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
/* Set channel, data width, inc and mode */
stream->CR = (chan & 0xF) << DMA_SxCR_CHSEL_Pos |
width << DMA_SxCR_MSIZE_Pos | width << DMA_SxCR_PSIZE_Pos |
@ -155,9 +395,20 @@ int dma_configure(dma_t dma, int chan, const void *src, void *dst, size_t len,
stream->CR |= DMA_SxCR_TCIE | DMA_SxCR_TEIE;
/* Configure FIFO */
stream->FCR = 0;
#else
#if defined(DMA_CSELR_C1S) || defined(DMA1_CSELR_DEFAULT)
dma_req(stream_n)->CSELR &= ~((0xF) << ((stream_n & 0x7) << 2));
dma_req(stream_n)->CSELR |= (chan & 0xF) << ((stream_n & 0x7) << 2);
#else
(void)chan;
#endif
stream->CONTROL_REG = width << DMA_CCR_MSIZE_Pos | width << DMA_CCR_PSIZE_Pos |
inc_periph << DMA_CCR_PINC_Pos | inc_mem << DMA_CCR_MINC_Pos |
(mode & 1) << DMA_CCR_DIR_Pos | ((mode & 2) >> 1) << DMA_CCR_MEM2MEM_Pos;
stream->CONTROL_REG |= DMA_CCR_TCIE | DMA_CCR_TEIE;
#endif
/* Set length */
stream->NDTR = len;
stream->NDTR_REG = len;
dma_ctx[dma].len = len;
dma_isr_enable(stream_n);
@ -169,9 +420,9 @@ void dma_start(dma_t dma)
{
assert(dma < DMA_NUMOF);
DMA_Stream_TypeDef *stream = dma_stream(dma_config[dma].stream);
STM32_DMA_Stream_Type *stream = dma_stream(dma_config[dma].stream);
stream->CR |= DMA_SxCR_EN;
stream->CONTROL_REG |= DMA_EN;
}
uint16_t dma_suspend(dma_t dma)
@ -179,15 +430,15 @@ uint16_t dma_suspend(dma_t dma)
assert(dma < DMA_NUMOF);
int stream_n = dma_config[dma].stream;
DMA_Stream_TypeDef *stream = dma_stream(stream_n);
STM32_DMA_Stream_Type *stream = dma_stream(stream_n);
uint16_t left = 0;
if ((stream->CR & DMA_SxCR_EN) == DMA_SxCR_EN) {
if ((stream->CONTROL_REG & DMA_EN) == DMA_EN) {
dma_isr_disable(stream_n);
stream->CR &= ~(uint32_t)DMA_SxCR_EN;
while ((stream->CR & DMA_SxCR_EN) == DMA_SxCR_EN) {}
stream->CONTROL_REG &= ~(uint32_t)DMA_EN;
while ((stream->CONTROL_REG & DMA_EN) == DMA_EN) {}
dma_clear_all_flags(dma);
left = stream->NDTR;
left = stream->NDTR_REG;
dma_isr_clear(stream_n);
}
return left;
@ -199,14 +450,14 @@ void dma_resume(dma_t dma, uint16_t remaining)
assert(dma < DMA_NUMOF);
int stream_n = dma_config[dma].stream;
DMA_Stream_TypeDef *stream = dma_stream(stream_n);
STM32_DMA_Stream_Type *stream = dma_stream(stream_n);
if (remaining > 0) {
dma_isr_enable(stream_n);
stream->NDTR = remaining;
stream->M0AR += dma_ctx[dma].len - remaining;
stream->NDTR_REG = remaining;
stream->MEM_ADDR += dma_ctx[dma].len - remaining;
dma_ctx[dma].len = remaining;
stream->CR |= (uint32_t)DMA_SxCR_EN;
stream->CONTROL_REG |= DMA_EN;
}
}
@ -214,9 +465,9 @@ void dma_stop(dma_t dma)
{
assert(dma < DMA_NUMOF);
DMA_Stream_TypeDef *stream = dma_stream(dma_config[dma].stream);
STM32_DMA_Stream_Type *stream = dma_stream(dma_config[dma].stream);
stream->CR &= ~(uint32_t)DMA_SxCR_EN;
stream->CONTROL_REG &= ~(uint32_t)DMA_EN;
}
void dma_wait(dma_t dma)
@ -304,3 +555,51 @@ void DMA_9_ISR(void)
dma_isr_handler(9);
}
#endif
#if defined(DMA_SHARED_ISR_0) || defined(DMA_SHARED_ISR_1)
static int dma_is_isr(dma_t dma)
{
DMA_TypeDef *dma_dev = dma_base(dma_config[dma].stream);
#if CPU_FAM_STM32F2 || CPU_FAM_STM32F4 || CPU_FAM_STM32F7
/* Clear all flags */
if (dma_hl(dma_config[dma].stream) == 0) {
return dma_dev->LISR & dma_all_flags(dma);
}
else {
return dma_dev->HISR & dma_all_flags(dma);
}
#else
return dma_dev->ISR & dma_all_flags(dma);
#endif
}
static void shared_isr(uint8_t *streams, size_t nb)
{
for (size_t i = 0; i < nb; i++) {
dma_t dma = streams[i];
if (dma_is_isr(dma)) {
dma_clear_all_flags(dma);
mutex_unlock(&dma_ctx[dma].sync_lock);
}
}
cortexm_isr_end();
}
#endif
#ifdef DMA_SHARED_ISR_0
void DMA_SHARED_ISR_0(void)
{
uint8_t streams[] = DMA_SHARED_ISR_0_STREAMS;
shared_isr(streams, sizeof(streams) / sizeof(streams[0]));
}
#endif
#ifdef DMA_SHARED_ISR_1
void DMA_SHARED_ISR_1(void)
{
uint8_t streams[] = DMA_SHARED_ISR_1_STREAMS;
shared_isr(streams, sizeof(streams) / sizeof(streams[0]));
}
#endif

View File

@ -169,19 +169,19 @@ static void _transfer_dma(spi_t bus, const void *out, void *in, size_t len)
if (!out) {
dma_configure(spi_config[bus].tx_dma, spi_config[bus].tx_dma_chan, &tmp,
(void *)&(dev(bus)->DR), len, DMA_MEM_TO_PERIPH, 0);
&(dev(bus)->DR), len, DMA_MEM_TO_PERIPH, 0);
}
else {
dma_configure(spi_config[bus].tx_dma, spi_config[bus].tx_dma_chan, out,
(void *)&(dev(bus)->DR), len, DMA_MEM_TO_PERIPH, DMA_INC_SRC_ADDR);
&(dev(bus)->DR), len, DMA_MEM_TO_PERIPH, DMA_INC_SRC_ADDR);
}
if (!in) {
dma_configure(spi_config[bus].rx_dma, spi_config[bus].rx_dma_chan,
(void *)&(dev(bus)->DR), &tmp, len, DMA_PERIPH_TO_MEM, 0);
&(dev(bus)->DR), &tmp, len, DMA_PERIPH_TO_MEM, 0);
}
else {
dma_configure(spi_config[bus].rx_dma, spi_config[bus].rx_dma_chan,
(void *)&(dev(bus)->DR), in, len, DMA_PERIPH_TO_MEM, DMA_INC_DST_ADDR);
&(dev(bus)->DR), in, len, DMA_PERIPH_TO_MEM, DMA_INC_DST_ADDR);
}
dev(bus)->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;

View File

@ -34,6 +34,21 @@
#include "periph/gpio.h"
#include "pm_layered.h"
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) \
|| defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) \
|| defined(CPU_FAM_STM32F7)
#define ISR_REG ISR
#define ISR_TXE USART_ISR_TXE
#define ISR_TC USART_ISR_TC
#define TDR_REG TDR
#else
#define ISR_REG SR
#define ISR_TXE USART_SR_TXE
#define ISR_TC USART_SR_TC
#define TDR_REG DR
#endif
#define RXENABLE (USART_CR1_RE | USART_CR1_RXNEIE)
/**
@ -189,26 +204,13 @@ static inline void uart_init_lpuart(uart_t uart, uint32_t baudrate)
static inline void send_byte(uart_t uart, uint8_t byte)
{
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) \
|| defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) \
|| defined(CPU_FAM_STM32F7)
while (!(dev(uart)->ISR & USART_ISR_TXE)) {}
dev(uart)->TDR = byte;
#else
while (!(dev(uart)->SR & USART_SR_TXE)) {}
dev(uart)->DR = byte;
#endif
while (!(dev(uart)->ISR_REG & USART_ISR_TXE)) {}
dev(uart)->TDR_REG = byte;
}
static inline void wait_for_tx_complete(uart_t uart)
{
#if defined(CPU_FAM_STM32F0) || defined(CPU_FAM_STM32L0) \
|| defined(CPU_FAM_STM32F3) || defined(CPU_FAM_STM32L4) \
|| defined(CPU_FAM_STM32F7)
while (!(dev(uart)->ISR & USART_ISR_TC)) {}
#else
while (!(dev(uart)->SR & USART_SR_TC)) {}
#endif
while (!(dev(uart)->ISR_REG & ISR_TC)) {}
}
void uart_write(uart_t uart, const uint8_t *data, size_t len)
@ -248,7 +250,7 @@ void uart_write(uart_t uart, const uint8_t *data, size_t len)
dma_acquire(uart_config[uart].dma);
dev(uart)->CR3 |= USART_CR3_DMAT;
dma_transfer(uart_config[uart].dma, uart_config[uart].dma_chan, data,
(void *)&dev(uart)->DR, len, DMA_MEM_TO_PERIPH, DMA_INC_SRC_ADDR);
(void *)&dev(uart)->TDR_REG, len, DMA_MEM_TO_PERIPH, DMA_INC_SRC_ADDR);
dma_release(uart_config[uart].dma);
/* make sure the function is synchronous by waiting for the transfer to