cancel
Showing results for 
Search instead for 
Did you mean: 

TIMER - Overflow event - Must reset CNT?

Skeeb
Associate

Hi There,

I have setup TIMER4 on STM32G484 device for overflow event and enabled interrupt for events. 

Everything works fine and as expected with correct fire time if I RESET the CNT register in the ISR. However, if I do not, it seems to do some level of free-running.

I only inquire about this, as in all of the STM32 reference manual images, when an overflow event occurs and it's been enabled to detect this, the CNT resets in the peripheral (as long as not single shot mode). So I'm just wanting to confirm that this seems normal and is not a hint that I've misconfigured something. Here are my configuration calls and ISR, I verify the ISR timing on the scope with a GPIO toggling (not shown here).

 

 

 

    Register_t rcc_tim4_en =    { .address = 0x40021058, .mask = 0x1, .bit_pos = 2 };
    Read_Then_Write_Masked(rcc_tim4_en, 0x1);

    Register_t tim4_cr_dir =    { .address = k_tim4_addr + k_timx_cr1_offset, .mask = 0x1, .bit_pos = 4 };
    Read_Then_Write_Masked(tim4_cr_dir, 0); // Up counter

    Register_t tim4_smcr_sms =  { .address = k_tim4_addr + k_timx_smcr_offset, .mask = 0x7, .bit_pos = 0 };
    Read_Then_Write_Masked(tim4_smcr_sms, 0); // Slave mode disabled, use internal clock for timer


    Read_Then_Write_Masked(k_tim4_arr, hal::Get_Timer_CLK_Hz() / k_timer_ISR_frequency_Hz);   // No prescaler, overflow at this value

    // Trigger a software driven event update so new capture parameters are forced through
    Register_t tim4_egr_ug =  { .address = k_tim4_addr + k_timx_egr_offset, .mask = 0x1, .bit_pos = 0 };
    Read_Then_Write_Masked(tim4_egr_ug, 1);

....
    Read_Then_Write_Masked(k_tim4_cr1_cen, 1);
    Read_Then_Write_Masked(k_tim4_dier_ue, 1);
....

void hal::timers::Factory::run_priority_tasks()
{
    // Make sure an overflow event is what got us here
    if (! Read_Masked_Shifted(k_tim4_sr_ue))
    {
        //FIXME error handling? This is kind of mission critical
        Abort();
    }

    Write_Masked(k_tim4_cnt, 0);    // Unfortunately the peripheral does not reset this when overflowing
    Write_Masked(k_tim4_sr_ue, 0);  // Reset it so can check on it again next ISR (this is purely a flag, not the interrupt clearing)

    hal::gpio::Factory::get_instance().toggle_debug_led();    
}

 

 

 

 

 

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

When a timer is in normal upcounting free-run mode, CNT resets to 0 after it reaches ARR. It does not need reset to 0, and in fact is already at 0 when the update event is handled.

TDK_0-1739852750794.png

 

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

5 REPLIES 5
TDK
Guru

When a timer is in normal upcounting free-run mode, CNT resets to 0 after it reaches ARR. It does not need reset to 0, and in fact is already at 0 when the update event is handled.

TDK_0-1739852750794.png

 

If you feel a post has answered your question, please click "Accept as Solution".

Thank you for confirming, any ideas with my configuration above why that is not happening? 

It probably is happening. The timer is a hardware state machine, if UIF gets set, an update event occurred, and CNT got set back to 0. It may tick a few times before you can handle it, depending on the timer tick speed. Probably you should recheck your assumptions which led you to believe it's not being set. Why do you think it's not happening?

If you feel a post has answered your question, please click "Accept as Solution".

NOTE: My bad, it was the lack of resetting the SR that was the issue, not the reset of CNT.

Works fine now like this:

void hal::timers::Factory::run_priority_tasks()
{
    // Make sure an overflow event is what got us here
    if (! Read_Masked_Shifted(k_tim4_sr_ue))
    {
        //FIXME error handling? This is kind of mission critical
        Abort();
    }

    //Write_Masked(k_tim4_cnt, 0);    // Unfortunately the peripheral does not reset this when overflowing
    Write_Masked(k_tim4_sr_ue, 0);  // Reset it so can check on it again next ISR (this is purely a flag, not the interrupt clearing)

Note that UE is not a flag within TIMx->SR, but UIF is. Probably that is what you want.

Using standard CMSIS defines can help avoid typos like this, even if in this case the typo didn't matter.

TDK_0-1739887815070.png

 

If you feel a post has answered your question, please click "Accept as Solution".