Skip to main content
Graduate
July 8, 2024
Solved

Strange values when reading timer CNT

  • July 8, 2024
  • 6 replies
  • 3752 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

    6 replies

    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?

    GuidotedAuthor
    Graduate
    July 8, 2024

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

     

    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

    GuidotedAuthor
    Graduate
    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

     

    Graduate
    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).

    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.

    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

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

     

    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

    Graduate II
    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.

    GuidotedAuthor
    Graduate
    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