Senstools
Hardware
Software
Drivers
Operating systems
Libraries
Drivers
Operating systems
Libraries
Contiki is an open-source multitasking event-driven operating system designed for networked embedded devices. Its lightweight footprint makes it suitable for memory constraint microcontrollers.
Contiki gathers several independent modules such as an event-driven thread-like multitasking environment with the protothread library, the uIP TCP/IP (v4 and v6) stack, the wireless sensor network set of protocols: the Rime stack.
Contiki is primarily designed for networking applications, but can be used for any other application using only its event driven kernel.
You can visit the official website for more information.
This page describes the main functionality of Contiki, and what works on the WSN430 platform. The Contiki source files ported for the WSN430 platform are found in the download section. For setup howto and examples, see the Contiki example page.
The Contiki kernel is event-driven. The idea of such a system is that every execution of a part of the application is a reaction to an event. The entire application (kernel + libraries + user code) may contain several processes that will execute concurrently.
The different processes usually execute for some time, then wait for events to happen. While waiting, a process is said to be blocked. When a event happen, the kernel execute the process passing it information about the event. The kernel is responsible for activating the processes when the events they're waiting for happen.
Events can be classified in three kinds:
Events are said posted. An interrupt service routine will post an event to a process when it is executed. Events have the following information:
This is the main principle of the Contiki Operating System: events are posted to processes, these execute when they receive them until they block waiting for another event.
Processes are the task-equivalent of Contiki. The process mechanism uses the underlying protothread library (website) which in turn uses the local continuation library (website). Refer to the given links for more information.
A process is a C function most likely containing an infinite loop and some blocking macro calls. Since the Contiki event-driven kernel is not preemptive, each process when executed will run until it blocks for an event. Several macros are defined for the different blocking possibilities. This allows programming state-machines as a sequential flow of control. Here is the skeleton of a Contiki process, as provided by the Contiki website:
#include "contiki.h" /* The PROCESS() statement defines the process' name. */ PROCESS(my_example_process, "My example process"); /* The AUTOSTART_PROCESS() statement selects what process(es) to start when the module is loaded. */ AUTOSTART_PROCESSES(&my_example_process); /* The PROCESS_THREAD() contains the code of the process. */ PROCESS_THREAD(my_example_process, ev, data) { /* Do not put code before the PROCESS_BEGIN() statement - such code is executed every time the process is invoked. */ PROCESS_BEGIN(); /* Initialize stuff here. */ while(1) { PROCESS_WAIT_EVENT(); /* Do the rest of the stuff here. */ } /* The PROCESS_END() statement must come at the end of the PROCESS_THREAD(). */ PROCESS_END(); }
This code does obviously nothing, since it's a skeleton. It waits repeatedly for an event to happen, and again…
There are some special consideration to take care of when programming with protothreads (or Contiki processes):
static
) were given some values before blocking, these values are not guaranteed to hold the same value when continuing after the block! A good way to work it around is to use static
variables in the process function.switch
statement. If the case
statements can be put almost anywhere (in an if
or a while
section), it can't be mixed up with another switch
statement. Therefore it is better not to use switch
statements inside a process function.Please look at the examples section for some simple application showing the use of processes
Contiki contains a lightweight TCP/IP stack called uIP (uIP website). It implements RFC-compliant IPv4, IPv6, TCP and UDP (the latter two compatible with IPv4 and IPv6). uIP is very optimized, only the required features are implemented. For instance there is a single buffer for the whole stack, used for received packets as well as for those to send.
There are two ways to program an application on top of the uIP stack:
Refer to the examples section for some explained networking examples.
Having a functional TCP/IP stack and some applications running on top of it is good, but not enough. The uIP stack requires a lower layer (according to the OSI model) in order to communicate with peers. We'll distinguish two different types of peers:
The Rime stack provides a hierchical set of wireless network protocols, from a simple anonymous broadcaster to a mesh network routing. Implementing a complex protocol (say the multihop mesh routing) is split into several parts, where the more complex modules make use of the simpler ones.
Here is the overall organization of the Rime protocols:
And here is a brief description of the different modules of Rime:
As we've seen, the uIPv6 stack use a very simple MAC layer called 'sicslomac', and there is no real option here. However the uIPv4 stack uses Rime as its immediately lower layer, which in turn uses a selectable MAC layer.
There are a few MAC layers implemented in Contiki:
What has been ported and tested so far on the WSN430 platform follows:
See the dedicated Contiki Example Page for the list of examples and their explanations.
Here is the archives, the Contiki OS ported for the WSN430, along with the examples: