第七章 TinyOS典型应用
第二节 存储
(7)调用Config.commit命令。当调用ConfigStore.write命令并触发Config.writeDone事件时,并不能保证数据一定写入了flash。为了确保数据被保存到flash,就要调用Config.commit命令,调用Config.commit命令的代码如下:
event void Config.writeDone(storage_addr_t addr, void *buf,
storage_len_t len, error_t err) {
// Verify addr and len
if (err == SUCCESS) {
if (call Config.commit() != SUCCESS) {
// Handle failure
}
}
else {
// Handle failure
}
}
(8)将数据写入flash中,当Config.commitDone事件触发时,数据就将被永久地写入到flash中,并能够存活一个能量循环,具体实现代码如下:
Event void Config.commitDone(error_t err) {
call Leds.led0Off();
call Timer().startPeriodic(conf.period);
if (err == SUCCESS) {
//失败情况的处理
}
}
7.2.3 日志数据的存储
通常,应用程序需要可靠地记录事件和小数据项,因此TinyOS提供一种日志形式的记录方式,这种记录方式记录的数据即使在系统崩溃时也不会丢失。日志记录可以是顺序录入(卷满就停止录入)也可以是循环录入(卷满就从该卷的起始地址开始写入)。
TinyOS系统的日志存储抽象具有这些特点:
1)日志是基于记录的,每次调用LogWrite.append命令就创建一条新纪录;
2)节点断电时(崩溃或能量循环),日志只丢失最近的记录;
3)一旦循环日志绕了一圈,日志就覆盖最早的记录。
示例程序PacketParrot(tinyos-2.x/apps/tutorials/PacketParrot/)演示了如何使用LogWrite和LogRead接口记录日志。该应用程序的主要功能是:节点将无线接收到的数据记录到flash中;如果读取失败,则擦除该日志,然后继续接收并记录数据包,如此循环运行。为了便于观察和调试,我们在程序中设定:当日志被擦除时,点亮红色LED灯(Led0);接收到数据包时则点亮黄色LED灯(Led1),成功录入后熄灭;如果数据包被接收但没有被录入(因为日志正在被擦除),黄色LED灯保持点亮状态;在一个能量循环后,如果记录的数据包被取出并发送出去,绿色LED灯(Led2)快速闪烁。下面将对PacketParrot的设计要点和具体操作步骤进行介绍。
(1)使用日志存储使用日志存储的第1步是要确定存储什么样的数据到日志里。PacketParrot 程序声明了如下的结构体:
Typedef nx_struct logentry_t{
nx_uint8_t len;
message_t msg;
}logentry_t;
(2)传递缓冲区指针和读取字节数。与配置存储不同,日志存储不需要挂载卷。一个简单的read命令就可以实现日志的读取,LogRead.read命令传递缓冲区指针和读取字节数,代码如下:
event void AMControl.startDone(error_t err) {
if (err == SUCCESS) {
if (call LogRead.read(&m_entry,sizeof(logentry_t)) != SUCCESS) {
//Handle error
}
}
else {
call AMControl.start();
}
}