实验的结果:红灯长亮,并没有进行闪烁,将数值变小后进行闪烁。 原因:计算干扰了Timer的操作。‘ 利用task的实验:
task void computeTask() { uint32_t i;
for (i = 0; i < 400001; i++){} }
event void Timer0.fired() { call Leds.led0Toggle(); post computeTask(); }
此段代码的含义:灯反转,再循环400,001次。 实验的结果:灯不断进行闪烁。
原因:task将计算与Timer的操作分开,由一个任务来执行计算。post操作将task放入一个任务序列,利用FIFO原则,完成一个任务继续执行下一个任务,不影响当前的操作。 进一步优化task操作: uint32_t i;
task void computeTask() { uint32_t start = i;
for (;i < start + 10000&& i < 400001; i++){} if (i >= 400000) { i = 0; } else {
postcomputeTask(); } }
event void Timer0.fired() { call Leds.led0Toggle(); post computeTask(); }
此段代码的含义:将计算分为10000次的多个小任务。实验的结果:红灯闪烁的频率变快。可见代码的效率提高修改优化代码:
task void computeTask() { static uint32_t i; uint32_t start = i;
for (;i < start + 10000&& i < 400001; i++){} if (i >= 400000) { i = 0; }
else {
postcomputeTask(); } }
在此段代码中将静态变量i设置为局部变量。在nesC中,由于组件的状态是完全私有的,使用静态变量不利于命用,也就是说可能和别的组件中变量的定义冲突,因此应注意静态变量变为局部变量。
TinyOS, task
TinyOS学习笔记5-Split-Phase操作 Split-Phase操作
比较以下Blocking和Split-Phase操作的两段代码 Blocking
if (send() == SUCCESS) { sendCount++; }
在Block的系统中,当要调用一个运行时间很长的操作时,直到操作完成调用才能返回。例如,只有执行完sen返回值。
Split-Phase // start phase send();
//completion phase
void sendDone(error_t err) { if (err == SUCCESS) { sendCount++; } }
在Split-Phase操作中,将程序的执行分为两个部分,开始部分和完成部分。 Split-Phase操作的好处:
1.节省内存,与block的操作需要stack相比,节省了内存stack的开销。 2.可以并行运行多个操作。 下面是另一个例子 Blocking:
state = WAITING; op1();
sleep(500); op2();
state = RUNNING
在此个Block的例子中,整个程序需要进行sleep(500)
Split-phase:
state = WAITING; op1();
call Timer.startOneShot(500);
event void Timer.fired() { op2();
state = RUNNING; }
此Split-Phase的操作,在调用Timer.startOneShot(500)后,程序立即返回,整个程序并没有停止,过500ms后,自void Timer.fired()
以上均为本人读过tutorials的总结,还会继续更新。
TinyOS, Split-Phase
TinyOS 学习笔记6- 基本的通信接口
基本的通信接口:
Packet:为message_t的抽象数据类型提供访问的接口
Packet.nc的位置为/opt/TinyOS-2.1.1/tos/interfaces/Packet.nc
#include
interface Packet {
//清空数据包,将msg的数据清空重新使用 command void clear(message_t* msg);
//返回信息负载的长度
command uint8_t payloadLength(message_t* msg); //设置负载长度
command void setPayloadLength(message_t* msg, uint8_t len); //返回最大负载
command uint8_t maxPayloadLength(); //获取负载,len为需要的负载的长度
command void* getPayload(message_t* msg, uint8_t len); }
message.h为于/opt/tinyos-2.1.1/tos/types/message.h,其主要内容如下:
#include \
typedef nx_struct message_t {
nx_uint8_t header[sizeof(message_header_t)]; nx_uint8_t data[TOSH_DATA_LENGTH];
nx_uint8_t footer[sizeof(message_footer_t)];
nx_uint8_t metadata[sizeof(message_metadata_t)]; } message_t;
platform_message.h为于相应平台下的目录中,例如在/telosb/mac/tkn154/platform_message.h
telosb
中为/opt/tinyos-2.1.1
telosb所采用的MAC层为802.15.4的MAC协议,用户无需再关心MAC协议,该Message同样定义了如何于串口nx_struct为nesC中的结构体,即可理解成c语言中的stuct nx_uint8_t,为无符号的8位整型数据
Send:提供基本的无地址信息发送接口
#include
interface Send {
//设置发送数据包的负载长度
command error_t send(message_t* msg, uint8_t len); //取消数据的传输
command error_t cancel(message_t* msg); //发送数据完成
event void sendDone(message_t* msg, error_t error); //返回通讯层允许的最大负载长度 command uint8_t maxPayloadLength();
//获取负载
command void* getPayload(message_t* msg, uint8_t len); }
Receive:提供基本的信息接收接口
#include
interface Receive {
//返回数据包的buffer,msg接收的数据包,数据包负载的指针,负载长度。
event message_t* receive(message_t* msg, void* payload, uint8_t len); }
PacketAcknowledgements:在每个包上为请求ACK提供一个策略
interface PacketAcknowledgements {
//告诉协议,当要发送这个数据包时,使用同步的ACK async command error_t requestAck( message_t* msg ); //不使用同步ACK
async command error_t noAck( message_t* msg ); //传输的数据包是否为ACK
async command bool wasAcked(message_t* msg); }
async的含义:同步
RadioTimeStamping:为无线通讯提供时间戳信息 interface RadioTimeStamping {
//提供帧开始传输的时间,时间单元是a 32kHz clock
async event void transmittedSFD( uint16_t time, message_t* p_msg ); //开始接收帧的时间
async event void receivedSFD( uint16_t time ); }
接口, 通信, TinyOS
TinyOS 学习笔记7- ACtive Message接口 Active Message Interfaces
由于会出现多个服务利用同一个radio通信的情况,TinyOS提供了AM层来多元访问radio。 AM type代表AM的类型,与以太网的帧类型,IP协议区,UDP协议区相类似。 AM address接收节点的地址,目的区域
AMPacket:对AM数据包的基本设置
位于/opt/tinyos-2.1.1/tos/interfaces/AMPacket.nc #include
interface AMPacket {

