aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libopencm3/stm32/f1/dma.h59
-rw-r--r--lib/stm32/f1/dma.c82
2 files changed, 118 insertions, 23 deletions
diff --git a/include/libopencm3/stm32/f1/dma.h b/include/libopencm3/stm32/f1/dma.h
index b08803f..6e5cc20 100644
--- a/include/libopencm3/stm32/f1/dma.h
+++ b/include/libopencm3/stm32/f1/dma.h
@@ -141,9 +141,30 @@ LGPL License Terms @ref lgpl_license
/* --- DMA_ISR values ------------------------------------------------------ */
+/* --- DMA Interrupt Flag offset values ------------------------------------- */
+/* These are based on every interrupt flag and flag clear being at the same relative location */
+/** @defgroup dma_if_offset DMA Interrupt Flag Offsets within stream flag group.
+@ingroup STM32F1xx_dma_defines
+
+@{*/
+/** Transfer Error Interrupt Flag */
+#define DMA_TEIF (1 << 3)
+/** Half Transfer Interrupt Flag */
+#define DMA_HTIF (1 << 2)
+/** Transfer Complete Interrupt Flag */
+#define DMA_TCIF (1 << 1)
+/** Global Interrupt Flag */
+#define DMA_GIF (1 << 0)
+/**@}*/
+
+/* Offset within interrupt status register to start of stream interrupt flag field */
+#define DMA_FLAG_OFFSET(channel) (4*(channel - 1))
+#define DMA_FLAGS (DMA_TEIF | DMA_TCIF | DMA_HTIF | DMA_GIF)
+#define DMA_ISR_MASK(channel) DMA_FLAGS << DMA_FLAG_OFFSET(channel)
+
/* TEIF: Transfer error interrupt flag */
-#define DMA_ISR_TEIF_BIT (1 << 3)
-#define DMA_ISR_TEIF(channel) (DMA_ISR_TEIF_BIT << (4 * ((channel) -1)))
+#define DMA_ISR_TEIF_BIT DMA_ISR_TEIF
+#define DMA_ISR_TEIF(channel) (DMA_ISR_TEIF_BIT << DMA_FLAG_OFFSET(channel)))
#define DMA_ISR_TEIF1 DMA_ISR_TEIF(DMA_CHANNEL1)
#define DMA_ISR_TEIF2 DMA_ISR_TEIF(DMA_CHANNEL2)
@@ -154,8 +175,8 @@ LGPL License Terms @ref lgpl_license
#define DMA_ISR_TEIF7 DMA_ISR_TEIF(DMA_CHANNEL7)
/* HTIF: Half transfer interrupt flag */
-#define DMA_ISR_HTIF_BIT (1 << 2)
-#define DMA_ISR_HTIF(channel) (DMA_ISR_HTIF_BIT << (4 * ((channel) -1)))
+#define DMA_ISR_HTIF_BIT DMA_HTIF
+#define DMA_ISR_HTIF(channel) (DMA_ISR_HTIF_BIT << DMA_FLAG_OFFSET(channel)))
#define DMA_ISR_HTIF1 DMA_ISR_HTIF(DMA_CHANNEL1)
#define DMA_ISR_HTIF2 DMA_ISR_HTIF(DMA_CHANNEL2)
@@ -166,8 +187,8 @@ LGPL License Terms @ref lgpl_license
#define DMA_ISR_HTIF7 DMA_ISR_HTIF(DMA_CHANNEL7)
/* TCIF: Transfer complete interrupt flag */
-#define DMA_ISR_TCIF_BIT (1 << 1)
-#define DMA_ISR_TCIF(channel) (DMA_ISR_TCIF_BIT << (4 * ((channel) -1)))
+#define DMA_ISR_TCIF_BIT DMA_TCIF
+#define DMA_ISR_TCIF(channel) (DMA_ISR_TCIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_ISR_TCIF1 DMA_ISR_TCIF(DMA_CHANNEL1)
#define DMA_ISR_TCIF2 DMA_ISR_TCIF(DMA_CHANNEL2)
@@ -178,8 +199,8 @@ LGPL License Terms @ref lgpl_license
#define DMA_ISR_TCIF7 DMA_ISR_TCIF(DMA_CHANNEL7)
/* GIF: Global interrupt flag */
-#define DMA_ISR_GIF_BIT (1 << 0)
-#define DMA_ISR_GIF(channel) (DMA_ISR_GIF_BIT << (4 * ((channel) -1)))
+#define DMA_ISR_GIF_BIT DMA_GIF
+#define DMA_ISR_GIF(channel) (DMA_ISR_GIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_ISR_GIF1 DMA_ISR_GIF(DMA_CHANNEL1)
#define DMA_ISR_GIF2 DMA_ISR_GIF(DMA_CHANNEL2)
@@ -192,8 +213,8 @@ LGPL License Terms @ref lgpl_license
/* --- DMA_IFCR values ----------------------------------------------------- */
/* CTEIF: Transfer error clear */
-#define DMA_IFCR_CTEIF_BIT (1 << 3)
-#define DMA_IFCR_CTEIF(channel) (DMA_IFCR_CTEIF_BIT << (4 * ((channel) -1)))
+#define DMA_IFCR_CTEIF_BIT DMA_TEIF
+#define DMA_IFCR_CTEIF(channel) (DMA_IFCR_CTEIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_IFCR_CTEIF1 DMA_IFCR_CTEIF(DMA_CHANNEL1)
#define DMA_IFCR_CTEIF2 DMA_IFCR_CTEIF(DMA_CHANNEL2)
@@ -204,8 +225,8 @@ LGPL License Terms @ref lgpl_license
#define DMA_IFCR_CTEIF7 DMA_IFCR_CTEIF(DMA_CHANNEL7)
/* CHTIF: Half transfer clear */
-#define DMA_IFCR_CHTIF_BIT (1 << 2)
-#define DMA_IFCR_CHTIF(channel) (DMA_IFCR_CHTIF_BIT << (4 * ((channel) -1)))
+#define DMA_IFCR_CHTIF_BIT DMA_HTIF
+#define DMA_IFCR_CHTIF(channel) (DMA_IFCR_CHTIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_IFCR_CHTIF1 DMA_IFCR_CHTIF(DMA_CHANNEL1)
#define DMA_IFCR_CHTIF2 DMA_IFCR_CHTIF(DMA_CHANNEL2)
@@ -216,8 +237,8 @@ LGPL License Terms @ref lgpl_license
#define DMA_IFCR_CHTIF7 DMA_IFCR_CHTIF(DMA_CHANNEL7)
/* CTCIF: Transfer complete clear */
-#define DMA_IFCR_CTCIF_BIT (1 << 1)
-#define DMA_IFCR_CTCIF(channel) (DMA_IFCR_CTCIF_BIT << (4 * ((channel) -1)))
+#define DMA_IFCR_CTCIF_BIT DMA_TCIF
+#define DMA_IFCR_CTCIF(channel) (DMA_IFCR_CTCIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_IFCR_CTCIF1 DMA_IFCR_CTCIF(DMA_CHANNEL1)
#define DMA_IFCR_CTCIF2 DMA_IFCR_CTCIF(DMA_CHANNEL2)
@@ -228,8 +249,8 @@ LGPL License Terms @ref lgpl_license
#define DMA_IFCR_CTCIF7 DMA_IFCR_CTCIF(DMA_CHANNEL7)
/* CGIF: Global interrupt clear */
-#define DMA_IFCR_CGIF_BIT (1 << 0)
-#define DMA_IFCR_CGIF(channel) (DMA_IFCR_CGIF_BIT << (4 * ((channel) -1)))
+#define DMA_IFCR_CGIF_BIT DMA_GIF
+#define DMA_IFCR_CGIF(channel) (DMA_IFCR_CGIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_IFCR_CGIF1 DMA_IFCR_CGIF(DMA_CHANNEL1)
#define DMA_IFCR_CGIF2 DMA_IFCR_CGIF(DMA_CHANNEL2)
@@ -241,7 +262,7 @@ LGPL License Terms @ref lgpl_license
/* Clear interrupts mask */
#define DMA_IFCR_CIF_BIT 0xF
-#define DMA_IFCR_CIF(channel) (DMA_IFCR_CIF_BIT << (4 * ((channel) - 1)))
+#define DMA_IFCR_CIF(channel) (DMA_IFCR_CIF_BIT << (DMA_FLAG_OFFSET(channel)))
#define DMA_IFCR_CIF1 DMA_IFCR_CIF(DMA_CHANNEL1)
#define DMA_IFCR_CIF2 DMA_IFCR_CIF(DMA_CHANNEL2)
@@ -349,12 +370,16 @@ LGPL License Terms @ref lgpl_license
BEGIN_DECLS
void dma_channel_reset(u32 dma, u8 channel);
+void dma_clear_interrupt_flags(u32 dma, u8 channel, u32 interrupts);
+bool dma_get_interrupt_flag(u32 dma, u8 channel, u32 interrupts);
void dma_enable_mem2mem_mode(u32 dma, u8 channel);
void dma_set_priority(u32 dma, u8 channel, u32 prio);
void dma_set_memory_size(u32 dma, u8 channel, u32 mem_size);
void dma_set_peripheral_size(u32 dma, u8 channel, u32 peripheral_size);
void dma_enable_memory_increment_mode(u32 dma, u8 channel);
+void dma_disable_memory_increment_mode(u32 dma, u8 channel);
void dma_enable_peripheral_increment_mode(u32 dma, u8 channel);
+void dma_disable_peripheral_increment_mode(u32 dma, u8 channel);
void dma_enable_circular_mode(u32 dma, u8 channel);
void dma_set_read_from_peripheral(u32 dma, u8 channel);
void dma_set_read_from_memory(u32 dma, u8 channel);
diff --git a/lib/stm32/f1/dma.c b/lib/stm32/f1/dma.c
index 04cb8a1..c26020a 100644
--- a/lib/stm32/f1/dma.c
+++ b/lib/stm32/f1/dma.c
@@ -10,12 +10,18 @@
@date 18 August 2012
-This library supports the DMA
-Control System in the STM32F1xx series of ARM Cortex Microcontrollers
-by ST Microelectronics. It can provide for two DMA controllers,
-one with 7 channels and one with 5. Channels are hardware dedicated
-and each is shared with a number of different sources (only one can be
-used at a time, under the responsibility of the programmer).
+This library supports the DMA Control System in the STM32 series of ARM Cortex
+Microcontrollers by ST Microelectronics.
+
+Up to two DMA controllers are supported. 12 DMA channels are allocated 7 to
+the first DMA controller and 5 to the second. Each channel is connected to
+between 3 and 6 hardware peripheral DMA signals in a logical OR arrangement.
+
+DMA transfers can be configured to occur between peripheral and memory in
+any combination including memory to memory. Circular mode transfers are
+also supported in transfers involving a peripheral. An arbiter is provided
+to resolve priority DMA requests. Transfers can be made with 8, 16 or 32 bit
+words.
LGPL License Terms @ref lgpl_license
*/
@@ -68,6 +74,42 @@ void dma_channel_reset(u32 dma, u8 channel)
}
/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Clear Interrupt Flag
+
+The interrupt flag for the channel is cleared. More than one interrupt for the
+same channel may be cleared by using the logical OR of the interrupt flags.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: @ref dma_st_number
+@param[in] interrupts unsigned int32. Logical OR of interrupt numbers: @ref dma_if_offset
+*/
+
+void dma_clear_interrupt_flags(u32 dma, u8 channel, u32 interrupts)
+{
+/* Get offset to interrupt flag location in channel field */
+ u32 flags = (interrupts << DMA_FLAG_OFFSET(channel));
+ DMA_IFCR(dma) = flags;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Read Interrupt Flag
+
+The interrupt flag for the channel is returned.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: @ref dma_st_number
+@param[in] interrupt unsigned int32. Interrupt number: @ref dma_st_number
+@returns bool interrupt flag is set.
+*/
+
+bool dma_get_interrupt_flag(u32 dma, u8 channel, u32 interrupt)
+{
+/* get offset to interrupt flag location in channel field. */
+ u32 flag = (interrupt << DMA_FLAG_OFFSET(channel));
+ return ((DMA_ISR(dma) & flag) > 0);
+}
+
+/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory to Memory Transfers
Memory to memory transfers do not require a trigger to activate each transfer.
@@ -160,12 +202,40 @@ void dma_enable_memory_increment_mode(u32 dma, u8 channel)
@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
*/
+void dma_disable_memory_increment_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_MINC;
+}
+
+/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Enable Peripheral Increment after Transfer
+
+Following each transfer the current peripheral address is incremented by
+1, 2 or 4 depending on the data size set in @ref dma_set_peripheral_size. The
+value held by the base peripheral address register is unchanged.
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
void dma_enable_peripheral_increment_mode(u32 dma, u8 channel)
{
DMA_CCR(dma, channel) |= DMA_CCR_PINC;
}
/*-----------------------------------------------------------------------------*/
+/** @brief DMA Channel Disable Peripheral Increment after Transfer
+
+@param[in] dma unsigned int32. DMA controller base address: DMA1 or DMA2
+@param[in] channel unsigned int8. Channel number: 1-7 for DMA1 or 1-5 for DMA2
+*/
+
+void dma_disable_peripheral_increment_mode(u32 dma, u8 channel)
+{
+ DMA_CCR(dma, channel) &= ~DMA_CCR_PINC;
+}
+
+/*-----------------------------------------------------------------------------*/
/** @brief DMA Channel Enable Memory Circular Mode
After the number of bytes/words to be transferred has been completed, the