第七章 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 {
}
}