olekaiwalker
olekaiwalker

Reputation: 51

embedded timer wrap

Currently, im working on an embedded project, where most of the subsystems are based on timing.

i have searched for many solutions to avoid issues with timers rolling over, but one thing still puzzles me.

At present time, i am using the twos complement of unsigned long's like this.

ulong t1 = tick of last event;
ulong t2 = current tick;
if ( t2 - t1 >= limit ){
 do something
}

Others have suggested, that it is necessary to cast the result of t2-t1 to a signed entity, before this will work, but that i can't understand why. Any other insights or suggestions?

Upvotes: 5

Views: 1860

Answers (3)

Jeff
Jeff

Reputation: 1362

Sometimes I do it like this:

ulong t1 = tick of last event;
ulong t2 = current tick;

if ( t1 > t2 ){
    if ((ULONG_MAX-t1+t2+1)>=limit){
       do something
    }
} else {
if ( t2 - t1 >= limit ){
    do something
}

Upvotes: 2

Dmitry Poroh
Dmitry Poroh

Reputation: 3825

You don't have to cast it to signed. If "do something" is alarm handling code and limit is time interval.

The best practice of the regular intervals is:

 ulong next_alarm_ticks = 0;

 void poll_alarm()
 {
     if (get_ticks() - next_alarm_ticks < ULONG_MAX/2) { 
         // current time is "greater" than next_alarm_ticks
         handle_alarm();
         next_alarm_ticks += alarm_interval;
     }
 }

Upvotes: 0

Daniel Fischer
Daniel Fischer

Reputation: 183978

If it is guaranteed that t2 is conceptually always larger than t1, casting to a signed entity would be wrong. Arithmetic of unsigned integers is guaranteed by the standard to be correct modulo UTYPE_MAX + 1, so the difference t2 - t1 will be correct modulo ULONG_MAX + 1 when calculated as unsigned longs. When casting to a signed entity, the behaviour is implementation defined if the value is not representable in the target type. Often that converts large positive values to negative values.

The test

if ( t2 - t1 >= limit ){

will break down if the difference between the current tick count and the previous without wrapping of the timer becomes larger than ULONG_MAX, but otherwise it works.

But if t2 could be earlier than t1, the true difference t2 - t1 would be negative, but as an unsigned long, it would be a potentially large positive number. Then casting to a signed type can work correctly in cases where using unsigned types doesn't.

Upvotes: 0

Related Questions