This is an old revision of the document!
This tutorial will show how to make use of timers in Contiki. It will also give a basic into to events.
All Contiki programs are processes. A process is a piece of code that is executed regularly by the Contiki system. Processes in Contiki are typically started when the system boots, or when a module that contains a process is loaded into the system. Processes run when something happens, such as a timer firing or an external event occurring.
Code in Contiki can run in one of two execution contexts: cooperative or preemptive. Code running in the cooperative execution context is run sequentially with respect to other code in the cooperative context. Cooperative code must run to completion before other cooperatively scheduled code can run. Preemptive code may stop the cooperative code at any time. When preemptive code stops the cooperative code, the cooperative code will not be resumed until the preemptive code has completed. The concept of Contiki's two scheduling contexts is illustrated above.
Processes always run in the cooperative context. The preemptive context is used by interrupt handlers in device drivers and by real-time tasks that have been scheduled for a specific deadline.
An example process that receives events and prints out their number:
#include "contiki.h" PROCESS(example_process, "Example process"); AUTOSTART_PROCESSES(&example_process); PROCESS_THREAD(example_process, ev, data) { PROCESS_BEGIN(); while(1) { PROCESS_WAIT_EVENT(); printf("Got event number %d\n", ev); } PROCESS_END(); }
The complete reference on Cokiti processes can be found here.
Contiki provides three kinds of timers:
More information on timer can be found on the Contiki's wiki page on timers.
The etimer (Event timer) will post an event when the timer is expiring. Since it posts an event you will need to have a process around it to handle the event.
PROCESS_THREAD(etimer_process, ev, data) { static struct etimer et; PROCESS_BEGIN(); /* set timer to expire after 5 seconds */ etimer_set(&et, CLOCK_SECOND * 5); while(1) { PROCESS_WAIT_EVENT(); /* Same thing as PROCESS_YIELD */ if(etimer_expired(&et)) { /* Do the work here and restart timer to get it periodic !!! */ printf("etimer expired.\n"); etimer_restart(&et); } } PROCESS_END(); }
In the above code the process is defined by PROCESS_THREAD which takes a name, an event variable and an event data variable as the arguments. When an etimer expires the event variable will be set to PROCESS_EVENT_TIMER and the event data variable will be set to point to the specific timer. Using that information the above example could also look like:
PROCESS_WAIT_EVENT_UNTIL(ev == PROCESS_EVENT_TIMER && data == &et); /* Do the work here and restart timer to get it periodic! */ printf("etimer expired.\n"); etimer_restart(&et);
But when waiting for this event in this way – all other events will be ignored so the first approach is more flexible as this will enable handling multiple types of events more easily.