You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mynewt.apache.org by je...@apache.org on 2021/02/12 15:07:15 UTC
[mynewt-core] 01/03: mcu/stm: Add DMA allocation schema API
This is an automated email from the ASF dual-hosted git repository.
jerzy pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mynewt-core.git
commit 5bb45700b36bc8ac9e52677dcf6ced4118f0e1ce
Author: Jerzy Kasenberg <je...@codecoup.pl>
AuthorDate: Tue Jan 26 15:24:26 2021 +0100
mcu/stm: Add DMA allocation schema API
API for using ST HAL DMA functionality.
It allows to safely share DMA channels/streams.
All ST HAL uses same style functions for accessing
peripherals. This adds allocate/release functionality.
It also provides DMA interrupt handlers that will
call ST HAL handlers with currently allocated for channel
peripheral.
---
.../stm32_common/include/stm32_common/stm32_dma.h | 106 ++++++++
hw/mcu/stm/stm32_common/src/stm32_dma.c | 279 +++++++++++++++++++++
2 files changed, 385 insertions(+)
diff --git a/hw/mcu/stm/stm32_common/include/stm32_common/stm32_dma.h b/hw/mcu/stm/stm32_common/include/stm32_common/stm32_dma.h
new file mode 100644
index 0000000..2386a9f
--- /dev/null
+++ b/hw/mcu/stm/stm32_common/include/stm32_common/stm32_dma.h
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#ifndef __STM32_DMA_H_
+#define __STM32_DMA_H_
+
+#include <stm32_common/stm32_hal.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * Enum for DMA channel.
+ * For F0, F1, F3, L0, L1, L4, WB it represents channel
+ * For F4, F7 it represents stream (because channel has other meaning).
+ */
+typedef enum {
+ DMA1_CH0,
+ DMA1_CH1,
+ DMA1_CH2,
+ DMA1_CH3,
+ DMA1_CH4,
+ DMA1_CH5,
+ DMA1_CH6,
+ DMA1_CH7,
+ DMA2_CH0,
+ DMA2_CH1,
+ DMA2_CH2,
+ DMA2_CH3,
+ DMA2_CH4,
+ DMA2_CH5,
+ DMA2_CH6,
+ DMA2_CH7,
+ DMA_CH_NUM,
+} stm32_dma_ch_t;
+
+/**
+ * Allocate DMA channel for specific ST DMA handle.
+ *
+ * Function assigns DMA handle to DMA channel.
+ * This handle is later used in interrupt handlers.
+ *
+ * @param ch DMA channel id
+ * @param hdma DMA handle to assign to channel
+ * @return SYS_EBUSY - when channel is already allocated
+ * SYS_EOK - on success
+ */
+int stm32_dma_acquire_channel(stm32_dma_ch_t ch, DMA_HandleTypeDef *hdma);
+
+/**
+ * Release DMA channel.
+ *
+ * @param ch DMA channel that was allocated with stm32_dma_acquire_channel()
+ *
+ * @return SYS_EOK on success
+ * SYS_EINVAL if channel was not previously allocated
+ */
+int stm32_dma_release_channel(stm32_dma_ch_t ch);
+
+/*
+ * Functions that can be used as interrupt handlers that redirect
+ * code execution to ST HAL drivers.
+ */
+void stm32_dma1_0_irq_handler(void);
+void stm32_dma1_1_irq_handler(void);
+void stm32_dma1_2_irq_handler(void);
+void stm32_dma1_3_irq_handler(void);
+void stm32_dma1_4_irq_handler(void);
+void stm32_dma1_5_irq_handler(void);
+void stm32_dma1_6_irq_handler(void);
+void stm32_dma1_7_irq_handler(void);
+void stm32_dma2_0_irq_handler(void);
+void stm32_dma2_1_irq_handler(void);
+void stm32_dma2_2_irq_handler(void);
+void stm32_dma2_3_irq_handler(void);
+void stm32_dma2_4_irq_handler(void);
+void stm32_dma2_5_irq_handler(void);
+void stm32_dma2_6_irq_handler(void);
+void stm32_dma2_7_irq_handler(void);
+
+/* F0 and L0 can have common vector for several DMA channels */
+void stm32_dma1_2_3_irq_handler(void);
+void stm32_dma1_4_5_6_7_irq_handler(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __STM32_DMA_H_ */
diff --git a/hw/mcu/stm/stm32_common/src/stm32_dma.c b/hw/mcu/stm/stm32_common/src/stm32_dma.c
new file mode 100644
index 0000000..b2ab923
--- /dev/null
+++ b/hw/mcu/stm/stm32_common/src/stm32_dma.c
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include <assert.h>
+#include <os/os_trace_api.h>
+#include <stm32_common/stm32_dma.h>
+#include <defs/error.h>
+
+#ifdef DMA2
+DMA_HandleTypeDef *stm32_dma_ch[16];
+#else
+DMA_HandleTypeDef *stm32_dma_ch[8];
+#endif
+
+int
+stm32_dma_acquire_channel(stm32_dma_ch_t ch, DMA_HandleTypeDef *hdma)
+{
+ int rc = SYS_EBUSY;
+ int sr;
+
+ OS_ENTER_CRITICAL(sr);
+
+ if (ch <= DMA_CH_NUM && stm32_dma_ch[ch] == NULL) {
+ stm32_dma_ch[ch] = hdma;
+ rc = SYS_EOK;
+ }
+
+ OS_EXIT_CRITICAL(sr);
+
+ return rc;
+}
+
+int
+stm32_dma_release_channel(stm32_dma_ch_t ch)
+{
+ int rc = SYS_EINVAL;
+ int sr;
+
+ OS_ENTER_CRITICAL(sr);
+
+ if (stm32_dma_ch[ch]) {
+ stm32_dma_ch[ch] = NULL;
+ rc = SYS_EOK;
+ }
+ OS_EXIT_CRITICAL(sr);
+
+ return rc;
+}
+
+void
+stm32_dma1_0_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH0]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_1_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH1]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_2_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH2]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_3_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH3]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_4_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH4]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_5_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH5]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_6_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH6]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_7_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH7]);
+
+ os_trace_isr_exit();
+}
+
+#ifdef DMA2
+
+void
+stm32_dma2_0_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH0]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_1_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH1]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_2_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH2]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_3_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH3]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_4_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH4]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_5_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH5]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_6_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH6]);
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma2_7_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH7]);
+
+ os_trace_isr_exit();
+}
+
+#endif
+
+/*
+ * Next two handlers are used by F0 and L0 devices that have shared interrupt for
+ * several channels.
+ */
+void
+stm32_dma1_2_3_irq_handler(void)
+{
+ os_trace_isr_enter();
+
+ if (stm32_dma_ch[DMA1_CH2]) {
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH2]);
+ }
+ if (stm32_dma_ch[DMA1_CH3]) {
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA1_CH3]);
+ }
+#ifdef DMA2
+ if (stm32_dma_ch[DMA2_CH1]) {
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH1]);
+ }
+ if (stm32_dma_ch[DMA2_CH2]) {
+ HAL_DMA_IRQHandler(stm32_dma_ch[DMA2_CH2]);
+ }
+#endif
+
+ os_trace_isr_exit();
+}
+
+void
+stm32_dma1_4_5_6_7_irq_handler(void)
+{
+ stm32_dma_ch_t i;
+
+ os_trace_isr_enter();
+
+ for (i = DMA1_CH4; i <= DMA1_CH7; ++i) {
+ if (stm32_dma_ch[i]) {
+ HAL_DMA_IRQHandler(stm32_dma_ch[i]);
+ }
+ }
+#ifdef DMA2
+ for (i = DMA2_CH3; i <= DMA2_CH5; ++i) {
+ if (stm32_dma_ch[i]) {
+ HAL_DMA_IRQHandler(stm32_dma_ch[i]);
+ }
+ }
+#endif
+
+ os_trace_isr_exit();
+}
+