Skip to main content
Guidoted
Associate III
July 8, 2024
Solved

Strange values when reading timer CNT

  • July 8, 2024
  • 15 replies
  • 3824 views

I have a timer (TIM10) with a period of 500 us, running without interrupt or any other function.

Then I have a rising+falling signal interrupt on PB0 (EXTI0) driven with a 31.25 kHz square wave.

In EXTI0 I read the CNT value into a variable New, evaluate the difference with the previous CNT value Old (obviously considering the case when Old value is greater than New value) and copy the New into Old for the next EXTI0 interrupt.

What I see is that many times the difference between New and Old, which should be about 16 us, is even 40, 80, 100 us or more!

I've checked with a signal output on a pin and a scope that I have EXTI0 interrupts correctly every 16 us, without any interrupt loose or other strange behaviours.

Seem's like sometimes (many times...) the CNT value read is not the current one but some strange old value.

What could be the problem?

Thanks

 

This topic has been closed for replies.
Best answer by waclawek.jan

> Are you saying that debugger is changing the variable values?

No.

The debugger stops execution upon your breakpoint, but TIM10 continues to run and rolls over many times until you start executing again (and also EXTI continues to be triggered by the incoming pulses).

That, unless you have set the respective DBGMCU_APBx_FZ.DBG_TIMx_STOP bit, directly or indirectly through some tickbox in your debugging environment/IDE). But even then, the "problem" with EXTI being already triggered while execution is stopped, remains, so the next difference will not reflect the true difference between edges anyway.

I repeat, debug this in some other way, which does not involve breakpoints and execution stops. Or, if you insist, take this effect into account - e.g. have a counter in the ISR, which allows it to be executed at least twice in a row without the breakpoint, and only then allow the breakpoint:

static uint32_t cnt;

... // do the thing with reading TIMx_CNT and making the diff here
if (cnt == 2) {
 __NOP; // place breakpoint here
 cnt = 0;
} else {
 cnt++;
}

JW

15 replies

waclawek.jan
Super User
July 8, 2024

Show code.

JW

 

PS.

> I have a timer (TIM10) with a period of 500 us

How did you verify this?

Guidoted
GuidotedAuthor
Associate III
July 8, 2024

It is programmed with a prescaler of 10 and a period of 49999.

 

waclawek.jan
Super User
July 8, 2024

> In EXTI0 I read the CNT value into a variable New, evaluate the difference with the previous CNT value Old (obviously considering the case when Old value is greater than New value) and copy the New into Old for the next EXTI0 interrupt.

Show code.

> What I see is that many times the difference between New and Old, which should be about 16 us, is even 40, 80, 100 us or more!

How do you "see" that?

JW

Guidoted
GuidotedAuthor
Associate III
July 8, 2024

I discarded the code, but i was about so:

(newTimer and oldTimer defined as uint32_t global variables)

...

newTimwer = TIM11->CNT;

if(newTimer > oldTimer) {

....

}

else {

....

}

 

oldTimer = newTimer;

....

 

With a breakpoint on "oldTimer = newTimer;" line, I watch the values of both variables

 

gbm
Super User
July 8, 2024

There is no need for two cases. Just do:

 

 

static uint16_t PrevVal;
uint16_t CurrVal = TIM10->CNT;
uint16_t lap = CurrVal - PrevVal;
PrevVal = CurrVal;

 

lap variable will always have a proper value, regardless of timer rollover. It's all about proper data types. :) No need for global (maybe lap should be global if it's used outside of ISR).

My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice
waclawek.jan
Super User
July 8, 2024

If you stop mcu execution by breakpoint and the external pulse train and/or TIM keep running, the results are confusing.

Chose a different method of debugging - using debuggers is intrusive.

JW

 

PS.

newTimwer = TIM11->CNT;

This won't work well with TIM10.

waclawek.jan
Super User
July 9, 2024

If you stop mcu execution by breakpoint and the external pulse train and/or TIM keep running, the results are confusing.

Chose a different method of debugging - using debuggers is intrusive.

JW

Guidoted
GuidotedAuthor
Associate III
July 9, 2024

Thanks JW, but I don't watch the CNT values, I watch the values of variables timerDiff16, timerNew16 and timerOld16.

Are you saying that debugger is changing the variable values?

 

waclawek.jan
waclawek.janBest answer
Super User
July 9, 2024

> Are you saying that debugger is changing the variable values?

No.

The debugger stops execution upon your breakpoint, but TIM10 continues to run and rolls over many times until you start executing again (and also EXTI continues to be triggered by the incoming pulses).

That, unless you have set the respective DBGMCU_APBx_FZ.DBG_TIMx_STOP bit, directly or indirectly through some tickbox in your debugging environment/IDE). But even then, the "problem" with EXTI being already triggered while execution is stopped, remains, so the next difference will not reflect the true difference between edges anyway.

I repeat, debug this in some other way, which does not involve breakpoints and execution stops. Or, if you insist, take this effect into account - e.g. have a counter in the ISR, which allows it to be executed at least twice in a row without the breakpoint, and only then allow the breakpoint:

static uint32_t cnt;

... // do the thing with reading TIMx_CNT and making the diff here
if (cnt == 2) {
 __NOP; // place breakpoint here
 cnt = 0;
} else {
 cnt++;
}

JW

BarryWhit
Lead
July 9, 2024

unless you have set the respective DBGMCU_APBx_FZ.DBG_TIMx_STOP bit, 

Configuring the chip to stop the timers when the debugger breaks makes life much easier when debugging capture values.

I repeat, debug this in some other way, which does not involve breakpoints and execution stops.

Monitoring the captured values using the "Live expressions" functionality in CubeIDE would work, but note you can't be 100% sure you're not blinking precisely when some outlier event occurs, since the values are constantly updating.

 

Simplest would be to check the value in software and turn on a LED if it exceeds some threshold (do not reset the LED once set). If the LED stays off, you're ok.

"- If someone's post helped resolve your issue, please thank them by clicking ""Accept as Solution"".- Please post an update with details once you've solved your issue. Your experience may help others."
Guidoted
GuidotedAuthor
Associate III
July 9, 2024

Many thanks JW and Barry,

now I understood what happens and clearly my problem is that EXTIO0 interrupt contnues to run with my square wave input on PB0 and continues to change the variable values.

I will do more test to understand it better.

Thanks again and best regards