STM32H7 ADC faster than expected
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();
}
