在失去连接时将数据存储到无线传感器网络中的闪存
Storing data to Flash in Wireless Sensor Networks on loosing connection
我必须实施一个最佳解决方案,将传感器的值存储到 NOR 闪存中,并在连接断开时带有时间戳,并在连接恢复时发送到中央服务器。需要一个类似队列的实现。任何人都可以建议一个实现开源或专有,或任何相同的算法。它应该具有磨损均衡、写入故障安全和擦除故障安全等特性。
是256Mb Spansion NOR flash(S25FL256S)。如果没有连接,我每 60 秒只需要存储少于 64 个字节(包括时间戳)。闪存的页面大小为 256 字节,扇区大小为 256KB。 flash的擦除循环次数为100,000次
一个简单的解决方案是使用 N 个闪存扇区,其中 N > 1。理想情况下,扇区大小相等,并且更小如果只需要少量数据存储,扇区会更有效率。扇区开始为空白(全部为 0xFF)。每条记录理想情况下是总扇区大小的一个因素(因此 64 或 128 字节可能是不错的选择。每条记录包括:
<timestamp><data><integrity check>
每条记录都按顺序连续写入闪存,但重要的是 <integrity check>
被写入 last。例如,<integrity check>
可以是 CRC 或只是 <timestamp>
的补码。我建议使用 time_t 类型的 Unix Epoch 时间戳,因为它简单且通用。最后写入 <integrity check>
允许检测不完整的记录(例如,由于写入期间电源故障)。
随着每个扇区边界被越过,下一个扇区被擦除,从扇区 N-1 到 0,所以你总是至少有 N-1 个扇区的数据,最多 N 个扇区。 (这就是为什么大量的小扇区比少量的大扇区更好)。这种闪存页面的循环缓冲区提供了磨损均衡。例如给定 2 * 256k 扇区和每分钟写入一次的 64 字节记录,每 2.844 天将擦除每页,因此对于 100000 erase/write 周期的耐久性,闪存将持续 779 年。这是矫枉过正,但这使用了恰好相当大的最小扇区数,您需要计算 N 和扇区大小的任何特定组合的耐力:
(((*N* - 1) * sector_size) / record_size) * write_period * flash_endurance
例如,每分钟写入 64 字节记录的 2 x 4Kb 扇区只能持续 12 年。
启动的初始化需要扫描闪存读取时间戳以找到不是 0xffffffff(或 64 位为 0xffffffffffffffff time_t)的最高编号时间戳,并且它通过了完整性检查,以便知道在哪里写下一条记录(紧接在这条 "most recent" 记录之后。请注意,如果你真的想 运行 779 年 - 甚至超过 2038 年 1 月 19 日,那么你 将 需要 64 位时间戳,但对于大多数用途,您可以使用 32 - 至少在产品保修期内!)。
2 * 256kb 的扇区实现保证至少有 256kb 的历史数据可用,对于 64 字节的记录,即 68 小时多一点。如果只使用 2 个 4kb 扇区,则最小历史记录减少到 64 分钟。您可以仅在连接丢失时记录,但最好连续记录,然后让远程客户端在需要时通过 start/end 时间戳请求丢失数据。这种方法将允许检索数据,即使它是 "lost" 由于系统检测到的连接丢失以外的原因,并且它可以允许连接多个客户端,这些客户端可能独立地断开连接并需要独立地恢复数据。
我必须实施一个最佳解决方案,将传感器的值存储到 NOR 闪存中,并在连接断开时带有时间戳,并在连接恢复时发送到中央服务器。需要一个类似队列的实现。任何人都可以建议一个实现开源或专有,或任何相同的算法。它应该具有磨损均衡、写入故障安全和擦除故障安全等特性。
是256Mb Spansion NOR flash(S25FL256S)。如果没有连接,我每 60 秒只需要存储少于 64 个字节(包括时间戳)。闪存的页面大小为 256 字节,扇区大小为 256KB。 flash的擦除循环次数为100,000次
一个简单的解决方案是使用 N 个闪存扇区,其中 N > 1。理想情况下,扇区大小相等,并且更小如果只需要少量数据存储,扇区会更有效率。扇区开始为空白(全部为 0xFF)。每条记录理想情况下是总扇区大小的一个因素(因此 64 或 128 字节可能是不错的选择。每条记录包括:
<timestamp><data><integrity check>
每条记录都按顺序连续写入闪存,但重要的是 <integrity check>
被写入 last。例如,<integrity check>
可以是 CRC 或只是 <timestamp>
的补码。我建议使用 time_t 类型的 Unix Epoch 时间戳,因为它简单且通用。最后写入 <integrity check>
允许检测不完整的记录(例如,由于写入期间电源故障)。
随着每个扇区边界被越过,下一个扇区被擦除,从扇区 N-1 到 0,所以你总是至少有 N-1 个扇区的数据,最多 N 个扇区。 (这就是为什么大量的小扇区比少量的大扇区更好)。这种闪存页面的循环缓冲区提供了磨损均衡。例如给定 2 * 256k 扇区和每分钟写入一次的 64 字节记录,每 2.844 天将擦除每页,因此对于 100000 erase/write 周期的耐久性,闪存将持续 779 年。这是矫枉过正,但这使用了恰好相当大的最小扇区数,您需要计算 N 和扇区大小的任何特定组合的耐力:
(((*N* - 1) * sector_size) / record_size) * write_period * flash_endurance
例如,每分钟写入 64 字节记录的 2 x 4Kb 扇区只能持续 12 年。
启动的初始化需要扫描闪存读取时间戳以找到不是 0xffffffff(或 64 位为 0xffffffffffffffff time_t)的最高编号时间戳,并且它通过了完整性检查,以便知道在哪里写下一条记录(紧接在这条 "most recent" 记录之后。请注意,如果你真的想 运行 779 年 - 甚至超过 2038 年 1 月 19 日,那么你 将 需要 64 位时间戳,但对于大多数用途,您可以使用 32 - 至少在产品保修期内!)。
2 * 256kb 的扇区实现保证至少有 256kb 的历史数据可用,对于 64 字节的记录,即 68 小时多一点。如果只使用 2 个 4kb 扇区,则最小历史记录减少到 64 分钟。您可以仅在连接丢失时记录,但最好连续记录,然后让远程客户端在需要时通过 start/end 时间戳请求丢失数据。这种方法将允许检索数据,即使它是 "lost" 由于系统检测到的连接丢失以外的原因,并且它可以允许连接多个客户端,这些客户端可能独立地断开连接并需要独立地恢复数据。