Timer with a long response time problem

HI,i need a timer with a one-time duration of 1.5 hours.once. Here is the initialization of the timer
reset_timer = xTimerCreate("RESET_TMR",pdMS_TO_TICKS(5400000UL),pdFALSE, (void*)0, (TimerCallbackFunction_t)reset_tmr_cb);

configuration of ticks

#define configTICK_RATE_HZ      ( ( TickType_t ) 1000 )
#define configUSE_16_BIT_TICKS    0

The problem is that the timer is triggered after 18 minutes and not after 90…What am I doing wrong?

does all of your other timing work as expected? For example, if you have a blinky app where you vTaskDelay() for one second between LED events, do you see ± 1 second blink intervals, or is that way off as well?

Yes. All other timings in app (max 20 sec) works fine

1.5 hours overflows the interger mathematics in pdMS_TO_TICKS, as it will multiply the time by the tick rate, which will then exceed 2^32. The overflow point with a 1 ms/1000 Hz tick is about 1 hour 12 minutes, which is why you end up with 18 minutes.

Solutions:

  1. specify your time (if over than an hour) as an “unsigned long long” with the ULL suffix

  2. create a new conversion macro pdS_TO_TICKS for long delays that doesn’t divide the result by 1000, so you give the parameter as a smaller number.

  3. look to see if you really need a 1 ms tick rate. In my experience most do not. It mostly is for “error” timeouts, which don’t need the accuracy, or polling loops which rarely need to be that fast or accurate. With even a 2 ms tick rate (500 Hz) your time won’t overflow.

  4. If you know you are using 1 ms tick rate, then you don’t need to use pdMS_TO_TICKS, but can just pass the value in milli-seconds as the period.

2 Likes

If the port supports, you can also define configTICK_TYPE_WIDTH_IN_BITS to TICK_TYPE_WIDTH_64_BITS - FreeRTOS-Kernel/portable/GCC/ARM_CM4F/portmacro.h at main · FreeRTOS/FreeRTOS-Kernel · GitHub.

1 Like

One simple solution could be to setup a timer with a 1 minute expiration, and count 90 timer ticks. The overall current consumption (if resuming from sleep) overhead would be negligible, yet you would have a possible cancellation point every minute should you decide later that you no longer want the timer.

1 Like

Thanks for the reply. It was more important for me to understand what the reason was, I felt that there was an overflow somewhere, but I couldn’t figure out where. In my case, the solution is very simple - an hour’s delay is enough for me, or even since I don’t plan to change the tick time, I can do without this macro

reset_timer = xTimerCreate("RESET_TMR",5400000UL,pdFALSE, (void*)0, (TimerCallbackFunction_t)reset_tmr_cb);

. Now I will know this nuance in pdMS_TP_TICKS arithmetic.