0

我的测试代码以 SD 卡上的一个大型现有文件 test.dat 开头,测试执行以下操作:

f_open(&fp, "test.dat", FA_OPEN_ALWAYS|FA_READ|FA_WRITE);
f_write(&fp, bufferOfZeros, 4096, &ioBytes);

似乎直截了当。

f_write 的结果是 SD 卡损坏。

我在我的嵌入式设备上跟踪了 EDMA 以观察FatFs读/写请求。f_open 读取请求都是健康的,它们正确地找到了文件和 FAT 表。

f_write 首先将第一个扇区读入暂存缓冲区,非常棒。然后它 memcpy 的零进入暂存缓冲区,太好了。在 memcpy 512 个零之后,它需要提交扇区并移动到下一个扇区。

正是在这一点上,代码被混淆了。它将零的暂存缓冲区写入 FAT 表!

ff.c/f_write() 中的违规代码是:

        if (fp->flag & FA__DIRTY) {     /* Write-back sector cache */
            if (disk_write(fp->fs->drv, fp->buf, fp->dsect, 1) != RES_OK)
                ABORT(fp->fs, FR_DISK_ERR);
            fp->flag &= ~FA__DIRTY;

这里,fp->buf 是零的扇区缓冲区,但 fp->dsect 是 FAT 扇区(8318),而不是文件数据扇区(10240)!哎呀。在 disk_write() fp->buf 匹配 fp->sect。

这里似乎是一个基本的用例,看到这个我很震惊。

我希望世界上有人以前用 FatFs 解决过这样的问题吗?

4

1 回答 1

1

Clifford 是正确的——这对我来说是个问题,我知道这样一个简单的用例必须有效。

我将测试切换到

f_open(&fp, "test.dat", FA_OPEN_ALWAYS|FA_READ|FA_WRITE);
f_write(&fp, pattern, 512, &ioBytes);
f_lseek(&fp, 0);
f_read(&fp, zeroedBuffer, 512, &ioBytes);

这揭示了一个缓存问题。f_read 操作成功,DMA 正常完成,但 zeroedBuffer 保持未修改,因为 L0 未刷新。因此,FatFs 看到了正确值和陈旧值的混合。我修复了 EDMA 缓存,现在一切正常。

另一项学习,TI Starterware 附带 R0.4b。我从那个开始,它返回了令人困惑的 FR_RW_ERROR。我升级到 R0.11a 并获得了更好的错误反馈。

有人知道 FatFs 的单元测试吗?

于 2015-11-29T13:30:25.070 回答