FatFS - 我可以创建多个搜索位置吗?

FatFS - can I create multiple seek locations?

我在基于 Cortex M4 的平台上的 C++ 应用程序 运行 中集成了 FatFS。

我的应用程序包括将数据记录到名为 MDF.

的数据格式

在实现方面,我在缓冲区中批量记录数据(到给定文件);缓冲区的数量取决于我获取数据的速度:log batch of one buffer。 . .做其他事情。 . .日志批次有五个缓冲区。 . .做其他事情。 . .等等

还有一个header,是24字节,包含数据的字节数。在 PC 上,我只会在测量结束时保存 header,但这是一个嵌入式产品,在任何时间点都可能是 de-powered。如果我不定期保存 header,文件会变成 "corrupted"。

因此,为了保持一致性,我需要在保存每批数据后 re-save header,这就是我的问题所在。

这意味着我必须在写入 header 之前调用 f_lseek,然后在写入批数据之前调用

am 使用 f_cache_fptr 所以 f_lseek 不是很慢但我想避免需要如此频繁地调用 f_lseek .

问题

是否有可能以某种方式有 2 个搜索位置,这样我就不需要在 header-location 和 data-location 之间调用 f_seek 到 ping-pong?

我愿意修改FatFS。

low-level 处的问题更简单,因为 header 仅与数据共享一个 512 字节 扇区:[= 的 24 字节58=]后跟488字节的数据。

Is it possible to somehow have 2 seek locations so that I don't need to call f_seek to ping-pong between header-location and data-location?

据我所知,没有,而且似乎没有任何意义。一个FIL只有一个当前位置,表示下一次写入它的数据会去哪里。有两个甚至意味着什么?系统怎么知道在哪里写?写到两个地方肯定是不正确的。

请特别注意,对于某些操作系统和文件系统,可以多次打开同一个文件,但 FatFS supports duplicate file opens only when all openings involved are for read-only mode.

我想可以修改 FatFS 使其能够在您搜索另一个文件位置时存储一个文件位置,然后再 return 到第一个。因此,这意味着至少要向 FIL 结构中添加一个成员,并至少添加一个新函数。

但为什么要处理 FatFS 的内部结构呢?这至少会有一点风险。只要你无论如何都要添加一个函数,在现有函数之上实现一个FRESULT my_f_write_at_beginning(FIL* fp, const void* buff, UINT btw, UINT* bw)怎么样?它可以存储当前位置,定位到文件开头,执行写入(可能确保写入指定的完整字节数),然后定位回原始位置。

但从根本上说,不,没有来回转义 ping-ponging,因为这样做是您提出的要求的一部分。

On a PC, I would just save the header at the end of the measurement but this is an embedded product which could be de-powered at any point in time. If I don't save the header periodically, the file becomes "corrupted".

Therefore, in order to maintain coherency I need to re-save the header after saving every batch of data and that's where my issue is.

更正确;您需要保存缓冲区和 header(页脚?),并更新目录条目以反映新的文件大小,并更新文件分配 table 以说明已分配的扇区;并且您需要“原子地”写入至少 3 个完全独立的扇区,以便在错误的时间出现电源故障时一切都是一致的。

这在大多数硬件上并不完全可行。

但是,有一种方法可以“比较安全”地做到这一点。具体来说:

  • pre-allocate 足够的簇用于文件的全新副本(包括要附加到末尾的新数据)并相应地更新文件分配 table。如果在执行此操作时(或在此之后立即发生)出现电源故障,则存在丢失集群的风险,这是一个“ignore-able”问题,会浪费一些 space 但可以使用典型的“轻松修复”检查磁盘”实用程序。

  • 在 pre-allocated 簇中创建文件数据的全新副本(复制旧数据,然后附加新数据和 header)。如果在执行此操作的过程中(或在此之后立即发生电源故障),则风险与以前相同 - 只是丢失了一些簇 (ignore-able)。

  • 自动更新目录条目;使用相同的原子(单个扇区)写入更改文件大小和“起始簇号”。如果在此之后出现电源故障,则风险是相同的丢失集群(旧版本文件数据所在的位置而不是新版本文件数据所在的位置)。

  • 释放旧版本文件使用的簇写入文件分配table。在这一点之后你已经成功完成,所以停电也没关系。

为了减少这种对性能的影响,您可以拥有两个“集群链”并在它们之间交替;这样一个簇链用于文件的当前版本,另一个将成为文件的下一个版本。这避免了将大量旧数据从一个地方复制到另一个地方的需要(如果您知道旧数据仍在以前使用的集群中)。它还可以避免在文件分配中分配和释放大多数簇的需要 table,但只会显着增加丢失簇的风险。

当然,要使其中任何一项工作,您需要保证 single-sector 写入是原子的;并且您不能使用 FAT12(文件分配中的条目 table 可以按扇区边界拆分)。