cancel
Showing results for 
Search instead for 
Did you mean: 

ADC with DMA in scan mode is not resulting in call to HAL_ADC_ConvCpltCallback

GreenGuy
Lead

Given:

STM32CubeIDE:

Version: 1.14.1

Build: 20064_20240111_1413 (UTC)

 

STM32CubeMX:

Version: 6.10.0-RC9

Build: 20231120-2037 (UTC)

 

OS:

Linux Lmint21

 

Initialization Code in Main for ADC: Scanning three internal values

 

 

static void MX_ADC3_Init(void)

{


/* USER CODE BEGIN ADC3_Init 0 */


/* USER CODE END ADC3_Init 0 */


ADC_ChannelConfTypeDef sConfig = {0};


/* USER CODE BEGIN ADC3_Init 1 */

 hadc3.Init.ClockPrescaler = ADC_CLOCK_ASYNC_DIV1;

/* USER CODE END ADC3_Init 1 */


/** Common config

 */

 hadc3.Instance = ADC3;

 hadc3.Init.Resolution = ADC_RESOLUTION_16B;

 hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;

 hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;

 hadc3.Init.LowPowerAutoWait = DISABLE;

 hadc3.Init.ContinuousConvMode = DISABLE;

 hadc3.Init.NbrOfConversion = 3;

 hadc3.Init.DiscontinuousConvMode = DISABLE;

 hadc3.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;

 hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;

 hadc3.Init.Overrun = ADC_OVR_DATA_PRESERVED;

 hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;

 hadc3.Init.OversamplingMode = DISABLE;

if (HAL_ADC_Init(&hadc3) != HAL_OK)

 {

 Error_Handler();

 }


/** Configure Regular Channel

 */

 sConfig.Channel = ADC_CHANNEL_TEMPSENSOR;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_16CYCLES_5;

 sConfig.SingleDiff = ADC_SINGLE_ENDED;

 sConfig.OffsetNumber = ADC_OFFSET_NONE;

 sConfig.Offset = 0;

 sConfig.OffsetSignedSaturation = DISABLE;

if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)

 {

 Error_Handler();

 }


/** Configure Regular Channel

 */

 sConfig.Channel = ADC_CHANNEL_VBAT;

 sConfig.Rank = ADC_REGULAR_RANK_2;

if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)

 {

 Error_Handler();

 }


/** Configure Regular Channel

 */

 sConfig.Rank = ADC_REGULAR_RANK_3;

if (HAL_ADC_ConfigChannel(&hadc3, &sConfig) != HAL_OK)

 {

 Error_Handler();

 }

/* USER CODE BEGIN ADC3_Init 2 */

/* USER CODE END ADC3_Init 2 */
}

 

Note: I had to add the clock pre-scale to the beginning user code since this is still not available to select in CubeMX.

The system clock config is set to pass 50MHz to the ADC,

GreenGuy_0-1712696499481.png

I did verify the ADC clock was being set in HAL_ADC_MspInit()

 

 

void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
{
  if(hadc->Instance==ADC3)
  {
  /* USER CODE BEGIN ADC3_MspInit 0 */

  /* USER CODE END ADC3_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_ADC3_CLK_ENABLE();

 

The code to perform the scan is in a thread (AZURE RTOS):

 

typedef struct ADCvalues{
	uint16_t Raw[3];
	double IntSensTmp;
	double int_ref;
	double vbat;
} adcval_t;

adcval_t ADC;

void ADC_Thread_entry(ULONG thread_input)
{
	(void) thread_input;

	tx_thread_sleep(500);
	HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC.Raw, 3);

	while(1){
		tx_semaphore_get(&ADC_Semaphore, TX_WAIT_FOREVER);
		tx_thread_sleep(500);
		HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC.Raw, 3);
	}
}

void HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef *hadc)
{
	HAL_ADC_Stop_DMA(hadc);
	tx_semaphore_put(&ADC_Semaphore); // let system know the FPGA is done loading
}

 

and the interrupt handlers are in the stm32h7xx_it.c as:

 

void ADC3_IRQHandler(void)
{
  /* USER CODE BEGIN ADC3_IRQn 0 */

  /* USER CODE END ADC3_IRQn 0 */
  HAL_ADC_IRQHandler(&hadc3);
  /* USER CODE BEGIN ADC3_IRQn 1 */

  /* USER CODE END ADC3_IRQn 1 */
}

/**
  * @brief This function handles BDMA channel0 global interrupt.
  */
void BDMA_Channel0_IRQHandler(void)
{
  /* USER CODE BEGIN BDMA_Channel0_IRQn 0 */

  /* USER CODE END BDMA_Channel0_IRQn 0 */
  HAL_DMA_IRQHandler(&hdma_adc3);
  /* USER CODE BEGIN BDMA_Channel0_IRQn 1 */

  /* USER CODE END BDMA_Channel0_IRQn 1 */
}

 

The CubeMX Mode and params are set up as:

GreenGuy_1-1712696961303.png

 

and

GreenGuy_2-1712697000932.png

GreenGuy_3-1712697038048.png

NVIC settings:

GreenGuy_4-1712697120739.png

with DMA settings:

GreenGuy_6-1712697188445.png

Also Register Callbacks are set to enable for ADC.

So what did I miss?

This did work a little as I was debugging and setting breakpoints. Pausing at the first HAL_ADC_Start_DMA call and stepping into the Hal code to verify parameters being passed, I then pushed play and hit the break point in the callback. However, continuing past the break point in the callback, I did not get anymore passes through the callback. Then, for reasons unknown this would not occur anymore after code changes that I cannot recall the sequence of. Now it does not work at all.

The code operation is intended to wait in the thread until a semaphore indicates a completed conversion. Then sleep for 5 seconds after which another conversion is started. There is no processing of the ADC values yet. I was going to add those later once I actually have data to process.

1 ACCEPTED SOLUTION

Accepted Solutions

Hello, 

BDMA, DMA1 and DMA2 do not have access to the DTCM memory. BDMA has access to SRAM4 in D3 only. Please refer to the reference manual.

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.

View solution in original post

3 REPLIES 3
GreenGuy
Lead

I made a change that did not change any behavior.

I created a DTCM_section in the linker script and set the attribute of the ADC data structure to point to that section with:

__attribute__((section(".DTCMRAM_section"))) adcval_t ADC;

The debugger confirms the ADC structure is pointing to 0x20000000 (DTCM RAM).

Then I made another change that seems to have had some effect.  I changed the Overrun behavior to Overrun data overwritten.

Now, I hit the break points at the first call HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC.Raw, 3); followed by the second call HAL_ADC_Start_DMA(&hadc3, (uint32_t*)ADC.Raw, 3); five seconds later in the while loop after the tx_semaphore_get.  But then, running the program further generates no more interrupts and hence no more hits to the HAL_ADC_ConvCpltCallback (ADC_HandleTypeDef *hadc) routine.

 

Hello, 

BDMA, DMA1 and DMA2 do not have access to the DTCM memory. BDMA has access to SRAM4 in D3 only. Please refer to the reference manual.

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.

Setting the DMA to DMA1 fixes the issue.  Thought I had tried this before and failed, but I must have had other issues in the setup.

Thank You SofLit