diff options
author | Giovanni Di Sirio <gdisirio@gmail.com> | 2015-07-29 09:57:15 +0000 |
---|---|---|
committer | Giovanni Di Sirio <gdisirio@gmail.com> | 2015-07-29 09:57:15 +0000 |
commit | 5e5cb6651a739e36bcbd9bb07dd7aa537af9dbf0 (patch) | |
tree | f448972b027b4fd1130f742b8db411681eebcdad /os/hal/ports/STM32/LLD | |
parent | bbacae2118c4c05a477d93ec0aa356e63442f6e2 (diff) | |
download | ChibiOS-5e5cb6651a739e36bcbd9bb07dd7aa537af9dbf0.tar.gz ChibiOS-5e5cb6651a739e36bcbd9bb07dd7aa537af9dbf0.tar.bz2 ChibiOS-5e5cb6651a739e36bcbd9bb07dd7aa537af9dbf0.zip |
Added support for DMA channels sharing IRQs.
git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@8126 35acf78f-673a-0410-8e92-d51de3d6d3f4
Diffstat (limited to 'os/hal/ports/STM32/LLD')
-rw-r--r-- | os/hal/ports/STM32/LLD/DMAv1/notes.txt | 29 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c | 77 | ||||
-rw-r--r-- | os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h | 2 |
3 files changed, 89 insertions, 19 deletions
diff --git a/os/hal/ports/STM32/LLD/DMAv1/notes.txt b/os/hal/ports/STM32/LLD/DMAv1/notes.txt new file mode 100644 index 000000000..889365852 --- /dev/null +++ b/os/hal/ports/STM32/LLD/DMAv1/notes.txt @@ -0,0 +1,29 @@ +STM32 DMAv1 driver.
+
+Driver capability:
+
+- The driver supports the STM32 traditional DMA controller in the following
+ configurations: 5ch, 7ch, 7ch+5ch.
+- Support for automatic the channel selection through the CSELR register.
+- For devices without CSELR register it is possible to select channels but
+ the SYSCFG CFGR register is not configured, the user has to configure it
+ before starting the DMA driver.
+- The driver supports shared ISR handlers with a quirk: the IRQ priority is
+ established by the first allocated channel among the channels sharing the
+ ISR.
+
+The file registry must export:
+
+STM32_ADVANCED_DMA - TRUE if CSELR is present.
+STM32_DMAn_NUM_CHANNELS - Number of channels in DMA1.
+STM32_DMAn_CHx_HANDLER - Vector name for IRQ "x".
+STM32_DMAn_CHxyz_HANDLER - Vector name for shared IRQs "x", "y" and "z".
+STM32_DMAn_CHx_NUMBER - Vector number for IRQ "x".
+STM32_DMAn_CHxyz_NUMBER - Vector number for shared IRQs "x", "y" and "z".
+
+Currently supported shared combinations are:
+
+STM32_DMA1_CH23_HANDLER
+STM32_DMA1_CH23_NUMBER
+STM32_DMA1_CH4567_HANDLER
+STM32_DMA1_CH4567_NUMBER
diff --git a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c index 57a325c61..74db011d1 100644 --- a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c +++ b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.c @@ -78,6 +78,34 @@ #define ADDR_DMA2_CSELR NULL
#endif
+/*
+ * ISR collision masks.
+ */
+#define DMA1_CH1_CMASK 0x00000001U
+#if !defined(STM32_DMA1_CH23_NUMBER)
+#define DMA1_CH2_CMASK 0x00000002U
+#define DMA1_CH3_CMASK 0x00000004U
+#else
+#define DMA1_CH2_CMASK 0x00000006U
+#define DMA1_CH3_CMASK 0x00000006U
+#endif
+#if !defined(STM32_DMA1_CH4567_NUMBER)
+#define DMA1_CH4_CMASK 0x00000008U
+#define DMA1_CH5_CMASK 0x00000010U
+#define DMA1_CH6_CMASK 0x00000020U
+#define DMA1_CH7_CMASK 0x00000040U
+#else
+#define DMA1_CH4_CMASK 0x00000078U
+#define DMA1_CH5_CMASK 0x00000078U
+#define DMA1_CH6_CMASK 0x00000078U
+#define DMA1_CH7_CMASK 0x00000078U
+#endif
+#define DMA2_CH1_CMASK 0x00000080U
+#define DMA3_CH2_CMASK 0x00000100U
+#define DMA3_CH3_CMASK 0x00000200U
+#define DMA4_CH4_CMASK 0x00000400U
+#define DMA5_CH5_CMASK 0x00000800U
+
/*===========================================================================*/
/* Driver exported variables. */
/*===========================================================================*/
@@ -90,23 +118,23 @@ * instead: @p STM32_DMA1_STREAM1, @p STM32_DMA1_STREAM2 etc.
*/
const stm32_dma_stream_t _stm32_dma_streams[STM32_DMA_STREAMS] = {
- {DMA1_Channel1, &DMA1->IFCR, ADDR_DMA1_CSELR, 0, 0, STM32_DMA1_CH1_NUMBER},
- {DMA1_Channel2, &DMA1->IFCR, ADDR_DMA1_CSELR, 4, 1, STM32_DMA1_CH2_NUMBER},
- {DMA1_Channel3, &DMA1->IFCR, ADDR_DMA1_CSELR, 8, 2, STM32_DMA1_CH3_NUMBER},
- {DMA1_Channel4, &DMA1->IFCR, ADDR_DMA1_CSELR, 12, 3, STM32_DMA1_CH4_NUMBER},
- {DMA1_Channel5, &DMA1->IFCR, ADDR_DMA1_CSELR, 16, 4, STM32_DMA1_CH5_NUMBER},
+ {DMA1_Channel1, DMA1_CH1_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 0, 0, STM32_DMA1_CH1_NUMBER},
+ {DMA1_Channel2, DMA1_CH2_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 4, 1, STM32_DMA1_CH2_NUMBER},
+ {DMA1_Channel3, DMA1_CH3_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 8, 2, STM32_DMA1_CH3_NUMBER},
+ {DMA1_Channel4, DMA1_CH4_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 12, 3, STM32_DMA1_CH4_NUMBER},
+ {DMA1_Channel5, DMA1_CH5_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 16, 4, STM32_DMA1_CH5_NUMBER},
#if STM32_DMA1_NUM_CHANNELS > 5
- {DMA1_Channel6, &DMA1->IFCR, ADDR_DMA1_CSELR, 20, 5, STM32_DMA1_CH6_NUMBER},
+ {DMA1_Channel6, DMA1_CH6_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 20, 5, STM32_DMA1_CH6_NUMBER},
#endif
#if STM32_DMA1_NUM_CHANNELS > 6
- {DMA1_Channel7, &DMA1->IFCR, ADDR_DMA1_CSELR, 24, 6, STM32_DMA1_CH7_NUMBER},
+ {DMA1_Channel7, DMA1_CH7_CMASK, &DMA1->IFCR, ADDR_DMA1_CSELR, 24, 6, STM32_DMA1_CH7_NUMBER},
#endif
#if STM32_DMA2_NUM_CHANNELS > 0
- {DMA2_Channel1, &DMA2->IFCR, ADDR_DMA2_CSELR, 0, 8, STM32_DMA2_CH1_NUMBER},
- {DMA2_Channel2, &DMA2->IFCR, ADDR_DMA2_CSELR, 4, 9, STM32_DMA2_CH2_NUMBER},
- {DMA2_Channel3, &DMA2->IFCR, ADDR_DMA2_CSELR, 8, 10, STM32_DMA2_CH3_NUMBER},
- {DMA2_Channel4, &DMA2->IFCR, ADDR_DMA2_CSELR, 12, 11, STM32_DMA2_CH4_NUMBER},
- {DMA2_Channel5, &DMA2->IFCR, ADDR_DMA2_CSELR, 16, 13, STM32_DMA2_CH5_NUMBER},
+ {DMA2_Channel1, DMA2_CH1_CMASK, &DMA2->IFCR, ADDR_DMA2_CSELR, 0, 8, STM32_DMA2_CH1_NUMBER},
+ {DMA2_Channel2, DMA2_CH2_CMASK, &DMA2->IFCR, ADDR_DMA2_CSELR, 4, 9, STM32_DMA2_CH2_NUMBER},
+ {DMA2_Channel3, DMA2_CH3_CMASK, &DMA2->IFCR, ADDR_DMA2_CSELR, 8, 10, STM32_DMA2_CH3_NUMBER},
+ {DMA2_Channel4, DMA2_CH4_CMASK, &DMA2->IFCR, ADDR_DMA2_CSELR, 12, 11, STM32_DMA2_CH4_NUMBER},
+ {DMA2_Channel5, DMA2_CH5_CMASK, &DMA2->IFCR, ADDR_DMA2_CSELR, 16, 13, STM32_DMA2_CH5_NUMBER},
#endif
};
@@ -505,10 +533,9 @@ bool dmaStreamAllocate(const stm32_dma_stream_t *dmastp, if ((dma_streams_mask & (1U << dmastp->selfindex)) != 0U)
return true;
- /* Marks the stream as allocated.*/
+ /* Installs the DMA handler.*/
dma_isr_redir[dmastp->selfindex].dma_func = func;
dma_isr_redir[dmastp->selfindex].dma_param = param;
- dma_streams_mask |= (1U << dmastp->selfindex);
/* Enabling DMA clocks required by the current streams set.*/
if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) != 0U)
@@ -522,9 +549,15 @@ bool dmaStreamAllocate(const stm32_dma_stream_t *dmastp, dmaStreamDisable(dmastp);
dmastp->channel->CCR = STM32_DMA_CCR_RESET_VALUE;
- /* Enables the associated IRQ vector if a callback is defined.*/
- if (func != NULL)
+ /* Enables the associated IRQ vector if not alread enabled and if a
+ callback is defined.*/
+ if (((dma_streams_mask & dmastp->cmask) != 0U) &&
+ (func != NULL)) {
nvicEnableVector(dmastp->vector, priority);
+ }
+
+ /* Marks the stream as allocated.*/
+ dma_streams_mask |= (1U << dmastp->selfindex);
return false;
}
@@ -550,12 +583,18 @@ void dmaStreamRelease(const stm32_dma_stream_t *dmastp) { osalDbgAssert((dma_streams_mask & (1 << dmastp->selfindex)) != 0U,
"not allocated");
- /* Disables the associated IRQ vector.*/
- nvicDisableVector(dmastp->vector);
-
/* Marks the stream as not allocated.*/
dma_streams_mask &= ~(1 << dmastp->selfindex);
+ /* Disables the associated IRQ vector if it is no more in use.*/
+ if ((dma_streams_mask & dmastp->cmask) == 0U) {
+ nvicDisableVector(dmastp->vector);
+ }
+
+ /* Removes the DMA handler.*/
+ dma_isr_redir[dmastp->selfindex].dma_func = NULL;
+ dma_isr_redir[dmastp->selfindex].dma_param = NULL;
+
/* Shutting down clocks that are no more required, if any.*/
if ((dma_streams_mask & STM32_DMA1_STREAMS_MASK) == 0U)
rccDisableDMA1(false);
diff --git a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h index f8cf56dda..63e0c5cfc 100644 --- a/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h +++ b/os/hal/ports/STM32/LLD/DMAv1/stm32_dma.h @@ -201,6 +201,8 @@ */
typedef struct {
DMA_Channel_TypeDef *channel; /**< @brief Associated DMA channel. */
+ uint32_t cmask; /**< @brief Mask of streams sharing
+ the same ISR. */
volatile uint32_t *ifcr; /**< @brief Associated IFCR reg. */
volatile uint32_t *cselr; /**< @brief Associated CSELR reg. */
uint8_t shift; /**< @brief Bit offset in IFCR and
|