The timing for reading the ADC with DMA seems way too long. I calculate just under 36 us to read 8 ADC channels with a STM32L443CCT running at 64 MHz.
I am trying to trigger every millisecond, or 1000 microseconds, but my counters in the interrupt are seeing 167 interrupts per second as opposed to the expected 1000 interrupts per second.
I am reading 6 channels with a sample rate of 92.5 clocks per sample.
I am reading two channels with a sample rate of 247.5 clocks per sample.
Adding the 12.5 clocks for the ADC processing, that totals up to 1150 ADC clocks.
The Processor is running at 64 MHz, but the ADC Clock can not run that fast, so I divide by 2. or 32 MHz or 0.03125 us per clock cycle. Multiply by the 1150 clocks and I get 35.9375 us for the ADC to sample all 8 channels.
Since the tick timer is running at 1000 Hz or every 1000 us so the ADC completing in 36 us should be a piece of cake.
However it looks like the ISR is executing a complete ADC transaction with the DMA exactly 1000 times in 6 seconds not 1000 times in 1 second.
My first thought was the ISR overhead, with all of the HAL stuff. So I short circuited it with a call in the DMA1_Channel1_IRQHandler(void), so it does not call HAL_DMA_IRQHandler(&hdma_adc1);
void DMA1_Channel1_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel1_IRQn 0 */
if ((DMA1->ISR & 0xF) != 0) ADC_DMA_Interrupt();
else
/* USER CODE END DMA1_Channel1_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_adc1);
/* USER CODE BEGIN DMA1_Channel1_IRQn 1 */
/* USER CODE END DMA1_Channel1_IRQn 1 */
}And my ISR is very simple for now;
void ADC_DMA_Interrupt(void)
{
if (DMA1->ISR & DMA_ISR_TCIF1) // transfer Complete
{
ADC_transfer_cnt++;
DMA1->IFCR |= DMA_ISR_TCIF1;
}
if (DMA1->ISR & DMA_ISR_HTIF1) // Half Transfer
{
ADC_half_transfer_cnt++;
DMA1->IFCR |= DMA_ISR_HTIF1;
}
if (DMA1->ISR & DMA_ISR_TEIF1)
{
ADC_error_cnt++;
DMA1->IFCR |= DMA_ISR_TEIF1;
}
}What am I missing? Why is it so slow?