Wednesday, August 10, 2016

Timers: etimer and rtimer - lowest resolution in us and ms

Objective

The objective of this tutorial is to understand which is the lowest resolution that etimer(ms) and rtimer(us) can provide. In order to do this tutorial i used sky motes, however, the same procedure applies to other architectures. I tested the code in Contiki v3.0 and lubuntu 16.04.

Some Background

The lowest resolution of the etimer is given by the CLOCK_SECOND constant, and for the rtimer is given by the RTIMER_ARCH_SECOND constant. The formula for obtaining the lowest etimer resolution is 1 / CLOCK_SECOND seconds, and for obtaining the lowest rtimer resolution is 1 / RTIMER_ARCH_SECOND seconds. Or in Adam Dunkels' words "The only constant is the RTIMER_ARCH_SECOND. I.e., if you have a hardware timer that runs at 32768Hz, the rtimer units is 1/32768 s and RTIMER_ARCH_SECOND is 32768" (See Reference [1] below).

Check the CLOCK_SECOND and the RTIMER_ARCH_SECOND value

So, in order to know the lowest etimer and rtimer resolution you need to know the value of the CLOCK_SECOND and RTIMER_ARCH_SECOND constants, respectively. Following this, to print that values in console you must run the following code in one node. The code creates the #define SHOW_DEFINE(x), which is used to print the values of the constants CLOCK_SECOND and RTIMER_ARCH_SECOND

/*
 * Copyright (c) 2007, Swedish Institute of Computer Science.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of the Institute nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 *
 * This file is part of the Contiki operating system.
 *
 */

/**
 * \file
 *       Show CLOCK_SECOND and RTIMER_ARCH_SECOND values
 * \author
 *        Sergio Diaz
 */


/*INCLUDES*/
#include "contiki.h"

//Show #define values: To USE them put it in the process like this: // SHOW_DEFINE(CLOCK_SECOND); // SHOW_DEFINE(RTIMER_ARCH_SECOND);
#define STR(x) #x
#define SHOW_DEFINE(x) printf("%s=%s\n", #x, STR(x))


/*---------------------------------------------------------------------------*/

PROCESS(show_define_values, "Show define values"); // Declares the process to show the #define values
AUTOSTART_PROCESSES( &show_define_values); // Load the process on boot

PROCESS_THREAD(show_define_values, ev, data) // Start of the process to show the #define values
{ 
  static struct etimer et;
  PROCESS_BEGIN(); // Says where the process starts

  while(1)
  {
    //Printf value every 1 second
    etimer_set(&et, CLOCK_SECOND);

    PROCESS_WAIT_EVENT_UNTIL(etimer_expired(&et)); //Wait for etimer (et) to expire

    SHOW_DEFINE(CLOCK_SECOND); // Show the value of the CLOCK_SECOND in console. To be aware of the etimer resolution
    SHOW_DEFINE(RTIMER_ARCH_SECOND); // Show the value of the RTIMER_ARCH_SECOND in console. To be aware of the rtimer resolution
    printf("\n"); //Printf a "\n"
  }

  PROCESS_END();  //Says where the process ends
}

/*---------------------------------------------------------------------------*/

When you run this code in a Sky mote and view the messages in the console, then you will see this:

CLOCK_SECOND=128UL
RTIMER_ARCH_SECOND=(4096U*8)

That means that the CLOCK_SECOND value is 128 Unsigned (U) Long (L), and that the RTIMER_ARCH_SECOND value is 4096 Unsigned (U) * 8, it means RTIMER_ARCH_SECOND value is 32768. So the lowest resolution for etimer is 1 / CLOCK_SECOND = 1 / 128 s = 7,8125 ms. Besides, the lowest resolution for rtimer is 1 / RTIMER_ARCH_SECOND = 1 / 4096U*8 = 1 / 32768 = 30,5175 us.

Example Setting etimer and rtimer

If you want to set the etimer and rtimer to the lowest resolution in the sky mote you can do the following.

etimer_set(&et, (CLOCK_SECOND / 128) ); //The etimer expires in 7,8125 ms
rtimer_set(&rtimer, RTIMER_NOW() + (RTIMER_ARCH_SECOND / 32768) , 1, carrier_OnOff, NULL);// The rtimer expires in 30,5175 us

You can not use a bigger number than 128 to divide the CLOCK_SECOND, and you can not use a bigger number than 32768 to divide the RTIMER_ARCH_SECOND; because you can not have a bigger resolution without changing the default behaviour of the sky node. If you want the timers to expire in 0,5 seconds you can do this:

etimer_set(&et, (CLOCK_SECOND / 2) ); //The etimer expires in 0,5 s
rtimer_set(&rtimer, RTIMER_NOW() + (RTIMER_ARCH_SECOND / 2) , 1, carrier_OnOff, NULL);// The rtimer expires in 0,5 s

References

[1] https://sourceforge.net/p/contiki/mailman/message/18577635/

1 comment: