第七章 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();

     }

    }