cancel
Showing results for 
Search instead for 
Did you mean: 

Why is analog dma data coming into buffer at 1 index position late?

HForr.1
Associate II

(((Yes, I'm still using Atollic, STM32CubeMX, and HAL. Now is not the time in this project to change these things.)))

I'm individually driving my AN0..AN5 analog inputs, and I've confirmed that the ADC results are showing up in ADC_DMA_BUFFER[1..6]. I would have expected them in ADC_DMA_BUFFER[0..5]. Meanwhile, I'm configured for 7 conversions, the 7th being AN14. It's not showing up in either ADC_DMA_BUFFER[6] (the normally expected location) or ADC_DMA_BUFFER[7] (an otherwise buffer overflow location that was hinted at by the behavior of the first 6 channels). Finally, I'm unable to test if AN14 is erroneously going into ADC_DMA_BUFFER[0] (which would be a looped-back index location).

I've analyzed everything and I believe it's all lined up properly. Why might this be happening? Below is select cut/paste/images from my code and circuit. Thanks in advance for your help!

----------------------------------------------------------------------------------------

static void MX_ADC1_Init(void)

{

 /* USER CODE BEGIN ADC1_Init 0 */

 /* USER CODE END ADC1_Init 0 */

 ADC_ChannelConfTypeDef sConfig = {0};

 /* USER CODE BEGIN ADC1_Init 1 */

 /* USER CODE END ADC1_Init 1 */

 /** Common config 

 */

 hadc1.Instance = ADC1;

 hadc1.Init.ScanConvMode = ADC_SCAN_ENABLE;

 hadc1.Init.ContinuousConvMode = DISABLE;

 hadc1.Init.DiscontinuousConvMode = DISABLE;

 hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;

 hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;

 hadc1.Init.NbrOfConversion = 7;

 if (HAL_ADC_Init(&hadc1) != HAL_OK)

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_0;

 sConfig.Rank = ADC_REGULAR_RANK_1;

 sConfig.SamplingTime = ADC_SAMPLETIME_239CYCLES_5;

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

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_1;

 sConfig.Rank = ADC_REGULAR_RANK_2;

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

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_2;

 sConfig.Rank = ADC_REGULAR_RANK_3;

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

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_3;

 sConfig.Rank = ADC_REGULAR_RANK_4;

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

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_4;

 sConfig.Rank = ADC_REGULAR_RANK_5;

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

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_5;

 sConfig.Rank = ADC_REGULAR_RANK_6;

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

 {

  Error_Handler();

 }

 /** Configure Regular Channel 

 */

 sConfig.Channel = ADC_CHANNEL_14;

 sConfig.Rank = ADC_REGULAR_RANK_7;

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

 {

  Error_Handler();

 }

 /* USER CODE BEGIN ADC1_Init 2 */

 HGF_ADC_INIT();

 /* USER CODE END ADC1_Init 2 */

}

----------------------------------------------------------------------------------------

void HGF_ADC_INIT(void)

{

memset(ADC_DMA_BUFFER,0,sizeof(ADC_DMA_BUFFER)); // Clear DMA memory (mostly just for debugging purposes to make sure all array entries get non-zero data)

HAL_ADCEx_Calibration_Start(&hadc1); // Calibration the ADC on power up for better accuracy

}

----------------------------------------------------------------------------------------

#define ADC_NUMBER_CHANNELS (7) /* Using 7 analog channels: AN0, AN1, AN2, AN3, AN4, AN5, AN14 */

----------------------------------------------------------------------------------------

void HGF_ADC_START(void)

{

HAL_ADC_Start_DMA(&hadc1, ADC_DMA_BUFFER, ADC_NUMBER_CHANNELS); // Start ADC Conversion with DMA xfer to AD_RES (buffer length = # analog channels)

}

----------------------------------------------------------------------------------------

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)

{

for (index_adc=0; index_adc<ADC_NUMBER_CHANNELS; ++index_adc) {

... do stuff with: ADC_DMA_BUFFER[index_adc];

}

}

----------------------------------------------------------------------------------------

0693W00000Nt3hKQAR.jpg

4 REPLIES 4
Nikita91
Lead II

What triggers DMA?

Are you sure this bit is clear before starting DMA?

HForr.1
Associate II

Thanks for participating, @Nikita91​ , but I get the feeling you didn't slow down to read the question -- or maybe I'm more confused than I realize. Specifically, the title question includes "Why is analog dma data". So analog is triggering the DMA, and it's doing so per HAL_ADC_Start_DMA().

To what bit are you referring? Are you referring to a DMA enable bit that is hidden from me and handled by HAL? The DMA *is* indeed happening, so any such enable bit must be set.

Is there possibly any bit setting that would cause the DMA transfer from the ADC result register to go into memory one position later in the array, and then also NOT into that ADC_DMA_BUFFER[7] position, otherwise overflowing what really should have been a 7 element array with last index 6, not 7?

Nikita91
Lead II

It is probably the EOC (End Of Conversion) bit of the ADC that triggers a DMA access to store the value that has just been acquired.

If this bit is set when starting the DMA, it immediately performs an access, since EOC is set, but before the end of the first conversion. This is why the value of the first conversion is in the second cell of the table.

I don't know if this is your case, but I'm telling you because it happened to me.

HForr.1
Associate II

Great, @Nikita91​ , we're on the same page now. Thanks for persisting. Next opportunity I get, I'll look for this EOC bit. This sounds like a HAL bug during initialization, which is certainly possible. (Or it's a HAL config detail too easy for me to omit.) I'll be finding out hopefully in about 40 hours from now.

Hmmm... I also wondered about this: My recollection was that at one time I saw AN0 going into index [0]. But now it doesn't. I have difficulty power cycling. I was already wondering if power cycling would get the AN0 back to [0]. I must power cycle soon in order to check a resistor divider on the board. Maybe AN0 will come back to [0]. If it does, then maybe the EOC bit *state* is getting "orphaned" whenever the processor is reprogrammed for debugging. That is, the system is running, then the debugger reprograms it. Maybe the analog system keeps running during this and was right at a vulnerable point when the reprogram occurred. This all would speak to *incomplete* initialization on my part (refer to quote "too easy for me to omit" above). Maybe if my initialization was *not* incomplete, then even during debugging reprogramming, that EOC bit would get to a *known* state.

I'll think in all these terms next time around! (But maybe I need to investigate complete initialization before power recycling. If I power recycle first and the problem goes away, I may not get another easy opportunity to experience the problem!)

Thanks for letting me think this through!...