Timer.h int or unsigned int storage?

28 Jan 2011

Using the Timer class, what is supposed to happen when the timer counter register goes beyond 0x8000 0000? The timer.read_us() returns the value of LPC_TIM3->TC right as a signed integer right?

It makes sense to not use this time for intervals beyond longer than 35 minutes, but what about small intervals during a total system run time beyond 35 minutes?

The timer counter continues beyond 0x7FFF FFFF and does not roll over until 0xFFFF FFFF. Should the return type of read_us() be an unsigned integer instead? If not, would it be better to configure the hardware timer to interrupt and roll over (reset) at 0x7FFF FFFF?

a simple test:

#include "mbed.h"

Timer t;
float a = 0;
int b = 0;
unsigned int c = 0;

int main() {
    printf("\nTimer Test\n");
    t.start();
    wait(1);
    for (int i=0; i < 2; i++) {
        a = t.read();
        printf("a = read() float: %f\n",a);

        b = t.read_us();
        printf("b = read_us() int: %d\n",b);

        c = LPC_TIM3->TC;
        printf("c = LPC_TIM3->TC unsigned int: %u\n",c);

        // simulate 35+ minutes passing
        LPC_TIM3->TC = 0x80050000;
    }

    return 0;
}

29 Jan 2011

Hi Richard,

A Timer is really designed for us to second level timings, as mentioned at the note on the bottom of the Timer Handbook page. For minutes upwards, you should probably consider time() and the real-time clock. The Timer returns an int, which gives a maximum time limit of 2^31-1 us.

The Timer class doesn't actually directly use TIMER3, nor interrupts. TIMER3 is always running at a 1us tick, and is used by Timer, Ticker, Timeout and wait by them sampling it when needed (e.g. start() is invoked on a Timer), then comparing the sampled value at some point in the future when needed (e.g. a read() is invoked on a Timer). So, for example, a Timer may only read 5us, but the TIMER3 could be any value at this point. This has the advantage that all the different objects share the same single timer, and you can have as many Timers/Tickers/Timeouts and wait calls as you want.

There are some good reasons it returns an int/2^31-1 rather than unsigned int/2^32-1 limit, the main being it is inline with the maximum time limits of Ticker and Timeout which rely on the fact they know whether a time is in the past or future (positive or negative difference) to allow e.g. interrupts to be handled late if they get delayed by other events (e.g. two Ticker events scheduled to run at the same time) - it is basically some modulo arithmetic tricks to make sure it all works.

Another reason not to special case Timer (apart from the fact you could only double it) is that you can see if it has wrapped, as it goes negative; you couldn't do this if it was unsigned e.g.:

#include "mbed.h"
Timer t;

int main() 
    t.start();
    while(1) {
        if(t.read_us() < 0) { error("overflow!"); }
        printf("%d us have passed\n", t.read_us());
    }
}

This is not the main reason, but it is another useful feature. Of course, you are free to use TIMER0-2 if you want to write some specialised timer code.

Hope that makes things clear!

Simon

30 Mar 2015

Hallo. I have posted at

http://developer.mbed.org/questions/1406/Why-is-timer-an-int_32-rather-than-uint_/#answer6970

not realizing that this topic would have been the better place. I will have a detailed look at the handbook -> Timer.

However since many years I have developed the clear opinion that SW timers should be unsigned. The past/future aspect of an event is easily checked by testing if the difference between actual and elapsed time stamps is smaller that half the variables range. This is done with no extra effort by the compiler checking the overflow or negative flag. The advantage of easy calculation of elapsed time by a simple subtraction however prevails.