From 353daeaa1260878550df39405ba18ce66d974907 Mon Sep 17 00:00:00 2001 From: Giovanni Di Sirio Date: Thu, 26 Oct 2023 15:00:36 +0000 Subject: [PATCH] git-svn-id: svn://svn.code.sf.net/p/chibios/svn/trunk@16403 27425a3e-05d8-49a3-a47f-9c15f0e5edd8 --- os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.c | 110 +++++++++++++++---- os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.h | 87 ++++++++++----- os/hal/ports/STM32/STM32H5xx/stm32_rcc.h | 2 +- 3 files changed, 146 insertions(+), 53 deletions(-) diff --git a/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.c b/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.c index 06d3ed330..73dbb3af3 100644 --- a/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.c +++ b/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.c @@ -19,11 +19,11 @@ * @brief GPDMA helper driver code. * * @addtogroup STM32_GPDMA - * @details GPDMA sharing helper driver. In the STM32 the DMA channels are a - * shared resource, this driver allows to allocate and free DMA + * @details GPDMA sharing helper driver. In the STM32 the GPDMA channels are a + * shared resource, this driver allows to allocate and free GPDMA * channels at runtime in order to allow all the other device * drivers to coordinate the access to the resource. - * @note The DMA ISR handlers are all declared into this module because + * @note The GPDMA ISR handlers are all declared into this module because * sharing, the various device drivers can associate a callback to * ISRs when allocating channels. * @{ @@ -106,7 +106,7 @@ const stm32_gpdma_channel_t __stm32_gpdma_channels[STM32_GPDMA_CHANNELS] = { /*===========================================================================*/ /** - * @brief Global DMA-related data structures. + * @brief Global GPDMA-related data structures. */ static struct { /** @@ -114,15 +114,15 @@ static struct { */ uint32_t allocated_mask; /** - * @brief DMA IRQ redirectors. + * @brief GPDMA IRQ redirectors. */ struct { /** - * @brief DMA callback function. + * @brief GPDMA callback function. */ stm32_gpdmaisr_t func; /** - * @brief DMA callback parameter. + * @brief GPDMA callback parameter. */ void *param; } channels[STM32_GPDMA_CHANNELS]; @@ -141,7 +141,7 @@ static struct { /*===========================================================================*/ /** - * @brief STM32 DMA helper initialization. + * @brief STM32 GPDMA helper initialization. * * @init */ @@ -158,13 +158,13 @@ void dmaInit(void) { } /** - * @brief Allocates a DMA channel. - * @details The channel is allocated and, if required, the DMA clock enabled. + * @brief Allocates a GPDMA channel. + * @details The channel is allocated and, if required, the GPDMA clock enabled. * The function also enables the IRQ vector associated to the channel * and initializes its priority. * * @param[in] cmask channels mask where to search for an available chennel - * @param[in] irqprio IRQ priority for the DMA channel + * @param[in] irqprio IRQ priority for the GPDMA 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_dma_channel_t @@ -192,12 +192,12 @@ const stm32_gpdma_channel_t *gpdmaChannelAllocI(uint32_t cmask, /* Channel found.*/ const stm32_gpdma_channel_t *dmachp = STM32_GPDMA_CHANNEL(i); - /* Installs the DMA handler.*/ + /* Installs the GPDMA handler.*/ gpdma.channels[i].func = func; gpdma.channels[i].param = param; gpdma.allocated_mask |= mask; - /* Enabling DMA clocks required by the current channels set.*/ + /* Enabling GPDMA clocks required by the current channels set.*/ if ((STM32_GPDMA1_MASK_ANY & mask) != 0U) { rccEnableGPDMA1(true); } @@ -215,7 +215,7 @@ const stm32_gpdma_channel_t *gpdmaChannelAllocI(uint32_t cmask, } /* Putting the channel in a known state.*/ - gpdmaStreamDisable(dmachp); + gpdmaChannelDisable(dmachp); dmachp->channel->CCR = 0U; return dmachp; @@ -226,13 +226,13 @@ const stm32_gpdma_channel_t *gpdmaChannelAllocI(uint32_t cmask, } /** - * @brief Allocates a DMA channel. - * @details The channel is allocated and, if required, the DMA clock enabled. + * @brief Allocates a GPDMA channel. + * @details The channel is allocated and, if required, the GPDMA clock enabled. * The function also enables the IRQ vector associated to the channel * and initializes its priority. * * @param[in] cmask channels mask where to search for an available chennel - * @param[in] irqprio IRQ priority for the DMA channel + * @param[in] irqprio IRQ priority for the GPDMA 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_dma_channel_t @@ -255,8 +255,8 @@ const stm32_gpdma_channel_t *gpdmaChannelAlloc(uint32_t cmask, } /** - * @brief Releases a DMA channel. - * @details The channel is freed and, if required, the DMA clock disabled. + * @brief Releases a GPDMA channel. + * @details The channel is freed and, if required, the GPDMA clock disabled. * Trying to release a unallocated channel is an illegal operation * and is trapped if assertions are enabled. * @@ -279,7 +279,7 @@ void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp) { /* Disables the associated IRQ vector if it is no more in use.*/ nvicDisableVector(dmachp->vector); - /* Removes the DMA handler.*/ + /* Removes the GPDMA handler.*/ gpdma.channels[selfindex].func = NULL; gpdma.channels[selfindex].param = NULL; @@ -295,8 +295,8 @@ void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp) { } /** - * @brief Releases a DMA channel. - * @details The channel is freed and, if required, the DMA clock disabled. + * @brief Releases a GPDMA channel. + * @details The channel is freed and, if required, the GPDMA clock disabled. * Trying to release a unallocated channel is an illegal operation * and is trapped if assertions are enabled. * @@ -307,12 +307,74 @@ void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp) { void gpdmaChannelFree(const stm32_gpdma_channel_t *dmachp) { osalSysLock(); - gpdmaStreamFreeI(dmachp); + gpdmaChannelFreeI(dmachp); osalSysUnlock(); } + /** - * @brief Serves a DMA IRQ. + * @brief GPDMA channel suspend. + * @note This function can be invoked in both ISR or thread context. + * @pre The channel must have been allocated using @p dmaChannelAlloc(). + * @post After use the channel can be released using @p dmaChannelRelease(). + * + * @param[in] dmastp pointer to a @p stm32_gpdma_channel_t structure + * + * @special + */ +void gpdmaChannelSuspend(const stm32_gpdma_channel_t *dmastp) { + + osalDbgAssert((dmastp->channel->CCR & STM32_GPDMA_CCR_EN) != 0U, + "not enabled"); + + dmastp->channel->CCR |= STM32_GPDMA_CCR_SUSP; + while ((dmastp->channel->CSR & STM32_GPDMA_CSR_SUSPF) != 0U) { + /* Wait completion.*/ + } + dmastp->channel->CFCR = STM32_GPDMA_CFCR_SUSPF; +} + +/** + * @brief GPDMA channel disable. + * @details The function disables the specified channel and then clears any + * pending interrupt. + * @note This function can be invoked in both ISR or thread context. + * @note Interrupts enabling flags are set to zero after this call, see + * bug 3607518. + * @pre The channel must have been allocated using @p dmaChannelAlloc(). + * @post After use the channel can be released using @p dmaChannelRelease(). + * + * @param[in] dmastp pointer to a @p stm32_gpdma_channel_t structure + * + * @special + */ +void gpdmaChannelDisable(const stm32_gpdma_channel_t *dmastp) { + + /* Suspending channel, note, we don't know if it is still active at this + point because the EN bit can be reset in HW.*/ + dmastp->channel->CCR |= STM32_GPDMA_CCR_SUSP; + + /* If the channel was actually active.*/ + if ((dmastp->channel->CCR & STM32_GPDMA_CCR_EN) != 0U) { + + /* Waiting for completion if suspend operation then resetting the + completion flag.*/ + while ((dmastp->channel->CSR & STM32_GPDMA_CSR_SUSPF) != 0U) { + /* Wait completion.*/ + } + dmastp->channel->CFCR = STM32_GPDMA_CFCR_SUSPF; + } + + /* Now resetting the channel.*/ + dmastp->channel->CCR |= STM32_GPDMA_CCR_RESET; + dmastp->channel->CCR = 0U; + + /* Clearing all interrupts.*/ + dmastp->channel->CFCR = STM32_GPDMA_CFCR_ALL; +} + +/** + * @brief Serves a GPDMA IRQ. * * @param[in] dmachp pointer to a @p stm32_gpdma_channel_t structure * diff --git a/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.h b/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.h index ea1c08333..9d03cf3aa 100644 --- a/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.h +++ b/os/hal/ports/STM32/LLD/GPDMAv1/stm32_gpdma.h @@ -15,7 +15,7 @@ */ /** - * @file GPDMAv1/stm32_gpdma.h + * @file DMAv1/stm32_gpdma.h * @brief GPDMA helper driver header. * * @addtogroup STM32_GPDMA @@ -32,7 +32,7 @@ /*===========================================================================*/ /** - * @name GPDMA registers helpers + * @name DMA registers helpers * @{ */ #define STM32_GPDMA_CLBAR_LBA_POS DMA_CLBAR_LBA_Pos @@ -46,6 +46,10 @@ #define STM32_GPDMA_CFCR_DTEF DMA_CFCR_DTEF #define STM32_GPDMA_CFCR_HTF DMA_CFCR_HTF #define STM32_GPDMA_CFCR_TCF DMA_CFCR_TCF +#define STM32_GPDMA_CFCR_ALL (DMA_CFCR_TOF | DMA_CFCR_SUSPF | \ + DMA_CFCR_USEF | DMA_CFCR_ULEF | \ + DMA_CFCR_DTEF | DMA_CFCR_HTF | \ + DMA_CFCR_TCF) #define STM32_GPDMA_CSR_FIFOL_POS DMA_CSR_FIFOL_Pos #define STM32_GPDMA_CSR_FIFOL_MASK (0x7FU << STM32_GPDMA_CSR_FIFOL_POS) @@ -63,21 +67,21 @@ DMA_CSR_DTEF | DMA_CSR_HTF | \ DMA_CSR_TCF) -#define STM32_GPDMA_CR_PRIO_POS DMA_CCR_PRIO_Pos -#define STM32_GPDMA_CR_PRIO_MASK (3U << STM32_GPDMA_CR_PRIO_POS) -#define STM32_GPDMA_CR_PRIO(n) ((n) << STM32_GPDMA_CR_PRIO_POS) -#define STM32_GPDMA_CR_LAP DMA_CCR_LAP -#define STM32_GPDMA_CR_LSM DMA_CCR_LSM -#define STM32_GPDMA_CR_TOIE DMA_CCR_TOIE -#define STM32_GPDMA_CR_SUSPIE DMA_CCR_SUSPIE -#define STM32_GPDMA_CR_USEIE DMA_CCR_USEIE -#define STM32_GPDMA_CR_ULEIE DMA_CCR_ULEIE -#define STM32_GPDMA_CR_DTEIE DMA_CCR_DTEIE -#define STM32_GPDMA_CR_HTIE DMA_CCR_HTIE -#define STM32_GPDMA_CR_TCIE DMA_CCR_TCIE -#define STM32_GPDMA_CR_SUSP DMA_CCR_SUSP -#define STM32_GPDMA_CR_RESET DMA_CCR_RESET -#define STM32_GPDMA_CR_EN DMA_CCR_EN +#define STM32_GPDMA_CCR_PRIO_POS DMA_CCR_PRIO_Pos +#define STM32_GPDMA_CCR_PRIO_MASK (3U << STM32_GPDMA_CR_PRIO_POS) +#define STM32_GPDMA_CCR_PRIO(n) ((n) << STM32_GPDMA_CR_PRIO_POS) +#define STM32_GPDMA_CCR_LAP DMA_CCR_LAP +#define STM32_GPDMA_CCR_LSM DMA_CCR_LSM +#define STM32_GPDMA_CCR_TOIE DMA_CCR_TOIE +#define STM32_GPDMA_CCR_SUSPIE DMA_CCR_SUSPIE +#define STM32_GPDMA_CCR_USEIE DMA_CCR_USEIE +#define STM32_GPDMA_CCR_ULEIE DMA_CCR_ULEIE +#define STM32_GPDMA_CCR_DTEIE DMA_CCR_DTEIE +#define STM32_GPDMA_CCR_HTIE DMA_CCR_HTIE +#define STM32_GPDMA_CCR_TCIE DMA_CCR_TCIE +#define STM32_GPDMA_CCR_SUSP DMA_CCR_SUSP +#define STM32_GPDMA_CCR_RESET DMA_CCR_RESET +#define STM32_GPDMA_CCR_EN DMA_CCR_EN #define STM32_GPDMA_CTR1_DSEC DMA_CTR1_DSEC #define STM32_GPDMA_CTR1_DAP DMA_CTR1_DAP @@ -143,6 +147,31 @@ #define STM32_GPDMA_CBR1_BNDT_MASK (3U << STM32_GPDMA_CBR1_BNDT_POS) #define STM32_GPDMA_CBR1_BNDT(n) ((n) << STM32_GPDMA_CBR1_BNDT_POS) +#define STM32_GPDMA_CTR3_DAO_POS DMA_CTR3_DAO_Pos +#define STM32_GPDMA_CTR3_DAO_MASK (0x1FFFU << STM32_GPDMA_CTR3_DAO_POS) +#define STM32_GPDMA_CTR3_DAO(n) ((n) << STM32_GPDMA_CTR3_DAO_POS) +#define STM32_GPDMA_CTR3_SAO_POS DMA_CTR3_SAO_Pos +#define STM32_GPDMA_CTR3_SAO_MASK (0x1FFFU << STM32_GPDMA_CTR3_SAO_POS) +#define STM32_GPDMA_CTR3_SAO(n) ((n) << STM32_GPDMA_CTR3_SAO_POS) + +#define STM32_GPDMA_CBR2_BRDAO_POS DMA_CBR2_BRDAO_Pos +#define STM32_GPDMA_CBR2_BRDAO_MASK (0xFFFFU << STM32_GPDMA_CBR2_BRDAO_POS) +#define STM32_GPDMA_CBR2_BRDAO(n) ((n) << STM32_GPDMA_CBR2_BRDAO_POS) +#define STM32_GPDMA_CBR2_BRSAO_POS DMA_CBR2_BRSAO_Pos +#define STM32_GPDMA_CBR2_BRSAO_MASK (0xFFFFU << STM32_GPDMA_CBR2_BRSAO_POS) +#define STM32_GPDMA_CBR2_BRSAO(n) ((n) << STM32_GPDMA_CBR2_BRSAO_POS) + +#define STM32_GPDMA_CLLR_UT1 DMA_CLLR_UT1 +#define STM32_GPDMA_CLLR_UT2 DMA_CLLR_UT2 +#define STM32_GPDMA_CLLR_UB1 DMA_CLLR_UB1 +#define STM32_GPDMA_CLLR_USA DMA_CLLR_USA +#define STM32_GPDMA_CLLR_UDA DMA_CLLR_UDA +#define STM32_GPDMA_CLLR_UT3 DMA_CLLR_UT3 +#define STM32_GPDMA_CLLR_UB2 DMA_CLLR_UB2 +#define STM32_GPDMA_CLLR_ULL DMA_CLLR_ULL +#define STM32_GPDMA_CLLR_LA_POS DMA_CLLR_LA_Pos +#define STM32_GPDMA_CLLR_LA_MASK (0xFFFCU << STM32_GPDMA_CLLR_LA_POS) +#define STM32_GPDMA_CLLR_LA(n) ((n) << STM32_GPDMA_CLLR_LA_POS) /** @< */ /** @@ -156,7 +185,7 @@ /** * @brief Checks if a GPDMA priority is within the valid range. - * @param[in] prio GPDMA priority + * @param[in] prio DMA priority * * @retval The check result. * @retval false invalid GPDMA priority. @@ -187,7 +216,7 @@ (1U << STM32_GPDMA_CHANNEL_ID(dma, ch)) /** - * @name GPDMA channels identifiers + * @name DMA channels identifiers * @{ */ /** @@ -315,12 +344,12 @@ * @brief Type of a GPDMA callback. * * @param[in] p parameter for the registered function - * @param[in] v content of the CxSR register + * @param[in] csr content of the CxSR register */ typedef void (*stm32_gpdmaisr_t)(void *p, uint32_t csr); /** - * @brief STM32 DMA channel descriptor structure. + * @brief STM32 GPDMA channel descriptor structure. */ typedef struct { DMA_Channel_TypeDef *channel; /**< @brief Associated channel. */ @@ -336,7 +365,7 @@ typedef struct { * @{ */ /** - * @brief Associates a peripheral data register to a DMA channel. + * @brief Associates a peripheral data register to a GPDMA channel. * @note This function can be invoked in both ISR or thread context. * @pre The channel must have been allocated using @p dmaStreamAlloc(). * @post After use the channel can be released using @p dmaStreamRelease(). @@ -351,7 +380,7 @@ typedef struct { } /** - * @brief Associates a memory destination to a DMA channel. + * @brief Associates a memory destination to a GPDMA channel. * @note This function can be invoked in both ISR or thread context. * @pre The channel must have been allocated using @p dmaStreamAlloc(). * @post After use the channel can be released using @p dmaStreamRelease(). @@ -409,7 +438,7 @@ typedef struct { } /** - * @brief DMA channel enable. + * @brief GPDMA channel enable. * @note This function can be invoked in both ISR or thread context. * @pre The channel must have been allocated using @p dmaStreamAlloc(). * @post After use the channel can be released using @p dmaStreamRelease(). @@ -423,7 +452,7 @@ typedef struct { } /** - * @brief DMA channel disable. + * @brief GPDMA channel disable. * @details The function disables the specified channel and then clears any * pending interrupt. * @note This function can be invoked in both ISR or thread context. @@ -436,14 +465,14 @@ typedef struct { * * @special */ -#define gpdmaStreamDisable(dmastp) { \ +#define ______gpdmaStreamDisable(dmastp) { \ (dmastp)->channel->CCR &= ~(STM32_GPDMA_CR_TCIE | STM32_GPDMA_CR_HTIE | \ STM32_GPDMA_CR_TEIE | STM32_GPDMA_CR_EN); \ dmaStreamClearInterrupt(dmastp); \ } /** - * @brief DMA channel interrupt sources clear. + * @brief GPDMA channel interrupt sources clear. * @note This function can be invoked in both ISR or thread context. * @pre The channel must have been allocated using @p dmaStreamAlloc(). * @post After use the channel can be released using @p dmaStreamRelease(). @@ -485,7 +514,7 @@ typedef struct { } /** - * @brief Polled wait for DMA transfer end. + * @brief Polled wait for GPDMA transfer end. * @pre The channel must have been allocated using @p dmaStreamAlloc(). * @post After use the channel can be released using @p dmaStreamRelease(). * @@ -520,6 +549,8 @@ extern "C" { void *param); void gpdmaChannelFreeI(const stm32_gpdma_channel_t *dmachp); void gpdmaChannelFree(const stm32_gpdma_channel_t *dmachp); + void gpdmaChannelSuspend(const stm32_gpdma_channel_t *dmastp); + void gpdmaChannelDisable(const stm32_gpdma_channel_t *dmastp); void gpdmaServeInterrupt(const stm32_gpdma_channel_t *dmachp); #ifdef __cplusplus } diff --git a/os/hal/ports/STM32/STM32H5xx/stm32_rcc.h b/os/hal/ports/STM32/STM32H5xx/stm32_rcc.h index 9fcab589c..4556af10b 100644 --- a/os/hal/ports/STM32/STM32H5xx/stm32_rcc.h +++ b/os/hal/ports/STM32/STM32H5xx/stm32_rcc.h @@ -518,7 +518,7 @@ * * @api */ -#define rccDisableGPDMA1() rccDisableGPAHB1(RCC_AHB1ENR_GPDMA1EN) +#define rccDisableGPDMA1() rccDisableAHB1(RCC_AHB1ENR_GPDMA1EN) /** * @brief Resets the GPDMA1 peripheral.