第三章 TinyOS编程语言nesC

第四节 模块

    例3.11:

    typedef struct RPEstEntry {

    uint16_t id;

    uint8_t receiveEst;

    } _attribute_ (( packed )) RPEstEntry;

    在TinyOS 2.x中的做法是使用了nesC 1.2中的平台独立类型。对于简单数据类型而言,除了在关键字之前加上nx_(表示高字节顺序布局)或者nxle_(低字节顺序布局)前缀外,平台独立类型数据的定义(声明)与正常类型数据一致。如例3.12。

    例3.12

    nx_uint16_t val; // A big -endian 16-bit value

    nxle_uint32_t otherVal; // A little -endian 32-bit value

    除了简单数据类型,也有独立于平台的结构体(struct)和共用体(union),分别用nx_struct和nx_union声明。这些数据类型中的每个域也必须是平台独立类型。非位的域以字节为单位对准边界。例如,针对无线通信芯片CC2420的通信分组控制头的平台独立的结构体如下。在所有硬件平台上编译这个结构体时都使用相同的内存布局,对结构体中的各个域都使用相同的字节顺序。这就使得平台代码可以封装和解封装该结构体,而不用使用htons、ntohl等宏指令。

    typedef nx_struct cc2420_header_t{

    nxle_uint8_t length;

    nxle_uint16_t fcf;

    nxle_uint8_t dsn;

    nxle_uint16_t destpan;

      nxle_uint16_t dest;

      nxle_uint16_t src;

      nxle_uint8_t type;

    }cc2420_header_t;

    对大多数nesC代码,可以忽略运行时间的开销。如例3.13。

    例3.13

    nx_uint16_t x = 5;

    uint16_t y = x;

    上述代码需要几个处理器时钟周期将x的字节重新排序,按照本地芯片的字节顺序形成y。需要注意的是,系统处理开销与转化次数成正比。因此,在需要对某个平台独立类型进行大量计算或者多次访问时,需要先将其转化为本地数据格式来处理。例如,要对多字节数组执行计算,应在计算前把这些数组复制到本地格式,在计算结束后再将这些数组复制回平台独立的数据中。

    3.常值变量

    在TinyOS程序实现中往往需要一些常量,比如,重传次数或阀值。可以采用常值变量、枚举以及#define三种方式实现,这三种方式可以达到相同的效果,但是内存分配及其他方面稍有不同。例如,定义一个最大重传次数,这三种方式声明(定义)分别如下。

    方式一:常值变量

    const int MAX_RETRANSMIT = 5;

    方式二:MAX_RETRANSMIT 5枚举类型的常量

    enum {

    MAX_RETRANSMIT = 5

    };

    方式三:宏定义 #define

    #define MAX_RETRANSMIT  5

    在C中,常值变量是一种常用方式,它属于静态存储分配,编译器会为其分配一块RAM或ROM区域,即便程序运行完,这部分存储区域也不释放。使用枚举常量(枚举元素)来定义常量也可以达到相同的目的。枚举常量在节省内存方面优于前一种方式,属于动态存储变量。相应程序函数运行结束,这部分区域可以重新使用。枚举常量在某些方面也优于第三种方式宏定义,因为枚举常量存在调试符号表和应用的元数据中。然而,枚举常量也有一些局限性,只能声明整数常量,而使用宏定义还可以定义浮点和字符串常量等。

    需要注意的是,由于枚举类型默认为整数宽度,使用枚举类型声明变量可能浪费内存。例如枚举类型变量state_t的定义如例3.14。