cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H7 ADC faster than expected

tarzan2
Associate III

Hello,

Using a STM32H743ZI - rev. V.

I'm using ADC3 to convert 4 channels in regular conversion mode, with a 2.5Tcy sampling time, 10 bits, sync clock /2.

The measured conversion time is quicker than expected so I'm suspecting something wrong...

CPU clock is 400MHz, AXI/AHB clock is 100MHz.

DMA transfers ADC results to AXI SRAM. I've fine tune my program for speed (gcc optimization for speed, release mode, interrupt routine relocated in ITCM with only the necessary code). 

TIM15 trigs the ADC, and also activate an output pin.

The first thing I do in the DMA interrupt is to rise a GPIO pin. So, I can measure the total time : TRIG + sampling & conversion + DMA transfert time + IRQ latency + GPIO write.

This measured time is 1100ns.

The ADC clock is 100MHz divided by 2 (CKMODE=0b10) and by 2 (internal /2 in rev V version) so 25MHz <=> Tck=40ns.

Trig time : 1.5~2.5Tck

Samp time : 4*2.5Tcy = 10Tck

Conv time : 4*(N/2+0.5) = 22Tck

Total expected time : 33.5~34.5Tck = 1340~1380ns => 23% faster than measured. There is definitely something wrong in my configuration or interpretation.

Many thanks pour your help 🙂

ADC config:

 

  hadc3.Instance = ADC3;
  hadc3.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV2;
  hadc3.Init.Resolution = ADC_RESOLUTION_10B;
  hadc3.Init.ScanConvMode = ADC_SCAN_ENABLE;
  hadc3.Init.EOCSelection = ADC_EOC_SEQ_CONV;
  hadc3.Init.LowPowerAutoWait = DISABLE;
  hadc3.Init.ContinuousConvMode = DISABLE;
  hadc3.Init.NbrOfConversion = 4;
  hadc3.Init.DiscontinuousConvMode = DISABLE;
  hadc3.Init.ExternalTrigConv = ADC_EXTERNALTRIG_T15_TRGO;
  hadc3.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING;
  hadc3.Init.ConversionDataManagement = ADC_CONVERSIONDATA_DMA_CIRCULAR;
  hadc3.Init.Overrun = ADC_OVR_DATA_OVERWRITTEN;
  hadc3.Init.LeftBitShift = ADC_LEFTBITSHIFT_NONE;
  hadc3.Init.OversamplingMode = DISABLE;

 

 

Clock config with 20MHz crystal:

 

  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLM = 2;
  RCC_OscInitStruct.PLL.PLLN = 80;
  RCC_OscInitStruct.PLL.PLLP = 2;
  RCC_OscInitStruct.PLL.PLLQ = 2;
  RCC_OscInitStruct.PLL.PLLR = 2;
  RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
  RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
  RCC_OscInitStruct.PLL.PLLFRACN = 0;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
                              |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
  RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }

 

 

6 REPLIES 6
Pavel A.
Evangelist III

Conversion and DMA may overlap?

 

 

AScha.3
Chief II

Hi,

so Tck (25M->40ns) is the ADC clock - right ? 

ADC needs at N=10 bits + 2.5 sampling:  2.5 + (N/2+0.5) = 8 x 40ns = 320ns ( 3Msps )

So some delay in your measurement, if you see 1100ns.

>23% faster than measured

How you measure it ?

If you feel a post has answered your question, please click "Accept as Solution".
TDK
Guru

It's difficult to measure the ADC conversion time in this way. Your measurement will include errors that aren't associated with the ADC.

If you want to measure it, here's a good method:

  • Set up a circular ADC DMA transfer to a large buffer. Something like 1000 samples.
  • Within the transfer complete callback, toggle a pin.
  • Measure the time between two successive toggles to estimate the time it takes to capture the entire buffer.

This method will have the same amount of overhead/delay on each toggle and will therefore cancel it out.

If you feel a post has answered your question, please click "Accept as Solution".

@AScha.3 wrote:

so Tck (25M->40ns) is the ADC clock - right ? 

ADC needs at N=10 bits + 2.5 sampling:  2.5 + (N/2+0.5) = 8 x 40ns = 320ns ( 3Msps )

So some delay in your measurement, if you see 1100ns.

>23% faster than measured

How you measure it ?


There is 4 channels in regular conversion mode. So 320ns*4=1280ns.

Adding trigger time, DMA transfert time, IRQ latency and GPIO write, I would expect to measure something between 1400 and 1600ns, I dont know... But definitely it should be more than 1280ns !

I could think that the ADC clock is not 25MHz but faster, making the sampling time and boost bits wrong.

I measure it with a 1GS/s scope :

- Channel 1 on TIM15 output, showing the beginning of ADC conversion

- Channel 2 on a GPIO rised at the beginning of the DMA interrupt :

void DMA2_Stream3_IRQHandler(void)       // @ITCM RAM
{
   GPO_TP3_GPIO_Port->BSRR = GPO_TP3_Pin;
   asm volatile("" ::: "memory");        // Avoid asm code re-ordering by the optimizer.

 

Some news...

- In debug mode, all ADC registers, including clocks and sampling time, are good.

- The MCO configured to output SYSCLK/10 is toggling at 40MHz. So SYSCLK is verified at 400MHz.

Modifying the ADC sampling time give some interesting results. It looks like the ADC clock is 50MHz instead of 25MHz. 

Looking more carefully how the ADC clock sclk is generated, I've found it is derived from sys_clk, not from ahb_clk. My adc was actually clocked at 50MHz. After reprogramming CKMODE to /4 instead of /2, the timings are looking ok.

The datasheet mentions the maximum adc frequency without precision about which clock we are talking about. I assume it is the final conversion clock. There is nothing about potential limitation on adc_sclk and adc_hclk. I assume they can accept all sysclk and ahbclk range.

A more unfortunate thing is that after reading AN5354, I see that the ADC clock is also limited by the package. Using 3 ADC, for my LQFP144 the max clock is 30MHz and not 50MHz as specified in the datasheet. Very bad that the datasheet don't mention anything about that.

 

>A more unfortunate thing is that after reading AN5354, I see that the ADC clock is also limited by the package. Using 3 ADC, for my LQFP144 the max clock is 30MHz and not 50MHz as specified in the datasheet. Very bad that the datasheet don't mention anything about that.

Your not right - in ds there are more or less clear indications of the problem - but no clear values.

see on top of ADC chapter...the most important footnote !

AScha3_1-1721739304182.png

 

AScha3_0-1721739132810.png

 

>> "might differ "  --> = everything else is worse. (But this was deleted by the marketing departrment . 🙂  )


It is the an5354 (and maybe others..) to read.... to really know.

If you feel a post has answered your question, please click "Accept as Solution".