Skip to main content
Emma
Associate II
June 22, 2020
Solved

Using ADC with DMA on M4 causes DMA transfer error

  • June 22, 2020
  • 7 replies
  • 4205 views

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 */

}

This topic has been closed for replies.
Best answer by Emma

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)

7 replies

mleo
Visitor II
June 24, 2020

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

Emma
EmmaAuthor
Associate II
June 24, 2020

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

MMevo.1
Associate II
January 3, 2022

Hi Emma,

I am experiancing the same issue with STM32H743-

did you manage to solve this problem?

Best Regards,

Maor

PatrickF
Technical Moderator
January 4, 2022

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.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.NEW ! Sidekick STM32 AI agent, see here
Emma
EmmaAuthorBest answer
Associate II
January 5, 2022

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)

PatrickF
Technical Moderator
January 5, 2022

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'

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.NEW ! Sidekick STM32 AI agent, see here
MMevo.1
Associate II
January 5, 2022

Hi @Emma (Community Member)​, @PatrickF (ST Employee)​ ,

I am not familier with etzpc node.. Do you know if it relevant also to STM32H7?

I have enabled ADC1 Global interrupt as well (From the CubeMX).

Regards,

Maor

PatrickF
Technical Moderator
January 5, 2022

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.

In order to give better visibility on the answered topics, please click on 'Accept as Solution' on the reply which solved your issue or answered your question.NEW ! Sidekick STM32 AI agent, see here
MMevo.1
Associate II
January 6, 2022