From 266446624fc055e988782577286fe91efbda438e Mon Sep 17 00:00:00 2001 From: "Peter D. Gray" Date: Fri, 13 Apr 2018 09:14:44 -0400 Subject: [PATCH] stm32/dma: Always deinit/reinit DMA channels on L4 MCUs. The problem is the existing code which tries to optimise the reinitialisation of the DMA breaks the abstraction of the HAL. For the STM32L4 the HAL's DMA setup code maintains two private vars (ChannelIndex, DmaBaseAddress) and updates a hardware register (CCR). In HAL_DMA_Init(), the CCR is updated to set the direction of the DMA. This is a problem because, when using the SD Card interface, the same DMA channel is used in both directions, so the direction bit in the CCR must follow that. A quick and effective fix for the L4 is to simply call HAL_DMA_DeInit() and HAL_DMA_Init() every time. --- ports/stm32/dma.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 7ea2eaa3b4..35cfba162e 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -498,6 +498,14 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data){ dma_enable_clock(dma_id); + #if defined(STM32L4) + // Always reset and configure the L4 DMA peripheral + // (dma->State is set to HAL_DMA_STATE_RESET by memset above) + // TODO: understand how L4 DMA works so this is not needed + HAL_DMA_DeInit(dma); + HAL_DMA_Init(dma); + HAL_NVIC_SetPriority(dma_irqn[dma_id], IRQ_PRI_DMA, IRQ_SUBPRI_DMA); + #else // if this stream was previously configured for this channel/request then we // can skip most of the initialisation uint8_t sub_inst = DMA_SUB_INSTANCE_AS_UINT8(dma_descr->sub_instance); @@ -518,6 +526,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, void *data){ DMA_CalcBaseAndBitshift(dma); #endif } + #endif HAL_NVIC_EnableIRQ(dma_irqn[dma_id]); }