cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F103 Timer Capture Problem

Jeroen3
Senior

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

1 ACCEPTED SOLUTION

Accepted Solutions
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

View solution in original post

10 REPLIES 10
Posted on April 19, 2017 at 12:24

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

JW

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.

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
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?

Posted on April 19, 2017 at 16:46

In an isolated project the period time measurement works fine. 

In the full project, if I enable any additional timer, problems arise. Ranging from once a minute to once every 5 seconds.

These 'occasional' bugs are the best...

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.

Posted on April 19, 2017 at 20:20

Who told you it's easy?

What I said is to cut out pieces from the existing problematic program, those you judge to be irrelevant, down until it's minimal but still exhibiting the problem. There are also other ways to isolate the problem of course. You can try to post portions of the program as it is now, e.g. the ISR alone, but then how do you know the issue is within the posted portion.

> TIM3->SR &= ~TIM_SR_CC2IF;

Don't RMW, do direct write, otherwise you risk missing interrupts, the TIMx_SR bits are rc_w0 for a reason. Besides, the capture flags are cleared by hardware when reading the capture register, so you don't need to do that at all.

Take into account the possiblity the interrupt being invoked simply because of late arrival of a cleared signal into NVIC also in the timer ISR, as you've experineced with the EXTI ISR. Btw., DSB is not a panacea, it's simply a form of time wasting not dissimilar to NOP (although with different timing implications).

JW

Posted on April 19, 2017 at 21:02

I am familiar with the basics used to isolate these issues. I just don't practice them a lot because this is my first full greenfield.

Don't RMW, do direct write, otherwise you risk missing interrupts, the TIMx_SR bits are rc_w0 for a reason. Besides, the capture flags are cleared by hardware when reading the capture register, so you don't need to do that at all.

I didn't notice the rc_w0. Great tip. I did indeed notice the superfluous clear. 

There is a bit of variety in the peripherals some are write 0 to clear some write 1 clear. I just used the 'standard' way of clearing bit. Force of habit I guess.

Jeroen3
Senior

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.