Dear Community,
I am currently using NUCLEO144-H563ZI board with STM32H563ZIT6 microcontroller to get ADC data via GPDMA1_CHANNEL1. The problem occurs when I change the optimization level in Keil(MDK-ARM version 5.26.2.0). If the firmware is compiled at optimization level O1, the DMA operate well and data can be read from destination memory. But if the firmware is compiled at optimization level O0, the DMA seems to be stuck in BUSY status. I simulate the process using Keil and find that if I comment out the code in red block in stm32h5xx_hal.c, the DMA can operate well even if at optimization level O0. Please see picture below.
Additionally, I find that the DMA register configuration is different at these two optimization level. Please see pictures below.
And the DMA initialization code as below:
/* ADC1 DMA Init */
/* GPDMA1_REQUEST_ADC1 Init */
NodeConfig.NodeType = DMA_GPDMA_LINEAR_NODE;
NodeConfig.Init.Request = GPDMA1_REQUEST_ADC1;
NodeConfig.Init.BlkHWRequest = DMA_BREQ_SINGLE_BURST;
NodeConfig.Init.Direction = DMA_PERIPH_TO_MEMORY;
NodeConfig.Init.SrcInc = DMA_SINC_FIXED;
NodeConfig.Init.DestInc = DMA_DINC_INCREMENTED;
NodeConfig.Init.SrcDataWidth = DMA_SRC_DATAWIDTH_HALFWORD;
NodeConfig.Init.DestDataWidth = DMA_DEST_DATAWIDTH_HALFWORD;
NodeConfig.Init.Priority = DMA_HIGH_PRIORITY;
NodeConfig.Init.SrcBurstLength = 1;
NodeConfig.Init.DestBurstLength = 1;
NodeConfig.Init.TransferAllocatedPort = DMA_SRC_ALLOCATED_PORT1 | DMA_DEST_ALLOCATED_PORT1;
NodeConfig.Init.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
NodeConfig.Init.Mode = DMA_NORMAL;
status = HAL_DMAEx_List_BuildNode(&NodeConfig, &Node_GPDMA1_Channel1);
if (status != HAL_OK)
{
MemoryUpdateRegisterByte(TABLE_INDEX_UPPER_PAGE_E4H, DMA_BUILD_NODE_INIT_STATUS, status);
}
status = HAL_DMAEx_List_InsertNode(&List_GPDMA1_Channel1, NULL, &Node_GPDMA1_Channel1);
if (status != HAL_OK)
{
MemoryUpdateRegisterByte(TABLE_INDEX_UPPER_PAGE_E4H, DMA_INSERT_NODE_INIT_STATUS, status);
}
status = HAL_DMAEx_List_SetCircularMode(&List_GPDMA1_Channel1);
if (status != HAL_OK)
{
MemoryUpdateRegisterByte(TABLE_INDEX_UPPER_PAGE_E4H, DMA_SET_CIR_MODE_INIT_STATUS, status);
}
handle_GPDMA1_Channel1.Instance = GPDMA1_Channel1;
handle_GPDMA1_Channel1.InitLinkedList.Priority = DMA_LOW_PRIORITY_HIGH_WEIGHT;
handle_GPDMA1_Channel1.InitLinkedList.LinkStepMode = DMA_LSM_FULL_EXECUTION;
handle_GPDMA1_Channel1.InitLinkedList.LinkAllocatedPort = DMA_LINK_ALLOCATED_PORT1;
handle_GPDMA1_Channel1.InitLinkedList.TransferEventMode = DMA_TCEM_BLOCK_TRANSFER;
handle_GPDMA1_Channel1.InitLinkedList.LinkedListMode = DMA_LINKEDLIST_CIRCULAR;
status = HAL_DMAEx_List_Init(&handle_GPDMA1_Channel1);
if (status != HAL_OK)
{
MemoryUpdateRegisterByte(TABLE_INDEX_UPPER_PAGE_E4H, DMA_LIST_INIT_STATUS, status);
}
status = HAL_DMAEx_List_LinkQ(&handle_GPDMA1_Channel1, &List_GPDMA1_Channel1);
if (status != HAL_OK)
{
MemoryUpdateRegisterByte(TABLE_INDEX_UPPER_PAGE_E4H, DMA_LIST_LINKQ_INIT_STATUS, status);
}
__HAL_LINKDMA(hadc, DMA_Handle, handle_GPDMA1_Channel1);
status = HAL_DMA_ConfigChannelAttributes(&handle_GPDMA1_Channel1, DMA_CHANNEL_NPRIV);
if (status != HAL_OK)
{
MemoryUpdateRegisterByte(TABLE_INDEX_UPPER_PAGE_E4H, DMA_CHANNEL_CONFIG_INIT_STATUS, status);
}
/* Enable DMA clock */
__HAL_RCC_GPDMA1_CLK_ENABLE();
/* DMA interrupt Init */
HAL_NVIC_SetPriority(GPDMA1_Channel1_IRQn, NVICPreemptionPriority_ADC_DMA, NVICSubPriority_ADC_DMA);
HAL_NVIC_EnableIRQ(GPDMA1_Channel1_IRQn);
Thanks and Regards!