Why is there a timing difference in periodically interrupt?

290 views Asked by At

I am writing a low level driver for a type of one line communication protocol. This line is connected to both Tx pin and Rx pin on a STM32F0 micro running internal clock at 8Mhz. The Tx pin state is set in a timer interrupt, and the Rx pin is read in a external GPIO interrupt.

For testing, I toggle the Tx pin at 416µs (auto reload value is 3333 with no prescaler), and in the GPIO interrupt I read the timing difference between 2 consecutive interrupts. The measured time are roughly 500µs from "High To Low" transition interrupt to "Low To High" transition interrupt and 300µs from "Low To High" transition interrupt to "High To Low" transition interrupt. Why is there such a difference? And how to get rid of it?

I have checked the signal on the scope and it's a perfect square wave with pulse width of 416µs. I also use htim->Instance->CNT = 0; and time = htim->Instance->CNT; to wrap different parts of the code to find where the difference comes from but no avail.

Here are the interrupt handles, the measured time is saved in tim3_value variable:

void TIM2_IRQHandler(void)
{
  if (__HAL_TIM_GET_FLAG(&htim2, TIM_FLAG_UPDATE) != RESET)
  {
    if (__HAL_TIM_GET_IT_SOURCE(&htim2, TIM_IT_UPDATE) != RESET)
    {
        __HAL_TIM_CLEAR_FLAG(&htim2, TIM_FLAG_UPDATE);
        HAL_GPIO_TogglePin(TX_GPIO_Port, TX_Pin);
        htim2.Instance->ARR = 3333;
    }
  }
return;
}

void EXTI4_15_IRQHandler(void)
{
  if(__HAL_GPIO_EXTI_GET_IT(RX_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(RX_Pin);
    tim3_value = htim3.Instance->CNT;
    htim3.Instance->CNT = 0;
  }
return;
}
2

There are 2 answers

1
0___________ On

STM32 timers have ARR preloaded. It means that it will change the actual value of the interal ARR register on the update event. If you want to change it at particular moment you need to generate this event yourself by writing 1 to the UG bit in the EGR register.

I strongly advice to read carefully the STM32 Reference Manual as magical HAL functions are not enough

I would not do it in the interrupt anyway. STM32 times have a mechanism called "direct transfer mode". It uses DMA to load the value(s) of the timer register on the chosen event. You just need to prepare data for it and on the update event ARR will be loaded from the memory autoatically.

0
ThongDT On

There isn't enough information to check for your issue.

In general, there are some cause that might impact to your measurement results:

  • Interrupt latency: for STM32F0 it is ~16 cycles. Additionally, if there are other interrupt it might add delay up to few us. However, seem that this is not your case since you mentioned that tolerances are somehow constant.
  • Physical property of input and output pin. This depends on the configuration of GPIO as well as the connection between Tx pin and Rx pin. In some cases, this impact a lot to the measurement result. Please try to measure it with an oscilloscope.

For better measurement, it is also recommend to use the timer module for stable result. The timer also provide "Input Capture" feature. This approach is better because it could remove impact of interrupt latency/priority.