2020-06-22 05:26 AM
We are trying to use circular DMA to transfer data from ADC1 into a buffer in MCU SRAM using CubeMX-generated code to configure the ADC and DMA. The DMA stream encounters a transfer error on transferring the first item. I have tried clearing the DMA error flags before starting the transfer with HAL_ADC_Start_DMA but that did not help.
The device is an STM32MP157C running in Production mode. ADC1 and DMA2 are assigned to the M4 core.
Using a debugger it can be seen that the peripheral address and memory address are configured correctly for the DMA stream. However, the DMA_HWCFGR1 register for DMA2 shows that all streams are in double-buffer mode despite the DBM bit being cleared in the stream configuration register, is this normal?
CubeMX-generated code:
static void MX_ADC1_Init(void)
{
/* USER CODE BEGIN ADC1_Init 0 */
/* USER CODE END ADC1_Init 0 */
ADC_MultiModeTypeDef multimode = {0};
ADC_ChannelConfTypeDef sConfig = {0};
/* USER CODE BEGIN ADC1_Init 1 */
/* USER CODE END ADC1_Init 1 */
/** Common config
*/
hadc1.Instance = ADC1;
hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
hadc1.Init.Resolution = ADC_RESOLUTION_12B;
hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;
hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
hadc1.Init.LowPowerAutoWait = DISABLE;
hadc1.Init.ContinuousConvMode = ENABLE;
hadc1.Init.NbrOfConversion = 8;
hadc1.Init.DiscontinuousConvMode = DISABLE;
hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
hadc1.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;
hadc1.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
hadc1.Init.OversamplingMode = DISABLE;
if (HAL_ADC_Init(&hadc1) != HAL_OK)
{
Error_Handler();
}
/** Configure the ADC multi-mode
*/
multimode.Mode = ADC_MODE_INDEPENDENT;
if (HAL_ADCEx_MultiModeConfigChannel(&hadc1, &multimode) != HAL_OK)
{
Error_Handler();
}
/** Configure Regular Channel
*/
sConfig.Channel = ADC_CHANNEL_10;
sConfig.Rank = ADC_REGULAR_RANK_1;
sConfig.SamplingTime = ADC_SAMPLETIME_64CYCLES_5;
sConfig.SingleDiff = ADC_SINGLE_ENDED;
sConfig.OffsetNumber = ADC_OFFSET_NONE;
sConfig.Offset = 0;
if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
{
Error_Handler();
}
/* Other channels omitted here */
}
void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hadc->Instance==ADC1)
{
/* USER CODE BEGIN ADC1_MspInit 0 */
/* USER CODE END ADC1_MspInit 0 */
/* Peripheral clock enable */
HAL_RCC_ADC12_CLK_ENABLED++;
if(HAL_RCC_ADC12_CLK_ENABLED==1){
__HAL_RCC_ADC12_CLK_ENABLE();
}
/* GPIO init omitted here */
/* ADC1 DMA Init */
/* ADC1 Init */
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Request = DMA_REQUEST_ADC1;
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE;
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_adc1.Init.Mode = DMA_CIRCULAR;
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH;
hdma_adc1.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_adc1) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hadc,DMA_Handle,hdma_adc1);
/* USER CODE BEGIN ADC1_MspInit 1 */
/* USER CODE END ADC1_MspInit 1 */
}
static void MX_DMA_Init(void)
{
/* DMA controller clock enable */
__HAL_RCC_DMAMUX_CLK_ENABLE();
__HAL_RCC_DMA2_CLK_ENABLE();
/* DMA interrupt init */
/* DMA2_Stream0_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream0_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream0_IRQn);
/* DMA2_Stream1_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
/* DMA2_Stream2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream2_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream2_IRQn);
/* DMA2_Stream3_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream3_IRQn, 4, 1);
HAL_NVIC_EnableIRQ(DMA2_Stream3_IRQn);
/* DMA2_Stream4_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream4_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream4_IRQn);
/* DMA2_Stream5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 4, 1);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
/* DMA2_Stream6_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 5, 1);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
void DMA2_Stream0_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream0_IRQn 0 */
/* USER CODE END DMA2_Stream0_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc1);
/* USER CODE BEGIN DMA2_Stream0_IRQn 1 */
/* USER CODE END DMA2_Stream0_IRQn 1 */
}
Solved! Go to Solution.
2022-01-05 07:11 AM
Hi @MMevo.1 , @PatrickF ,
Yes, ST Support helped me with this. The missing piece was to add DMA2 to MCU isolation in the TF-A device tree.
To the etzpc node, add:
DECPROT(STM32MP1_ETZPC_DMA2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
2020-06-24 03:00 AM
Hi @Emma ,
In you code fragment you didn't provide the DMA settings located in file stm32mp1xx_hal_msp.c
Could you for better inspection send the original ioc file?
I tend to think it's just matter of settings - the M4 core and this ADC DMA feature has been used frequently.
Best regards,
MIlan
2020-06-24 08:00 AM
Hi @mleo ,
Please find the ioc file attached.
(In the project you can see that I2C1 and I2C3 are also configured to use DMA, but I couldn't get it working so I switched to using interrupts for the time being. I haven't looked into why the I2C DMA didn't work.)
Best Regards,
Emma
2020-09-10 06:47 AM
I haven't been able to solve this and I'm also having the same problem with the DAC: Transferring data from a buffer in MCU SRAM to the DAC (DHR12R1) using DMA2 generates a DMA transfer error on the first data item.
The only DMA transfer I've been able to get to work on the M4 core is a memory-to-memory transfer. Because of this I'm assuming that the transfer error is caused by a bus error when accessing the ADC/DAC data registers and not when accessing the MCU SRAM.
What would cause such a bus error? I'm using half-word alignment which worked fine on an STM32F427 but I've also tried word alignment to make sure it's not an alignment issue.
2022-01-03 07:31 AM
Hi Emma,
I am experiancing the same issue with STM32H743-
did you manage to solve this problem?
Best Regards,
Maor
2022-01-04 12:06 AM
Hi @MMevo.1, @Emma , did you also enable the ADC1 global interrupt (or relevant peripheral interrupt you want to use with DMA) in CubeMx ?
@MMevo.1 , for further support on STM32H7, please enter a question on STM32 MCUs community
Regards.
2022-01-05 07:11 AM
Hi @MMevo.1 , @PatrickF ,
Yes, ST Support helped me with this. The missing piece was to add DMA2 to MCU isolation in the TF-A device tree.
To the etzpc node, add:
DECPROT(STM32MP1_ETZPC_DMA2_ID, DECPROT_MCU_ISOLATION, DECPROT_UNLOCK)
2022-01-05 07:25 AM
In order to give better visibility on the answered topics, please click on 'Select as Best' on the reply which solved your issue or answered your question. See also 'Best Answers'
2022-01-05 07:25 AM
2022-01-05 07:29 AM
Hi,
not at all, this is related only to STM32MP1 series Cortex-A7 side with Linux.
Not relevant for STM32H7.
Maybe worth that you look at existing examples provided in STM32CubeH7 and if not enough please enter a question on STM32 MCUs community
Regards.