Chinaunix首页 | 论坛 | 博客
  • 博客访问: 253429
  • 博文数量: 65
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 375
  • 用 户 组: 普通用户
  • 注册时间: 2014-11-29 21:49
个人简介

Flowers_World

文章分类

全部博文(65)

文章存档

2017年(7)

2016年(38)

2015年(14)

2014年(6)

我的朋友

分类: 嵌入式

2015-12-30 09:31:24

原文地址:Contiki基础 作者:fly123456789

简介

Contiki是一个开源多任务事件驱动操作系统,为网络嵌入式设备设计。它轻量级的足印(footprint)很适合内存有限的MCU。

Contiki集成了数个独立的模块,在一个事件驱动的类线程多任务的环境中,包含了protothread library、uIP TCP/IP(v4和v6)协议栈、无线传感器网络的协议套件—Rime协议栈。

Contik主要为网络应用程序而设计,但也可运行仅使用它的事件驱动内核的非网络程序。

事件

Contiki内核基于事件驱动。这类系统的核心思想是,程序的每次执行都是一个事件的响应。整个系统(内核+链接库+用户代码)可以多进程并行执行。

不同的进程一般执行一段时间,然后等待事件发生。在等待时,这个进程的状态称为阻塞。当一个事件发生时,内核执行由事件传递来的信息指向的进程。在所等待的事件发生时,内核负责调用相对应的进程。

事件被分为以下三种:

·定时器事件(timer events:进程可以设置一个定时器,在给定的时间之后生成一个事件,进程一直阻塞直到定时器终止,才继续执行。这对周期性操作很有用,或者用于网络协议,比如涉及同步。

·外部事件(external events:外围设备连接至具有中断功能的MCU的IO引脚,触发中断时可能生成事件。例如按键,射频芯片或脉冲探测加速器都是可以产生中断的装置,可以生成此类事件。进程可以等待到这类事件后相应地响应。

·内部事件(internal events:任何进程都有可以为自身或其他进程指定事件。这对进程间通讯很有用,例如通知某个进程,数据已经准备好可以进行计算。

对事件的操作被称为投递(posted),一个中断服务程序将投递一个事件至一个进程当它被执行时。事件具有以下信息:

·process:进程被事件寻址,它可以是特定的进程或所有注册进程。

·event type:事件类型。用户可以为进程定义一些事件类型用来区分它们,比如一个类型为收到数据包,另一个为发数据包。

·data:一些数据可以同事件一起提供给进程。

Contiki操作系统主要的理念是:事件被投递给进程,进程触发后开始执行直到阻塞,然后等待下一个事件。

进程

进程在Contiki中相当于任务(task)。进程的构造基于protothread library,使用local continuation library实现。更多信息参考下文提供的链接。

一个进程是一个C函数包括一个死循环和一些阻塞宏调用。由于Contiki事件驱动内核不是抢占式的,每个进程会在被事件阻塞时才停止执行。一些宏用来处理不同的阻塞情况。这允许使用编程状态机作为流控制。以下是contiki进程的架构,由contiki官方网站提供

1#include "contiki.h"

2

/* The PROCESS() statement defines the process' name. */

3PROCESS(my_example_process, "My example process");

4

/* The AUTOSTART_PROCESS() statement selects what process(es)

5   to start when the module is loaded. */
6AUTOSTART_PROCESSES(&my_example_process);

7

/* The PROCESS_THREAD() contains the code of the process. */

8PROCESS_THREAD(my_example_process, ev, data)
9{
10  /* Do not put code before the PROCESS_BEGIN() statement -
11     such code is executed every time the process is invoked. */
12  PROCESS_BEGIN();
13  /* Initialize stuff here. */
14  while(1) {
15    PROCESS_WAIT_EVENT();
16    /* Do the rest of the stuff here. */
17  }
18  /* The PROCESS_END() statement must come at the end of the
19     PROCESS_THREAD(). */
20  PROCESS_END();
21}

由于是架构,很明显该代码没有完成任何事。它反复在等待一个事件发生,一遍又一遍……

以下有一些在使用protothreads(或Contiki processes)编程时需要特别注意的事项

·局部变量未被保护:当进程调用一个阻塞宏,实际是当前进程函数返回了,让内核调用其他的进程。当某个事件被投递,内核将调用相同的进程函数,函数将跳转至它之前返回的位置。因此如果进程的局部变量(如果没有被声明为静态(static))在阻塞前被赋值,阻塞后继续执行,将不能保证仍为相同的值。一个好的方式是在进程函数中使用静态(static)变量。

·不要使用switches:protothreads使用local continuations在返回后找回函数状态时,使用了switch语句。只有case语句放在if或while的语句块中,才不会和另一个switch语句混淆。因此,最好就是不要在进程函数中使用switch函数。

uIP TCP/IP stack

Contiki包括了一个轻量级的TCP/IP协议栈叫做uIP。它实现了RFC-定义的IPv4,IPv6,TCP和UDP(后两个兼容IPv4和IPv6)。uIP很高效,只实现了协议要求的特性。例如整个协议栈只有一个buffer,用于接收和发送数据报。

Application API

这里有两种方法使用uIP协议栈写程序:

·raw API:uIP raw API很适合实现一个简单的应用,例如一个简单的’echo’ server可以监听一些TCP端口并且将它收到的每个数据发送回去。然而当实现一个全功能的程序时编码变得越来越复杂,或者当多个程序需要共同使用时。甚至TCP连接状态机都有些烦人。

·protosocket API:protosocket library利用 protothread library,提供一个更灵活的方式编写TCP/IP程序。这个库提供了一个类似于标准BSD sockets的接口,并允许在一个进程中编写程序。

Lower Layers

拥有一个有效的TCP/IP协议栈并且某些程序可以运行在其上当然很好,但是还不够。uIP协议栈要求一个更低的层(根据OSI模型)为了和peers通讯。我们将讨论两种类型的peers。

·节点(nodes):节点间通信是由无线连接实现的。uIP协议栈需要能够发送和接受数据包。取决于uIP版本,Contiki遵循不同的方法:

·当使用IPv6,Contiki将遵循route-over配置。因此,uIP6使用一个被称为sicslowmac的简单MAC层。除了头部压缩由6loWPAN模型提供,它仅通过射频转发数据包。

·然而,对于IPv4,Contiki选用mesh-under配置。这由Rime通讯协议栈完成。Rime提供mesh routing和路由发现,因此uIP使用它来转发网络上的数据包。从IP point的角度来看,所有的传感器网络节点组成了一个本地子网,虽然multiple radio hops可能被要求。

·网关(gateways):与WSN以外的网络通信,必须通过网关。网关连接WSN和另一个网络。一般接入的是PC,也可以是其他嵌入式系统。PC和mote是串口线连接的。IP报文通过SLIP协议在两者之间发送。在计算机端,必须运行一个程序作为串口线和网络接口的接口。根据uIP协议栈版本,节点的作用不同。

·使用uIPv6时,有一个节点将被装载一个非常简单的程序,转发从射频收到的所有数据包至串口线,或者反向发送,它不做任何的地址比对,没有IP协议栈运行在它上面,除了头部压缩/解压机制(6loWPAN)。这个节点被PC端仅视为一个以太网接口,由PC完成所有工作。

·使用uIPv4时则完全不同,节点作为网关连接至PC,有完整的IP协议栈在节点上运行。每当它收到数据包要发送,节点将检查报文的IP地址:如果它属于WSN子网范围,它将使用射频发送,否则它将使用串口线发送至PC。由PC运行一个程序来创建IP层网络接口。

Rime stack

Rime协议栈提供一种递阶型无线网络协议,从简单的匿名广播到mesh网络路由。一个复杂的协议(比如multihop mesh routing)实现会被分解成若干部分,复杂的模块利用相对简单的模块来组成。

以下是对Rime不同模块的简述:

·abc:匿名广播,它仅通过射频驱动发送数据包和接收所有的数据包,并将他们送至上层;

·broadcast:标识广播,它为发出的数据包添加了发送者地址,然后传递给abc模块;

·unicast:这个模块添加给数据包添加一个目标地址,再传递给broadcast模块。在接收端,如果数据包的目标地址和当前节点地址不符,该数据包将为丢弃。

·stunicast:当要求发送数据包至某个节点,它将在给定的时间周期内反复发送,直到要求停止。

·runicast:可信单播,它使用stunicast模块发送数据包,并等待确认报文,收到后停止持续重发数据包。为了防止无限次发送,必须指定一个最大重发次数。

·politeipolite:这两个模块几乎相同,当一个数据包必须在给定的时间帧内被发送,模块在到达时间的一半时,检查是否收到的数据包与它准备发送的相同。如果收到了,这个数据包将不被发送,否则发送。这是一个有效的泛洪技术,可以避免没必要的重发。

·multihop:这个模块要求一个路由表功能,当将要发送数据时它会请求路由表提供下一跳,并且使用unicast发送。当它收到一个数据包,如果本身即为目标节点就将数据包传至上层,否则再次请求路由表提供下一跳并转发。

MAC

如我们所见,uIPv6协议栈使用了一个非常简单的MAC层协议称为sicsomac,没有其他选择。但是uIPv4协议栈使用Rime作为它的直接下层,因此可以选择MAC层协议。

以下是一些在Contiki上实现的MAC协议:

nullmac协议,正如其名,它什么都不做只是从更高层转发数据包至射频驱动,或者反向。

xmac协议,序文采样协议,节点周期性短时间监听射频频道。

lpp协议,探针协议,节点周期性发送一小段消息通知正在监听,之后监听一小段时间后休眠。

Eample

以下是本文提到的一些代码示例与解释:

本文翻译自: 如果转载,请注明来源!

阅读(662) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~