第七章 TinyOS典型应用

第二节 存储

    module BlinkConfigC {

    uses {

        ...

    interface ConfigStorage as Config;

    interface Mount;

        ...

      }

    }

    (3)每个接口必须绑定到提供该接口的组件。相应的代码如下:

    configuration BlinkConfigAppC {

    }

    implementation {

    components BlinkConfigC as App;

    components new ConfigStorageC(VOLUME_CONFIGTEST);

      /NOLUME_CONFIGTEST 定义在自动生成的StorageVolumes.h头文件中

    ...

      App.Config -> ConfigStorageC.ConfigStorage;

      App.Mount -> ConfigStorageC.Mount;

      ...

    }

    (4)在使用flash存储芯片前,必须先挂载卷。在Boot.booted事件处理函数中调用Mount.mount命令,启动挂载,其代码如下:

    event void Boot.booted() {

        conf.period = DEFAULT_PERIOD;

    if (call Mount.mount() != SUCCESS) {

       //失败情况的处理

    }

    }

    (5)卷挂载成功,就会触发Mount.mountDone事件。接下来,需要检查挂载的卷是否有效。如果卷有效,使用Config.read命令读取卷中的数据即可。否则,调用Config.commit命令使其有效(这个命令也可用来书信缓冲数据,类似于UNIX系统中调用fsync命令可以刷新写入到磁盘上的缓冲),检查挂载的卷的代码如下:

    event void Mount.mountDone(error_t error) {

    if (error == SUCCESS) {

          if (call Config.valid() == TRUE) {    //检查挂载的卷是否有效

    if (call Config.read(CONFIG_ADDR, &conf, sizeof(conf)) != SUCCESS) {

              // 失败情况的处理

            }

          }

    else {

            // 分卷无效,发送commit命令使其有效

    call Leds.led1On();

    if (call Config.commit() == SUCCESS) {

    call Leds.led0On();

            }

    else {

              // 失败情况的处理

            }

          }

        }

    else{

          // 失败情况的处理

        }

      }

    (6)Config.read命令执行成功,就会触发Config.readDone事件。这时,先检查是否成功读取了卷中的内容,如果数据读取成功,再检查版本号。如果版本号与预期的一样,就可以复制配置数据到本地的配置变量,并调节变量period的值;如果版本号不对,就将配置变量设为默认值。最后,调用Config.write函数将新的配置变量写回到flash存储,具体实现代码如下:

    event void Config.readDone(storage_addr_t addr, void* buf,

    storage_len_t len, error_t err) __attribute__((noinline)) {

        if (err == SUCCESS) {   

          memcpy(&conf, buf, len);

          if (conf.version == CONFIG_VERSION) {

    conf.period = conf.period/2;

            conf.period = conf.period > MAX_PERIOD ? MAX_PERIOD : conf.period;

            conf.period = conf.period < MIN_PERIOD ? MAX_PERIOD : conf.period;

          }

    else {

    call Leds.led1On();

            conf.version = CONFIG_VERSION;

            conf.period = DEFAULT_PERIOD;

          }

    call Leds.led0On();

    call Config.write(CONFIG_ADDR, &conf, sizeof(conf));

        } 

    else {

        }

      }