0

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;
}
Blue
  • 820
  • 4
  • 17
cuckoo
  • 111
  • 2
  • 9
  • Probably because of the physical properties of the input/output pins. Their transition times and hi/lo threshold voltages – Eugene Sh. Sep 30 '20 at 20:30
  • I have measured the time between the end of the timer interrupt and the beginning of the GPIO interrupt but didn't find any significant difference – cuckoo Sep 30 '20 at 20:34
  • @EugeneSh. negligible. – 0___________ Sep 30 '20 at 20:34
  • OK, how do you measure the time? – Eugene Sh. Sep 30 '20 at 20:36
  • Are these interrupts guaranteed to arrive at a particular time? Can they be held up if other interrupt processing is under way? – tadman Sep 30 '20 at 20:37
  • @tadman that depends on their priority. – 0___________ Sep 30 '20 at 20:38
  • @P__J__ I'm wondering if there's other interrupt activity getting in the way periodically. – tadman Sep 30 '20 at 20:38
  • @Eugene Sh. Like I said in the post, I used the micro timer to measure the time (reset the counter at the end of timer interrupt and read the counter value at the beginning of GPIO interrupt). Is that a valid way to measure the time? – cuckoo Sep 30 '20 at 20:38
  • Your two wonky transition times do seem to add up to about 2x the cycle time of 832µs. – tadman Sep 30 '20 at 20:40
  • It is not the issue here in my opnion. – 0___________ Sep 30 '20 at 20:44
  • @tadman yes I did notice that but I don't know where it comes from – cuckoo Sep 30 '20 at 20:44
  • `htim2.Instance->ARR = 3333;` will not change the ARR. It will change it on the next overflow – 0___________ Sep 30 '20 at 20:45
  • This is an interesting problem. Can you please add the code which is used for initialization of RX/TX GPIO (mode, speed, etc), EXTI peripheral and IRQ priorities for TX and RX IRQ handler. Can we assume, that no other interrupt is active in your example project? – Blue Oct 04 '20 at 17:06

2 Answers2

1

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___________
  • 60,014
  • 4
  • 34
  • 74
0

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.

ThongDT
  • 162
  • 7