3

I am trying to use gettimeofday on an embedded ARM device, however it seems as though I am unable to use it:

gnychis@ubuntu:~/Documents/coexisyst/econotag_firmware$ make
Building for board: redbee-econotag
       CC obj_redbee-econotag/econotag_coexisyst_firmware.o
LINK (romvars) econotag_coexisyst_firmware_redbee-econotag.elf
/home/gnychis/Documents/CodeSourcery/Sourcery_G++_Lite/bin/../lib/gcc/arm-none- eabi/4.3.2/../../../../arm-none-eabi/lib/libc.a(lib_a-gettimeofdayr.o): In function `_gettimeofday_r':
gettimeofdayr.c:(.text+0x1c): undefined reference to `_gettimeofday'
/home/gnychis/Documents/CodeSourcery/Sourcery_G++_Lite/bin/../lib/gcc/arm-none-eabi/4.3.2/../../../../arm-none-eabi/lib/libc.a(lib_a-sbrkr.o): In function `_sbrk_r':
sbrkr.c:(.text+0x18): undefined reference to `_sbrk'
collect2: ld returned 1 exit status
make[1]: *** [econotag_coexisyst_firmware_redbee-econotag.elf] Error 1
make: *** [mc1322x-default] Error 2

I am assuming I cannot use gettimeofday() ? Does anyone have any suggestions for being able to tell elapsed time? (e.g., 100ms)

gnychis
  • 7,289
  • 18
  • 75
  • 113

5 Answers5

7

What you need to do is create your own _gettimeofday() function to get it to link properly. This function could use the appropriate code to get the time for your processor, assuming you have a free-running system timer available.

#include <sys/time.h>

int _gettimeofday( struct timeval *tv, void *tzvp )
{
    uint64_t t = __your_system_time_function_here__();  // get uptime in nanoseconds
    tv->tv_sec = t / 1000000000;  // convert to seconds
    tv->tv_usec = ( t % 1000000000 ) / 1000;  // get remaining microseconds
    return 0;  // return non-zero for error
} // end _gettimeofday()
JonS
  • 621
  • 7
  • 25
2

What I usually do, is to have a timer running at 1khz, so it will generate an interrupt every millisecond, in the interrupt handler I increment a global var by one, say ms_ticks then do something like:

volatile unsigned int ms_ticks = 0;

void timer_isr() { //every ms
    ms_ticks++;
}

void delay(int ms) {
    ms += ms_ticks;
    while (ms > ms_ticks)
        ;
}

It is also possible to use this as a timestamp, so let's say I want to do something every 500ms:

last_action = ms_ticks;

while (1) {  //app super loop

    if (ms_ticks - last_action >= 500) {
        last_action = ms_ticks;
        //action code here
    }

    //rest of the code
}

Another alternative, since ARMs are 32bits and your timer will probably be a 32bits one, is to instead of generating a 1khz interrupt, you leave it free running and simply use the counter as your ms_ticks.

Vinicius Kamakura
  • 7,665
  • 1
  • 29
  • 43
  • thanks for your answer! do you have any good documentation on how to set up the timer and interrupt handler? is this easy to do on the system? – gnychis Aug 10 '11 at 01:19
2

Use one of the timers in the chip...

old_timer
  • 69,149
  • 8
  • 89
  • 168
0

It looks like you are using the Econotag which is based on the MC13224v from Freescale.

The MACA_CLK register provides a very good timebase (assuming the radio is running). You can also use the the RTC with CRM->RTC_COUNT. The RTC may or may not be very good depending on if you have an external 32kHz crystal or not (the econotag does NOT).

e.g. with MACA_CLK:

uint32_t t;

t = *MACA_CLK;

while (*MACA_CLK - t > SOMETIME);

See also the timer examples in libmc1322x:

http://git.devl.org/?p=malvira/libmc1322x.git;a=blob;f=tests/tmr.c

Alternate methods are to use etimers or rtimers in Contiki (which has good support for the Econotag). (see http://www.sics.se/contiki/wiki/index.php/Timers )

Spudley
  • 166,037
  • 39
  • 233
  • 307
Mariano Alvira
  • 216
  • 1
  • 3
-3

I've done this before in one of my applications. Just use :

while(1)
{
...
}
Sparkup
  • 3,686
  • 2
  • 36
  • 50
Jim Hubbard
  • 111
  • 2
  • 6