diff --git a/os/hal/ports/STM32/LLD/MDMAv1/driver.mk b/os/hal/ports/STM32/LLD/MDMAv1/driver.mk new file mode 100644 index 000000000..d10e2add0 --- /dev/null +++ b/os/hal/ports/STM32/LLD/MDMAv1/driver.mk @@ -0,0 +1,2 @@ +PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c +PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/MDMAv1 diff --git a/os/hal/ports/STM32/LLD/MDMAv1/notes.txt b/os/hal/ports/STM32/LLD/MDMAv1/notes.txt new file mode 100644 index 000000000..a092556a6 --- /dev/null +++ b/os/hal/ports/STM32/LLD/MDMAv1/notes.txt @@ -0,0 +1,11 @@ +STM32 MDMAv1 driver. + +Driver capability: + +- The driver supports the STM32 complex MDMA controller found on H7 + sub-family. + +The file registry must export: + +STM32_MDMA_CHn_HANDLER - Vector name for channel "n" (0..15). +STM32_MDMA_CHn_NUMBER - Vector number for channel "n" (0..15). diff --git a/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c new file mode 100644 index 000000000..997c47855 --- /dev/null +++ b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.c @@ -0,0 +1,541 @@ +/* + ChibiOS - Copyright (C) 2006..2018 Giovanni Di Sirio + + Licensed 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. +*/ + +/** + * @file MDMAv1/stm32_mdma.c + * @brief MDMA helper driver code. + * + * @addtogroup STM32_MDMA + * @details MDMA sharing helper driver. In the STM32 the MDMA channels are a + * shared resource, this driver allows to allocate and free MDMA + * STM32 at runtime in order to allow all the other device + * drivers to coordinate the access to the resource. + * @note The MDMA ISR handlers are all declared into this module because + * sharing, the various device drivers can associate a callback to + * ISRs when allocating channels. + * @{ + */ + +#include "hal.h" + +/* The following macro is only defined if some driver requiring MDMA services + has been enabled.*/ +#if defined(STM32_MDMA_REQUIRED) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** + * @brief MDMA channels descriptors. + * @details This table keeps the association between an unique channel + * identifier and the involved physical registers. + * @note Don't use this array directly, use the appropriate wrapper macros + * instead: @p STM32_MDMA_CHANNEL0, @p STM32_MDMA_CHANNEL1 etc. + */ +const stm32_mdma_channel_t __stm32_mdma_channels[STM32_MDMA_CHANNELS] = { + {MDMA_Channel0, 0, STM32_MDMA_CH0_NUMBER}, + {MDMA_Channel1, 1, STM32_MDMA_CH1_NUMBER}, + {MDMA_Channel2, 2, STM32_MDMA_CH2_NUMBER}, + {MDMA_Channel3, 3, STM32_MDMA_CH3_NUMBER}, + {MDMA_Channel4, 4, STM32_MDMA_CH4_NUMBER}, + {MDMA_Channel5, 5, STM32_MDMA_CH5_NUMBER}, + {MDMA_Channel6, 6, STM32_MDMA_CH6_NUMBER}, + {MDMA_Channel7, 7, STM32_MDMA_CH7_NUMBER}, + {MDMA_Channel8, 8, STM32_MDMA_CH8_NUMBER}, + {MDMA_Channel9, 9, STM32_MDMA_CH9_NUMBER}, + {MDMA_Channel10, 10, STM32_MDMA_CH10_NUMBER}, + {MDMA_Channel11, 11, STM32_MDMA_CH11_NUMBER}, + {MDMA_Channel12, 12, STM32_MDMA_CH12_NUMBER}, + {MDMA_Channel13, 13, STM32_MDMA_CH13_NUMBER}, + {MDMA_Channel14, 14, STM32_MDMA_CH14_NUMBER}, + {MDMA_Channel15, 15, STM32_MDMA_CH15_NUMBER}, +}; + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/** + * @brief Global MDMA-related data structures. + */ +static struct { + /** + * @brief Mask of the allocated channels. + */ + uint32_t allocated_mask; + /** + * @brief MDMA IRQ redirectors. + */ + struct { + /** + * @brief MDMA callback function. + */ + stm32_mdmaisr_t func; + /** + * @brief MDMA callback parameter. + */ + void *param; + } channels[STM32_MDMA_CHANNELS]; +} mdma; + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +static void mdma_serve_interrupt(const stm32_mdma_channel_t *mdmachp) { + uint32_t idx = mdmachp->selfindex; + uint32_t flags = mdmachp->channel->CISR; + mdmachp->channel->CIFCR = flags; + if (mdma.channels[idx].func != NULL) { + mdma.channels[idx].func(mdma.channels[idx].param, flags); + } +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +/** + * @brief MDMA channel 0 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH0_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL0); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 1 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH1_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 2 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH2_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 3 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH3_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 4 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH4_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL4); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 5 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH5_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL5); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 6 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH6_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL6); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 7 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH7_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL7); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 8 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH8_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL8); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 9 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH9_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL9); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 10 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH10_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL10); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 11 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH11_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL11); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 12 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH12_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL12); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 13 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH13_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL13); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 14 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH14_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL14); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief MDMA channel 15 shared interrupt handler. + * + * @isr + */ +OSAL_IRQ_HANDLER(STM32_MDMA_CH15_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + mdma_serve_interrupt(STM32_MDMA_CHANNEL15); + + OSAL_IRQ_EPILOGUE(); +} + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief STM32 MDMA helper initialization. + * + * @init + */ +void mdmaInit(void) { + unsigned i; + + mdma.allocated_mask = 0U; + for (i = 0U; i < STM32_MDMA_CHANNELS; i++) { + mdma.channels[i].func = NULL; + __stm32_dma_channels[i].channel->CCR = STM32_MDMA_CCR_RESET_VALUE; + __stm32_dma_channels[i].channel->CTCR = STM32_MDMA_CTCR_RESET_VALUE; + __stm32_dma_channels[i].channel->CIFCR = STM32_MDMA_CIFCR_CTEIF | + STM32_MDMA_CIFCR_CBRTIF | + STM32_MDMA_CIFCR_CBRTIF | + STM32_MDMA_CIFCR_CCTCIF | + STM32_MDMA_CIFCR_CTEIF; + } +} + +/** + * @brief Allocates an MDMA channel. + * @details The channel is allocated and, if required, the MDMA clock enabled. + * The function also enables the IRQ vector associated to the channel + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific channel or: + * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel. + * . + * @param[in] priority IRQ priority for the MDMA channel + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_mdma_channel_t + * structure. + * @retval NULL if a/the channel is not available. + * + * @iclass + */ +const stm32_mdma_channel_t *dmaChannelAllocI(uint32_t id, + uint32_t priority, + stm32_mdmaisr_t func, + void *param) { + uint32_t i, startid, endid; + + osalDbgCheckClassI(); + + if (id < STM32_MDMA_CHANNELS) { + startid = id; + endid = id; + } + else if (id == STM32_MDMA_CHANNEL_ID_ANY) { + startid = 0U; + endid = STM32_MDMA_CHANNELS - 1U; + } + else { + osalDbgCheck(false); + return NULL; + } + + for (i = startid; i <= endid; i++) { + uint32_t mask = (1U << i); + if ((mdma.allocated_mask & mask) == 0U) { + const stm32_mdma_channel_t *mdmachp = STM32_MDMA_CHANNEL(i); + + /* Installs the MDMA handler.*/ + mdma.channels[i].func = func; + mdma.channels[i].param = param; + mdma.allocated_mask |= mask; + + /* Enabling MDMA clocks required by the current channels set.*/ + if (mdma.allocated_mask != 0U) { + rccEnableMDMA(true); + } + + /* Enables the associated IRQ vector if a callback is defined.*/ + if (func != NULL) { + nvicEnableVector(mdmachp->vector, priority); + } + + return mdmachp; + } + } + + return NULL; +} + +/** + * @brief Allocates a MDMA channel. + * @details The channel is allocated and, if required, the MDMA clock enabled. + * The function also enables the IRQ vector associated to the channel + * and initializes its priority. + * + * @param[in] id numeric identifiers of a specific channel or: + * - @p STM32_MDMA_CHANNEL_ID_ANY for any channel. + * . + * @param[in] priority IRQ priority for the MDMA channel + * @param[in] func handling function pointer, can be @p NULL + * @param[in] param a parameter to be passed to the handling function + * @return Pointer to the allocated @p stm32_mdma_channel_t + * structure. + * @retval NULL if a/the channel is not available. + * + * @api + */ +const stm32_mdma_channel_t *dmaChannelAlloc(uint32_t id, + uint32_t priority, + stm32_mdmaisr_t func, + void *param) { + const stm32_mdma_channel_t *mdmachp; + + osalSysLock(); + mdmachp = mdmaChannelAllocI(id, priority, func, param); + osalSysUnlock(); + + return mdmachp; +} + +/** + * @brief Releases a MDMA channel. + * @details The channel is freed and, if required, the MDMA clock disabled. + * Trying to release a unallocated channel is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @iclass + */ +void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp) { + + osalDbgCheck(mdmachp != NULL); + + /* Check if the channels is not taken.*/ + osalDbgAssert((dma.allocated_mask & (1U << mmdmachp->selfindex)) != 0U, + "not allocated"); + + /* Disables the associated IRQ vector.*/ + nvicDisableVector(mdmachp->vector); + + /* Marks the channel as not allocated.*/ + mdma.allocated_mask &= ~(1U << mmdmachp->selfindex); + + /* Shutting down clocks that are no more required, if any.*/ + if (dma.allocated_mask == 0U) { + rccDisableMDMA(); + } +} + +/** + * @brief Releases a MDMA channel. + * @details The channel is freed and, if required, the MDMA clock disabled. + * Trying to release a unallocated channel is an illegal operation + * and is trapped if assertions are enabled. + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @api + */ +void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp) { + + osalSysLock(); + mdmaChannelFreeI(mdmachp); + osalSysUnlock(); +} + +/** + * @brief MDMA stream disable. + * @details The function disables the specified stream, waits for the disable + * operation to complete and then clears any pending interrupt. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @xclass + */ +void mdmaStreamDisableX(const stm32_mdma_channel_t *mdmachp) { + uint32_t ccr = mdmachp->channel->CCR; + + /* Clearing CCR regardless of previous state.*/ + mdmachp->channel->CCR &= ~(STM32_MDMA_CCR_TCIE | STM32_MDMA_CCR_BTIE | + STM32_MDMA_CCR_BRTIE | STM32_MDMA_CCR_CTCIE | + STM32_MDMA_CCR_TEIE | STM32_MDMA_CCR_EN); + + /* If the channel was enabled then waiting for ongoing operations + to finish.*/ + if ((ccr & STM32_MDMA_CCR_EN) != 0U) { + while (((mdmachp)->channel->CISR & STM32_MDMA_CISR_CTCIF) == 0U) + ; + } + + /* Clearing IRQ sources.*/ + mdmaStreamClearInterruptX(mdmachp); +} + +#endif /* defined(STM32_MDMA_REQUIRED) */ + +/** @} */ diff --git a/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h new file mode 100644 index 000000000..9fb26ccb3 --- /dev/null +++ b/os/hal/ports/STM32/LLD/MDMAv1/stm32_mdma.h @@ -0,0 +1,560 @@ +/* + ChibiOS - Copyright (C) 2006..2019 Giovanni Di Sirio + + Licensed 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. +*/ + +/** + * @file MDMAv1/stm32_mdma.h + * @brief MDMA helper driver header. + * + * @addtogroup STM32_MDMA + * @{ + */ + +#ifndef STM32_MDMA_H +#define STM32_MDMA_H + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Total number of MDMA streams. + */ +#define STM32_MDMA_CHANNELS 16U + +/** + * @brief Mask of the ISR bits passed to the MDMA callback functions. + */ +#define STM32_MDMA_ISR_MASK 0x1FU + +/** + * @brief Checks if a MDMA priority is within the valid range. + * @param[in] prio MDMA priority + * + * @retval The check result. + * @retval false invalid MDMA priority. + * @retval true correct MDMA priority. + */ +#define STM32_MDMA_IS_VALID_PRIORITY(prio) (((prio) >= 0U) && ((prio) <= 3U)) + +/** + * @brief Special stream identifier + */ +#define STM32_MDMA_CHANNEL_ID_ANY STM32_MDMA_CHANNELS + +/** + * @name MDMA streams identifiers + * @{ + */ +/** + * @brief Returns a pointer to a stm32_mdma_channel_t structure. + * + * @param[in] id the stream numeric identifier + * @return A pointer to the stm32_mdma_channel_t constant structure + * associated to the MDMA stream. + */ +#define STM32_MDMA_CHANNEL(id) (&__stm32_mdma_channels[id]) + +#define STM32_MDMA_CHANNEL0 STM32_MDMA_CHANNEL(0) +#define STM32_MDMA_CHANNEL1 STM32_MDMA_CHANNEL(1) +#define STM32_MDMA_CHANNEL2 STM32_MDMA_CHANNEL(2) +#define STM32_MDMA_CHANNEL3 STM32_MDMA_CHANNEL(3) +#define STM32_MDMA_CHANNEL4 STM32_MDMA_CHANNEL(4) +#define STM32_MDMA_CHANNEL5 STM32_MDMA_CHANNEL(5) +#define STM32_MDMA_CHANNEL6 STM32_MDMA_CHANNEL(6) +#define STM32_MDMA_CHANNEL7 STM32_MDMA_CHANNEL(7) +#define STM32_MDMA_CHANNEL8 STM32_MDMA_CHANNEL(8) +#define STM32_MDMA_CHANNEL9 STM32_MDMA_CHANNEL(9) +#define STM32_MDMA_CHANNEL10 STM32_MDMA_CHANNEL(10) +#define STM32_MDMA_CHANNEL11 STM32_MDMA_CHANNEL(11) +#define STM32_MDMA_CHANNEL12 STM32_MDMA_CHANNEL(12) +#define STM32_MDMA_CHANNEL13 STM32_MDMA_CHANNEL(13) +#define STM32_MDMA_CHANNEL14 STM32_MDMA_CHANNEL(14) +#define STM32_MDMA_CHANNEL15 STM32_MDMA_CHANNEL(15) +/** @} */ + +/** + * @name CISR register constants + * @{ + */ +#define STM32_MDMA_CISR_TEIF (1U << 0) +#define STM32_MDMA_CISR_CTCIF (1U << 1) +#define STM32_MDMA_CISR_BRTIF (1U << 2) +#define STM32_MDMA_CISR_BTIF (1U << 3) +#define STM32_MDMA_CISR_TCIF (1U << 4) +#define STM32_MDMA_CISR_CRQA (1U << 16) +/** @} */ + +/** + * @name CIFCR register constants + * @{ + */ +#define STM32_MDMA_CIFCR_CTEIF (1U << 0) +#define STM32_MDMA_CIFCR_CCTCIF (1U << 1) +#define STM32_MDMA_CIFCR_CBRTIF (1U << 2) +#define STM32_MDMA_CIFCR_CBTIF (1U << 3) +#define STM32_MDMA_CIFCR_CTCIF (1U << 4) +/** @} */ + +/** + * @name CESR register constants + * @{ + */ +#define STM32_MDMA_CESR_TEA_MASK (127U << 0) +#define STM32_MDMA_CESR_TED (1U << 7) +#define STM32_MDMA_CESR_TELD (1U << 8) +#define STM32_MDMA_CESR_TEMD (1U << 9) +#define STM32_MDMA_CESR_ASE (1U << 10) +#define STM32_MDMA_CESR_BSE (1U << 11) +/** @} */ + +/** + * @name CCR register constants + * @{ + */ +#define STM32_MDMA_CCR_RESET_VALUE 0x00000000U +#define STM32_MDMA_CCR_EN (1U << 0) +#define STM32_MDMA_CCR_TEIE (1U << 1) +#define STM32_MDMA_CCR_CTCIE (1U << 2) +#define STM32_MDMA_CCR_BRTIE (1U << 3) +#define STM32_MDMA_CCR_BTIE (1U << 4) +#define STM32_MDMA_CCR_TCIE (1U << 5) +#define STM32_MDMA_CCR_PL_MASK (3U << 6) +#define STM32_MDMA_CCR_PL(n) ((n) << 6) +#define STM32_MDMA_CCR_BEX (1U << 12) +#define STM32_MDMA_CCR_HEX (1U << 13) +#define STM32_MDMA_CCR_WEX (1U << 14) +#define STM32_MDMA_CCR_SWRQ (1U << 16) +/** @} */ + +/** + * @name CTCR register constants + * @{ + */ +#define STM32_MDMA_CTCR_RESET_VALUE 0x00000000U + +#define STM32_MDMA_CTCR_SINC_MASK (3U << 0) +#define STM32_MDMA_CTCR_SINC(n) ((n) << 0) +#define STM32_MDMA_CTCR_SINC_FIXED STM32_MDMA_CTCR_SINC(0U) +#define STM32_MDMA_CTCR_SINC_INC STM32_MDMA_CTCR_SINC(1U) +#define STM32_MDMA_CTCR_SINC_DEC STM32_MDMA_CTCR_SINC(3U) + +#define STM32_MDMA_CTCR_DINC_MASK (3U << 2) +#define STM32_MDMA_CTCR_DINC(n) ((n) << 2) +#define STM32_MDMA_CTCR_DINC_FIXED STM32_MDMA_CTCR_DINC(0U) +#define STM32_MDMA_CTCR_DINC_INC STM32_MDMA_CTCR_DINC(1U) +#define STM32_MDMA_CTCR_DINC_DEC STM32_MDMA_CTCR_DINC(3U) + +#define STM32_MDMA_CTCR_SSIZE_MASK (3U << 4) +#define STM32_MDMA_CTCR_SSIZE(n) ((n) << 4) +#define STM32_MDMA_CTCR_SSIZE_BYTE STM32_MDMA_CTCR_SSIZE(0U) +#define STM32_MDMA_CTCR_SSIZE_HALF STM32_MDMA_CTCR_SSIZE(1U) +#define STM32_MDMA_CTCR_SSIZE_WORD STM32_MDMA_CTCR_SSIZE(2U) +#define STM32_MDMA_CTCR_SSIZE_DWORD STM32_MDMA_CTCR_SSIZE(3U) + +#define STM32_MDMA_CTCR_DSIZE_MASK (3U << 6) +#define STM32_MDMA_CTCR_DSIZE(n) ((n) << 6) +#define STM32_MDMA_CTCR_DSIZE_BYTE STM32_MDMA_CTCR_DSIZE(0U) +#define STM32_MDMA_CTCR_DSIZE_HALF STM32_MDMA_CTCR_DSIZE(1U) +#define STM32_MDMA_CTCR_DSIZE_WORD STM32_MDMA_CTCR_DSIZE(2U) +#define STM32_MDMA_CTCR_DSIZE_DWORD STM32_MDMA_CTCR_DSIZE(3U) + +#define STM32_MDMA_CTCR_SINCOS_MASK (3U << 8) +#define STM32_MDMA_CTCR_SINCOS(n) ((n) << 8) +#define STM32_MDMA_CTCR_SINCOS_BYTE STM32_MDMA_CTCR_SINCOS(0U) +#define STM32_MDMA_CTCR_SINCOS_HALF STM32_MDMA_CTCR_SINCOS(1U) +#define STM32_MDMA_CTCR_SINCOS_WORD STM32_MDMA_CTCR_SINCOS(2U) +#define STM32_MDMA_CTCR_SINCOS_DWORD STM32_MDMA_CTCR_SINCOS(3U) + +#define STM32_MDMA_CTCR_DINCOS_MASK (3U << 10) +#define STM32_MDMA_CTCR_DINCOS(n) ((n) << 10) +#define STM32_MDMA_CTCR_DINCOS_BYTE STM32_MDMA_CTCR_DINCOS(0U) +#define STM32_MDMA_CTCR_DINCOS_HALF STM32_MDMA_CTCR_DINCOS(1U) +#define STM32_MDMA_CTCR_DINCOS_WORD STM32_MDMA_CTCR_DINCOS(2U) +#define STM32_MDMA_CTCR_DINCOS_DWORD STM32_MDMA_CTCR_DINCOS(3U) + +#define STM32_MDMA_CTCR_SBURST_MASK (7U << 12) +#define STM32_MDMA_CTCR_SBURST(n) ((n) << 12) +#define STM32_MDMA_CTCR_SBURST_1 STM32_MDMA_CTCR_SBURST(0U) +#define STM32_MDMA_CTCR_SBURST_2 STM32_MDMA_CTCR_SBURST(1U) +#define STM32_MDMA_CTCR_SBURST_4 STM32_MDMA_CTCR_SBURST(2U) +#define STM32_MDMA_CTCR_SBURST_8 STM32_MDMA_CTCR_SBURST(3U) +#define STM32_MDMA_CTCR_SBURST_16 STM32_MDMA_CTCR_SBURST(4U) +#define STM32_MDMA_CTCR_SBURST_32 STM32_MDMA_CTCR_SBURST(5U) +#define STM32_MDMA_CTCR_SBURST_64 STM32_MDMA_CTCR_SBURST(6U) +#define STM32_MDMA_CTCR_SBURST_128 STM32_MDMA_CTCR_SBURST(7U) + +#define STM32_MDMA_CTCR_DBURST_MASK (7U << 15) +#define STM32_MDMA_CTCR_DBURST(n) ((n) << 15) +#define STM32_MDMA_CTCR_DBURST_1 STM32_MDMA_CTCR_DBURST(0U) +#define STM32_MDMA_CTCR_DBURST_2 STM32_MDMA_CTCR_DBURST(1U) +#define STM32_MDMA_CTCR_DBURST_4 STM32_MDMA_CTCR_DBURST(2U) +#define STM32_MDMA_CTCR_DBURST_8 STM32_MDMA_CTCR_DBURST(3U) +#define STM32_MDMA_CTCR_DBURST_16 STM32_MDMA_CTCR_DBURST(4U) +#define STM32_MDMA_CTCR_DBURST_32 STM32_MDMA_CTCR_DBURST(5U) +#define STM32_MDMA_CTCR_DBURST_64 STM32_MDMA_CTCR_DBURST(6U) +#define STM32_MDMA_CTCR_DBURST_128 STM32_MDMA_CTCR_DBURST(7U) + +#define STM32_MDMA_CTCR_TLEN_MASK (127U << 18) +#define STM32_MDMA_CTCR_TLEN(n) ((n) << 18) + +#define STM32_MDMA_CTCR_PKE (1U << 25) + +#define STM32_MDMA_CTCR_PAM_MASK (3U << 26) +#define STM32_MDMA_CTCR_PAM(n) ((n) << 26) +#define STM32_MDMA_CTCR_PAM_RIGHT STM32_MDMA_CTCR_PAM(0U) +#define STM32_MDMA_CTCR_PAM_RIGHT_SE STM32_MDMA_CTCR_PAM(1U) +#define STM32_MDMA_CTCR_PAM_LEFT STM32_MDMA_CTCR_PAM(2U) + +#define STM32_MDMA_CTCR_TRGM_MASK (3U << 28) +#define STM32_MDMA_CTCR_TRGM(n) ((n) << 28) +#define STM32_MDMA_CTCR_TRGM_BUFFER STM32_MDMA_CTCR_TRGM(0U) +#define STM32_MDMA_CTCR_TRGM_BLOCK STM32_MDMA_CTCR_TRGM(1U) +#define STM32_MDMA_CTCR_TRGM_REP_BLOCK STM32_MDMA_CTCR_TRGM(2U) +#define STM32_MDMA_CTCR_TRGM_WHOLE STM32_MDMA_CTCR_TRGM(3U) + +#define STM32_MDMA_CTCR_SWRM (1U << 30) + +#define STM32_MDMA_CTCR_BWM (1U << 31) +/** @} */ + +/** + * @name BNDTR register constants + * @{ + */ +#define STM32_MDMA_CBNDTR_BNDT_MASK (0x1FFFFU << 0) +#define STM32_MDMA_CBNDTR_BNDT(n) ((n) << 0) +#define STM32_MDMA_CBNDTR_BRSUM (1U << 18) +#define STM32_MDMA_CBNDTR_BRDUM (1U << 19) +#define STM32_MDMA_CBNDTR_BRC_MASK (0xFFFU << 20) +#define STM32_MDMA_CBNDTR_BRC(n) ((n) << 20) +/** @} */ + +/** + * @name CBRUR register constants + * @{ + */ +#define STM32_MDMA_CBRUR_SUV_MASK (0xFFFFU << 0) +#define STM32_MDMA_CBRUR_SUV(n) ((n) << 0) +#define STM32_MDMA_CBRUR_DUV_MASK (0xFFFFU << 16) +#define STM32_MDMA_CBRUR_DUV(n) ((n) << 16) +/** @} */ + +/** + * @name CTBR register constants + * @{ + */ +#define STM32_MDMA_CTBR_TSEL_MASK (0x3FU << 0) +#define STM32_MDMA_CTBR_TSEL(n) ((n) << 0) +#define STM32_MDMA_CTBR_TSEL_SBUS (1U << 16) +#define STM32_MDMA_CTBR_TSEL_DBUS (1U << 17) +/** @} */ + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if !defined(STM32_HAS_MDMA) +#error "STM32_HAS_MDMA missing in registry" +#endif + +#if !defined(STM32_HAS_DMA2) +#error "STM32_HAS_DMA2 missing in registry" +#endif + +#if !defined(STM32_MDMA_CH0_HANDLER) +#error "STM32_MDMA_CH0_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH1_HANDLER) +#error "STM32_MDMA_CH1_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH2_HANDLER) +#error "STM32_MDMA_CH2_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH3_HANDLER) +#error "STM32_MDMA_CH3_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH4_HANDLER) +#error "STM32_MDMA_CH4_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH5_HANDLER) +#error "STM32_MDMA_CH5_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH6_HANDLER) +#error "STM32_MDMA_CH6_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH7_HANDLER) +#error "STM32_MDMA_CH7_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH8_HANDLER) +#error "STM32_MDMA_CH8_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH9_HANDLER) +#error "STM32_MDMA_CH9_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH10_HANDLER) +#error "STM32_MDMA_CH10_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH11_HANDLER) +#error "STM32_MDMA_CH11_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH12_HANDLER) +#error "STM32_MDMA_CH12_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH13_HANDLER) +#error "STM32_MDMA_CH13_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH14_HANDLER) +#error "STM32_MDMA_CH14_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH15_HANDLER) +#error "STM32_MDMA_CH15_HANDLER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH0_NUMBER) +#error "STM32_MDMA_CH0_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH1_NUMBER) +#error "STM32_MDMA_CH1_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH2_NUMBER) +#error "STM32_MDMA_CH2_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH3_NUMBER) +#error "STM32_MDMA_CH3_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH4_NUMBER) +#error "STM32_MDMA_CH4_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH5_NUMBER) +#error "STM32_MDMA_CH5_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH6_NUMBER) +#error "STM32_MDMA_CH6_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH7_NUMBER) +#error "STM32_MDMA_CH7_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH8_NUMBER) +#error "STM32_MDMA_CH8_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH9_NUMBER) +#error "STM32_MDMA_CH9_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH10_NUMBER) +#error "STM32_MDMA_CH10_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH11_NUMBER) +#error "STM32_MDMA_CH11_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH12_NUMBER) +#error "STM32_MDMA_CH12_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH13_NUMBER) +#error "STM32_MDMA_CH13_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH14_NUMBER) +#error "STM32_MDMA_CH14_NUMBER missing in registry" +#endif + +#if !defined(STM32_MDMA_CH15_NUMBER) +#error "STM32_MDMA_CH15_NUMBER missing in registry" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief STM32 MDMA ISR function type. + * + * @param[in] p parameter for the registered function + * @param[in] flags content of the CISR register + */ +typedef void (*stm32_mdmaisr_t)(void *p, uint32_t flags); + +/** + * @brief STM32 MDMA stream descriptor structure. + */ +typedef struct { + MDMA_Channel_TypeDef *channel; /**< @brief Associated MDMA channel. */ + uint32_t selfindex; /**< @brief Index to self in array. */ + uint32_t vector; /**< @brief Associated IRQ vector. */ +} stm32_mdma_channel_t; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @name Macro Functions + * @{ + */ +/** + * @brief Associates a source address to a MDMA stream. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] addr value to be written in the CSAR register + * + * @xclass + */ +#define mdmaChannelSetSourceX(mdmachp, addr) do { \ + (mdmachp)->channel->CSAR = (uint32_t)(addr); \ +} while (0) + +/** + * @brief Associates a memory destination to a MDMA stream. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] addr value to be written in the CDAR register + * + * @xclass + */ +#define mdmaChannelSetDestinationX(mdmachp, addr) do { \ + (mdmachp)->channel->CDAR = (uint32_t)(addr); \ +} while (0) + +/** + * @brief Sets parameters related to the transaction size. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] size number of bytes per block + * @param[in] n number of blocks repetitions + * @param[in] opt other option bits for the CBNDTR register + * + * @xclass + */ +#define mdmaChannelSetTransactionSizeX(mdmachp, size, n, opt) do { \ + (mdmachp)->channel->CBNDTR = (uint32_t)STM32_MDMA_CBNDTR_BNDT(size) | \ + (uint32_t)STM32_MDMA_CBNDTR_BRC(n) | \ + (uint32_t)opt; \ +} while (0) + +/** + * @brief Programs the stream mode settings. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * @param[in] ctcr value to be written in the CTCR register + * @param[in] ccr value to be written in the CCR register + * + * @xclass + */ +#define mdmaChannelSetModeX(mdmachp, ctcr, ccr) do { \ + (mdmachp)->channel->CTCR = (uint32_t)(ctcr); \ + (mdmachp)->channel->CCR = (uint32_t)(ccr); \ +} while (0) + +/** + * @brief MDMA stream enable. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @xclass + */ +#define mdmaChannelEnableX(mdmachp) do { \ + (mdmachp)->channel->CCR |= STM32_MDMA_CCR_EN; \ +} while (0) + +/** + * @brief MDMA stream interrupt sources clear. + * @pre The stream must have been allocated using @p mdmaChannelAlloc(). + * @post After use the stream can be released using @p mdmaChannelFree(). + * + * @param[in] mdmachp pointer to a stm32_mdma_channel_t structure + * + * @xclass + */ +#define mdmaStreamClearInterruptX(mdmachp) do { \ + *(mdmachp)->CIFCR = (STM32_MDMA_CIFCR_CTEIF | \ + STM32_MDMA_CIFCR_CBRTIF | \ + STM32_MDMA_CIFCR_CBRTIF | \ + STM32_MDMA_CIFCR_CCTCIF | \ + STM32_MDMA_CIFCR_CTEIF) \ +} while (0) +/** @} */ + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +extern const stm32_mdma_channel_t __stm32_mdma_channels[STM32_MDMA_CHANNELS]; +#endif + +#ifdef __cplusplus +extern "C" { +#endif + void mdmaInit(void); + const stm32_mdma_channel_t *mdmaChannelAllocI(uint32_t id, + uint32_t priority, + stm32_mdmaisr_t func, + void *param); + const stm32_mdma_channel_t *mdmaChannelAlloc(uint32_t id, + uint32_t priority, + stm32_mdmaisr_t func, + void *param); + void mdmaChannelFreeI(const stm32_mdma_channel_t *mdmachp); + void mdmaChannelFree(const stm32_mdma_channel_t *mdmachp); + void mdmaStreamDisableX(const stm32_mdma_channel_t *mdmachp); +#ifdef __cplusplus +} +#endif + +#endif /* STM32_MDMA_H */ + +/** @} */