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 <jerzy.kasenb...@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(); +} +