Skip to main content
Jeroen3
Senior
April 19, 2017
Solved

STM32F103 Timer Capture Problem

  • April 19, 2017
  • 10 replies
  • 3206 views

Posted on April 19, 2017 at 11:43

In a project I'm attempting to measure 4 frequency channels (range 10 to 500 hz) using TIM3 in the STM32F

During development I noticed the occasional missed capture event, or double capture events. I didn't pay much attention to these glitches thinking it was my hardware that glitched around a bit.

However, a completely other project with the same software has an identical problem. Then it must be software, right?

I've looked and it for a few days, and I think I found another problem in the timer capture hardware.

The erratas currently there:

In capture mode, when a capture occurs while the CCRx register is being read, the capture flag (CCxIF) may be cleared without the overcapture flag (CCxOF) being set. The new data are actually captured in the capture register

If a capture occurs while the capture register is being read, an overcapture is detected even though the previously captured data are correctly read and the new data are correctly stored into the capture register

But it seems unrelated to the reading of the capture registers because the frequency of my signal is relatively slow.

Following this I created a bare metal example, with 1 channel, and I found that when the capture flag is active longer than approximately 25 us, the capture interrupt never triggers.

What happens:

- PC7 has a falling edge. EXTI is pending immediately, TIM3 has hardware filtering first.

- The EXTI triggers, and sets PD2.

- The EXTI runs a series of nops to delay the execution of TIM3 ISR.

- The TIM3 ISR does timer stuff.

- The

TIM3

ISR clears PD2.

Now when I add one extra nop to the EXTI, the capture will occasionally miss. (probably when PC7 falls during systick)

As seen in this image:

<LINK NO LONGER ACTIVE>

Is this hardware, or a flaw in my software?

(void)register performs a dummy read to R0, I've checked.

The obvious workaround is to use software capture using the EXTI, but that would require the unfiltered EXTI to be at a very high nvic priority. Not ideal.

Source:

https://github.com/Jeroen6/stm32f103_capture_problem/blob/master/main.c

Chip: STM32F103RCT7 - GH239 93 - CHN GH 445

input-capture stm32f103 errata

This topic has been closed for replies.
Best answer by waclawek.jan
Posted on April 20, 2017 at 14:52

You don't need to check  for overflow.

delta = period + capture - previous_capture;

if (delta > period) delta-= period;

JW

10 replies

waclawek.jan
Super User
April 19, 2017
Posted on April 19, 2017 at 12:24

Count the number of occurences of each interrupt - both counts have to be identical.

JW

Jeroen3
Jeroen3Author
Senior
April 19, 2017
Posted on April 19, 2017 at 13:22

I found that there were twice as much EXTI IRQ's than TIM3 IRQ's. 

There had to be a __DSB(); after the pending flags were cleared. Immediate return causes issues.

However, now I am unable the reproduce the problem in the bare metal variant. But the problem is worse in the full project. 

Now 1 in 7 capture is corrupted.

waclawek.jan
Super User
April 19, 2017
Posted on April 19, 2017 at 14:12

However, now I am unable the reproduce the problem in the bare metal variant. But the problem is worse in the full project. 

Now 1 in 7 capture is corrupted.

Then there's some other issue. Try to reduce to minimal your 'full project' while checking if the problem still persists.

JW

S.Ma
Principal
April 19, 2017
Posted on April 19, 2017 at 17:36

Have you disabled all other interrupt sources? Usually input capture will miss if something disable interrupts too long in the main loop, or if in some isr there can be delays. Interrupt priorities and behaviour programming is important. Can you share the timer capture isr code?

Jeroen3
Jeroen3Author
Senior
April 19, 2017
Posted on April 19, 2017 at 19:55

There are some segments where interrupts are globally are disabled. This is done to copy some data between ISR threadspace to main threadspace. When the nvic is enabled again, the chip is supposed to start with any pending interrupts.The capture flags do still work when doing this, don't they?

The behavior in the main code is the occasional two failed captures. I only noticed this now, playing around with STM Studio*.

Say normal T delta is 80, then a capture of delta 15 is measured, followed by a capture of The 150 I can understand, it's because the last one was skipped or early. However the early capture confuses me, especially since the EXTIdoes not register this one as being early.

When I disable many other peripherals, the probability of the glitch decreases. Meaning there is something to do with timings.

I'm now seeing clearing the capture flags is superfluous, but the code looks like this:

void TIM3_IRQHandler(void){
 IRQ_PROLOGUE(); 
 // Capture channel 1
 if(TIM3->SR & TIM_SR_CC1IF){
 uint32_t c = sw_extend | TIM3->CCR1;
 compute_period(0, c);
 TIM3->SR &= ~TIM_SR_CC1IF;
 }
 // Capture channel 2
 if(TIM3->SR & TIM_SR_CC2IF){
 uint32_t c = sw_extend | TIM3->CCR2;
 compute_period(1, c);
 TIM3->SR &= ~TIM_SR_CC2IF;
 }
 // Capture channel 3
 if(TIM3->SR & TIM_SR_CC3IF){
 uint32_t c = sw_extend | TIM3->CCR3;
 compute_period(2, c);
 TIM3->SR &= ~TIM_SR_CC3IF;
 }
 // Capture channel 4
 if(TIM3->SR & TIM_SR_CC4IF){
 uint32_t c = sw_extend | TIM3->CCR4;
 compute_period(3, c);
 TIM3->SR &= ~TIM_SR_CC4IF;
 }
 // Update (overflow)
 if(TIM3->SR & TIM_SR_UIF){
 compute_overflow();
 compute_frequency();
 // Flag ISR complete 
 TIM3->SR &= ~TIM_SR_UIF;
 }
 // Trigger
 if(TIM3->SR & TIM_SR_TIF){
 TIM3->SR &= ~TIM_SR_TIF;
 }
 // Overcapture (no interrupt)
 if(TIM3->SR & (TIM_SR_CC1OF | TIM_SR_CC2OF | TIM_SR_CC3OF | TIM_SR_CC4OF)){
 overcapture++;
 TIM3->SR &= ~(TIM_SR_CC1OF | TIM_SR_CC2OF | TIM_SR_CC3OF | TIM_SR_CC4OF);
 }
 __ISB();
 IRQ_EPILOGUE();
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Which looks reasonable to me.

*I am aware of the unstable sample rate of stm studio.

Jeroen3
Jeroen3Author
Senior
April 20, 2017

Posted on April 20, 2017 at 13:46

Is this hardware, or a flaw in my software?

Good news everyone: It is my software.

The probabilty of the event slim. But the problem exists when the ISR handlerhas to handle both capture and overflow flags.

This means on entry of the ISR two things are known:

- Capture x contains a value.

- The counter was reset.

This means that the ISR has to figure out if the capture was before or after the overflow. And that part was missing.

The probability of the event depends on the jitter from IRQ to ISR. And thus on ISR priority and exclusive code.

How to fix this? Add the

if( overflow flag )

part.

if( timer overflow flag ){
 // Overflow and Capture in the same handler
 if( capture < counter ){
 // Capture after overlow. else capture before overflow
 set overflow event flag
 }
}
if( overflow event flag ){
 // Overflow between captures
 T = counter_max - previous capture;
 T = capture + T;
}else{
 T = capture - ch[i].n1;
}�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?�?

Thanks

https://community.st.com/s/profile/0050X000007vs4BQAQ

for having me look at interrupts priorities and noticing the jitter problem.

Thanks

https://community.st.com/s/profile/0050X000007vqmpQAA

forhaving me notice the need of DMB's and superflous flag clearings.

waclawek.jan
waclawek.janBest answer
Super User
April 20, 2017
Posted on April 20, 2017 at 14:52

You don't need to check  for overflow.

delta = period + capture - previous_capture;

if (delta > period) delta-= period;

JW