第三章 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。