‎2025-06-12 2:19 AM - last edited on ‎2025-06-12 2:31 AM by mƎALLEm
Hello ST Team,
We are currently working with the STM32G0B1KCUX series MCU, which has 144 KB RAM and 256 KB Flash.
Our objective is to measure the frequency of an incoming signal using TIM1 in Input Capture mode with DMA (Channel 2). Below are the key configuration and issue details:
We are interested in capturing frequency using DMA mode without any interrupt callbacks. We need a way to synchronize the transfer completion to ensure the captured data is correct
i have Attached timer settings and code snippet
Timer Configuration:
Timer: TIM1 (16-bit)
Clock Frequency: 64 MHz (no prescaler)
DMA: Used to capture values without interrupt
Slave Mode: Reset mode with trigger on TI1FP1
Input Signal:
Frequency Range: 15.8 kHz to 16 kHz
Signal Period: Approximately 62.5 µs to 63.3 µs
Observation:
When checking the DMA_ISR_TCIF2 flag before reading, the time between frequency measurements varies inconsistently — sometimes 1ms, 2ms, or 3ms.
However, if we remove the DMA complete flag check, the capture reads occur at a rate matching the system clock and signal input, i.e., much faster and more consistent.
We are confused why adding this DMA transfer complete flag check:
results in millisecond-level delays between readings, even though the input signal is at ~63 µs intervals. Without this check, data comes in faster, matching expectations.
‎2025-06-12 2:49 AM - edited ‎2025-06-12 2:50 AM
It appears that you've set up the slave-mode controller in Reset mode triggered from channel 1, i.e. the setup which is in RM called "PWM Input". That alone should be enough to measure frequency, you shouldn't need DMA for that. At the same time, in that setup, it's unlikely two successive readings would result in any significant difference - regardless of whether in us or ms - if the input signal's frequency is stable.
So, either you don't show us relevant portions of the setup and relevant portions of code, or the input signal is intermittent.
Also, note, that it's not unlikely that Cube/HAL interrupt handlers would execute for hundreds to thousands of cycles, i.e. up to tens of us.
JW
‎2025-06-12 3:21 AM
Hi thanks for the reply since we are reading this input frequency continuously what kind of setup or timer configuration would you recommend so that we can read efficiently with low latency any reference? please check the below attached code snippet
‎2025-06-12 6:19 AM
> We are confused why adding this DMA transfer complete flag check:
> results in millisecond-level delays between readings,
Because the flag is checked and cleared within the HAL_DMA_IRQHandler. You should leave it alone, or you should remove the call to HAL_DMA_IRQHandler if you want to handle it yourself and implement your own handling of the flag.
‎2025-06-19 8:35 AM
Hi thanks for the reply i understood your point and i have made changes since i have commented out the irq handler and i will be waiting in the polling method for the new data available once new data available i need to process as quickly as possible so will the below things are correct
So we need a capture in dma method only and i need to process as soon as possible
i need to reduce the overhead for calling interrupt callback and then process the freq
// Disable DMA IRQ to prevent interrupt processing
HAL_NVIC_DisableIRQ(DMA1_Channel2_3_IRQn);
// Disable DMA transfer complete interrupt
__HAL_DMA_DISABLE_IT(htim1.hdma[TIM_DMA_ID_CC1], DMA_IT_TC);
// Clear any pending DMA flags
__HAL_DMA_CLEAR_FLAG(htim1.hdma[TIM_DMA_ID_CC1], DMA_FLAG_TC2 | DMA_FLAG_HT2);
// Start DMA in circular mode (runs continuously)
if (HAL_TIM_IC_Start_DMA(&htim1, TIM_CHANNEL_1, (uint32_t *)captr_pwm, CAPTR_SAMPLE_COUNT) != HAL_OK)
{
printf("TIM1 IC Start Error\n\r");
}
static inline uint32_t captr_pulse_freq(void)
{
// Early exit if data not ready
if (!(DMA1->ISR & DMA_ISR_TCIF2)) return 0;
// Clear flag
DMA1->IFCR = DMA_IFCR_CTCIF2;
//process the freq
}
void DMA1_Channel2_3_IRQHandler(void)
{
/* USER CODE BEGIN DMA1_Channel2_3_IRQn 0 */
/* USER CODE END DMA1_Channel2_3_IRQn 0 */
// HAL_DMA_IRQHandler(&hdma_tim1_ch1);
/* USER CODE BEGIN DMA1_Channel2_3_IRQn 1 */
/* USER CODE END DMA1_Channel2_3_IRQn 1 */
}
‎2025-06-23 9:37 AM
Hi I have just provided below a reference flow will it be ok or should I need to change anything else
‎2025-06-23 10:21 AM
DMA flags need to be checked and handed within the IRQ handler, otherwise it will continuously re-trigger. Interrupts are enabled within HAL_TIM_IC_Start_DMA. You can disable interrupts after calling that, and wrap it all within a __disable_irq/__enable_irq, if you don't want interrupts to be called.