STM32G474 TIM triggered ADC + DMA limited to 50kHz (50ksps)
Hi all, I am triggering ADC conversion from TIM1 and I can't achieve sampling rate higher than 50kHz. I am using STM32G474RE and HAL library. Based on AN5496 and AN5497 I should be able to do it up to 200kHz and my target is 100kHz.
I am testing STM32G474 (STEVAL-DPSG474) for a power converter application where i need to sample ADC at 100kHz (Timer TRGO driven). For that purpose I use ADC + DMA sampling without FMAC, and SPI transfering the sampled data.
As ADC samples in 16bit format (12bit converter) I am using 2 bytes per data for SPI transfer. A tests would send 2 values through SPI, one comming from ADC (2 variable bytes), and the other a fixed one for debug (2 fixed bytes):
// main.c
/* USER CODE BEGIN PV */
#define Buflen 1
uint16_t adcValue = 0;
volatile uint16_t adc_dma_result[Buflen];
uint8_t SPI_buffer_tx[4] = {20, 60, 160, 200};
/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
void MX_GPIO_Init(void);
static void MX_DMA_Init(void);
void MX_RTC_Init(void);
static void MX_ADC1_Init(void);
static void MX_TIM15_Init(void);
static void MX_TIM16_Init(void);
static void MX_TIM17_Init(void);
static void MX_TIM1_Init(void);
static void MX_SPI3_Init(void);
/* USER CODE END PV */
int main(void)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_RTC_Init();
MX_ADC1_Init();
MX_TIM15_Init();
MX_TIM16_Init();
MX_TIM17_Init();
MX_TIM1_Init();
MX_SPI3_Init();
/* USER CODE BEGIN 2 */
/* Perform an ADC automatic self-calibration and enable ADC */
if (HAL_ADCEx_Calibration_Start(&hadc1, ADC_SINGLE_ENDED) != HAL_OK)
{
/* Configuration Error */
Error_Handler();
}
/* Start the ADC DMA */
if ( HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_dma_result, Buflen) != HAL_OK)
{
/* Configuration Error */
Error_Handler();
}
// start pwm generation
if(HAL_TIM_PWM_Start(&htim1, TIM_CHANNEL_1) != HAL_OK) {
Error_Handler();
}
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
}
}
In order to debug the development I am sending an SPI message with logged ADC data every Transfer Completed using HAL predefined function
// stm32g4xx_it.c
/* USER CODE BEGIN 1 */
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc)
{
/* Prevent unused argument(s) compilation warning */
//UNUSED(hadc);
if (hadc == &hadc1) {
adcValue = adc_dma_result[0];
SPI_buffer_tx[1]=adcValue & 0xFF;
SPI_buffer_tx[0]=(adcValue >> & 0xFF;
HAL_SPI_Transmit(&hspi3, SPI_buffer_tx, sizeof(SPI_buffer_tx), 1000);
//If continuousconversion mode is DISABLED uncomment below
HAL_ADC_Start_DMA(&hadc1, (uint32_t*)dmaBuffer, Buflen);
}
}
/* USER CODE END 1 */
Main clock is HSI + PLL (170MHz) for TIM and ADC is configured at 56.66MHz, so a single ADC input should be done in less than 10us (1/100kHz).

To configure TIM1 to trigger TRGO at 100kHz I am configuring it with PSC = 0 and ARR = 1699. 170MHz TIM1 CLK would result on 100kHz period as stated in this support note.
What I achieve is a 50kHz sampling (20us between SPI transfers). If I increase TIM1 ARR over 3.399 (value for 50kHz) the sampling rate starts to decrease from 50kHz. I can sample at exact 20kHz, 30kHz, 40kHz... but under ARR=3.399 I can't see any sampling increase over 50kHz. Could it be because AN5497 is based on CRM SRAM memory instead of flash? Could it be because they use DMA+FMAC instead of DMA register reading? Could it be because I use HAL library and LL is more optimised for register programming?
In next figure I represent 50kHz ADC sampling and SPI sending (20us between SPI send) sending 4 bytes.

When I RUN the code (no matter if Debug or Release version) it samples just once, and in ADC I can measure a decreasing value from original value. In numbers:
ADC input is 0V, that with right alignment corresponds to around 17000 ADC value (12 bits). In SPI (hex coded) I can see around 10-20 samples starting from 17000 and ending at 0. Could it be the ADC SAR capacities discharging? (as If I only sample once)
Thanks in advance for any help or tip!

