第七章 TinyOS典型应用
第二节 存储
(3)检查返回的数据长度。如果LogRead.read命令返回SUCCESS,那LogRead.read Done事件就会马上被触发。在LogRead.readDone事件中,首先检查返回的数据长度是否和预期长度一样。如果一致,可以将该数据无线发送出去;否则,可以认为日志是空的,或已失去了同步,那么日志就需要被擦除,代码如下:
Event void Logread.readDone(void* buf, storage_len_t len, error_t err) {
If ( (len == sizeof(logentry_t)) && (buf == &m_entry) ) {
call Send.send(&m_entry.msg, m_entry.len);
call Leds.led1On();
}
else {
if (call LogWrite.erase() != SUCCESS) {
//Handle error
}
call Leds.led0ON();
}
}
(4)接收数据包并将其中的数据写入flash。接收到来自无线电的数据包,并调用LogWrite.append命令将数据包中的数据写入到flash,具体实现代码如下:
event message_t* Receive.receive(message_t* msg, void* payload, uint*_t len) {
call Leds.led2On();
if (!m_busy) {
m_busy = TRUE;
m_entry.len = len;
m_entry.msg = *msg;
if (call LogWrite.append(&m_entry, sizeof(logentry_t)) !=SUCCESS) {
m_busy = FALSE;
}
}
return msg;
}
(5)触发LogWrite.appendDone事件如果LogWrite.append返回SUCCESS,就会触发LogWrite.appendDone事件。这个事件返回了日志写入的详情,如缓冲区指针、写入数据的长度、是否有记录丢失(如果是循环缓冲)以及错误提示。如果没有错误发生,数据就在原子性(每条记录不可被分隔开保存)、连续性(前后条的记录是连续的)和耐用性(能经受节点崩溃和重启)的保证下写入到flash,具体实现代码如下:
event void LogWrite.appendDone(void* buf, storage_len_t len,
bool recordsLost, error_t err) {
m_busy = FALSE;
call Leds.led2Off();
}
7.2.4 大数据块的存储
块存储(Block Storage)通常用于保存那些不能存于RAM的大数据对象。块是一个低级的系统接口,使用时需要小心,因为其本质是一次性写入的存储模型。重写就需要擦除,而擦除比较耗费时间,且必须以块为单位(如256B~64KB)擦除,以及只能擦除有限次(一般是10000~100000次)。TinyOS的重编程下载系统就是在节点上使用块存储来保存程序镜像的。
在tinyos-2.x/apps/tests/storage/Block/目录下,有一个块存储的例子程序供读者学习和参考。下面将简单介绍下相关的两个接口:BlockRead接口和BlockWrite接口。
1)BlockRead接口
interface BlockRead {
command error_t read(storage_addr_t addr, void* buf, storage_len_t len);
event void readDone(storage_addr_t addr, void* buf, storage_len_t len, error_t error);
command error_t computeCrc(storage_addr_t addr, storage_len_t len, uint16_t crc);
event void computeCrcDone(storage_addr_t addr, storage_len_t len, uint16_t crc, error_t error);
command storage_len_t getSize();
}
2)BlockWrite接口
interface BlockWrite {
command error_t write(storage_addr_t addr, void* buf, storage_len_t len);
event void writeDone(storage_addr_t addr, void* buf, storage_len_t len, error_t error);
command error_t erase();
event void eraseDone(error_t error);
command error_t sync();
event void syncDone(error_t error);
}