aboutsummaryrefslogtreecommitdiffstats
path: root/libmaple
diff options
context:
space:
mode:
Diffstat (limited to 'libmaple')
-rw-r--r--libmaple/stm32f1/dma.c62
-rw-r--r--libmaple/stm32f1/include/series/dma.h2
2 files changed, 60 insertions, 4 deletions
diff --git a/libmaple/stm32f1/dma.c b/libmaple/stm32f1/dma.c
index fc502a1..5364a04 100644
--- a/libmaple/stm32f1/dma.c
+++ b/libmaple/stm32f1/dma.c
@@ -121,14 +121,57 @@ static int preconfig_check(dma_dev *dev, dma_channel channel,
return DMA_TUBE_CFG_SUCCESS;
}
+static inline void set_ccr(dma_tube_reg_map *chregs,
+ dma_xfer_size msize, int minc,
+ dma_xfer_size psize, int pinc,
+ uint32 other_flags) {
+ chregs->CCR = ((msize << 10) | (psize << 8) |
+ (minc ? DMA_CCR_MINC : 0) | (pinc ? DMA_CCR_PINC : 0) |
+ other_flags);
+}
+
+static inline uint32 cfg_ccr_flags(unsigned tube_flags) {
+ /* DMA_CFG_SRC_INC and DMA_CFG_DST_INC are special */
+ return tube_flags & ~(DMA_CFG_SRC_INC | DMA_CFG_DST_INC);
+}
+
/* Configure chregs according to cfg, where cfg->tube_dst is peripheral. */
static int config_to_per(dma_tube_reg_map *chregs, dma_tube_config *cfg) {
- return -DMA_TUBE_CFG_ECFG; /* FIXME implement */
+ /* Check that ->tube_src is memory (if it's anything else, we
+ * shouldn't have been called). */
+ ASSERT(_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM);
+
+ set_ccr(chregs,
+ cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC,
+ cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC,
+ (cfg_ccr_flags(cfg->tube_flags) | DMA_CCR_DIR_FROM_MEM));
+ chregs->CMAR = (uint32)cfg->tube_src;
+ chregs->CPAR = (uint32)cfg->tube_dst;
+ return DMA_TUBE_CFG_SUCCESS;
}
/* Configure chregs according to cfg, where cfg->tube_dst is memory. */
static int config_to_mem(dma_tube_reg_map *chregs, dma_tube_config *cfg) {
- return -DMA_TUBE_CFG_ECFG; /* FIXME implement */
+ uint32 mem2mem;
+
+ if ((_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM) &&
+ (cfg->tube_flags & DMA_CFG_CIRC)) {
+ /* Can't do mem-to-mem and circular mode */
+ return -DMA_TUBE_CFG_ECFG;
+ }
+
+ mem2mem = (_dma_addr_type(cfg->tube_src) == DMA_ATYPE_MEM ?
+ DMA_CCR_MEM2MEM : 0);
+ set_ccr(chregs,
+ cfg->tube_dst_size, cfg->tube_flags & DMA_CFG_DST_INC,
+ cfg->tube_src_size, cfg->tube_flags & DMA_CFG_SRC_INC,
+ (cfg_ccr_flags(cfg->tube_flags) |
+ DMA_CCR_DIR_FROM_PER |
+ mem2mem));
+ chregs->CNDTR = cfg->tube_nr_xfers;
+ chregs->CMAR = (uint32)cfg->tube_dst;
+ chregs->CPAR = (uint32)cfg->tube_src;
+ return DMA_TUBE_CFG_SUCCESS;
}
/*
@@ -143,17 +186,28 @@ int dma_tube_cfg(dma_dev *dev, dma_channel channel, dma_tube_config *cfg) {
return ret;
}
+ dma_disable(dev, channel); /* Must disable before reconfiguring */
+ dma_clear_isr_bits(dev, channel); /* For sanity and consistency
+ * with STM32F2. */
+
chregs = dma_tube_regs(dev, channel);
switch (_dma_addr_type(cfg->tube_dst)) {
case DMA_ATYPE_PER:
- return config_to_per(chregs, cfg);
+ ret = config_to_per(chregs, cfg);
+ break;
case DMA_ATYPE_MEM:
- return config_to_mem(chregs, cfg);
+ ret = config_to_mem(chregs, cfg);
+ break;
default:
/* Can't happen */
ASSERT(0);
return -DMA_TUBE_CFG_ECFG;
}
+ if (ret < 0) {
+ return ret;
+ }
+ chregs->CNDTR = cfg->tube_nr_xfers;
+ return DMA_TUBE_CFG_SUCCESS;
}
void dma_set_priority(dma_dev *dev,
diff --git a/libmaple/stm32f1/include/series/dma.h b/libmaple/stm32f1/include/series/dma.h
index 6da3246..3b19e2b 100644
--- a/libmaple/stm32f1/include/series/dma.h
+++ b/libmaple/stm32f1/include/series/dma.h
@@ -293,6 +293,8 @@ typedef struct dma_tube_reg_map {
#define DMA_CCR_PINC (1U << DMA_CCR_PINC_BIT)
#define DMA_CCR_CIRC (1U << DMA_CCR_CIRC_BIT)
#define DMA_CCR_DIR (1U << DMA_CCR_DIR_BIT)
+#define DMA_CCR_DIR_FROM_PER (0U << DMA_CCR_DIR_BIT)
+#define DMA_CCR_DIR_FROM_MEM (1U << DMA_CCR_DIR_BIT)
#define DMA_CCR_TEIE (1U << DMA_CCR_TEIE_BIT)
#define DMA_CCR_HTIE (1U << DMA_CCR_HTIE_BIT)
#define DMA_CCR_TCIE (1U << DMA_CCR_TCIE_BIT)