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 をトレースして、FatFの読み取り/書き込み要求を監視しました。f_open 読み取り要求はすべて正常で、ファイルと FAT テーブルを適切に検出します。

f_write は、最初のセクターをスクラッチ バッファーに読み込むことから始まります。次に、ゼロをスクラッチ バッファに memcpy します。すばらしいです。512 個のゼロの memcpy の後、セクターをコミットして次のセクターに移動する必要があります。

コードが混乱するのはこの時点です。そのゼロのスクラッチ バッファを 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 は正常に完了しましたが、L0 がフラッシュされなかったため、zeroedBuffer は変更されませんでした。そのため、FatFs では正しい値と古い値が混在していました。EDMA キャッシングを修正したところ、すべて動作するようになりました。

もう 1 つの学習として、TI Starterware には R0.4b が付属しています。私はそれから始めましたが、困惑していた FR_RW_ERROR が返されました。R0.11a に移行したところ、エラー フィードバックが大幅に改善されました。

FatFs の単体テストについて知っている人はいますか?

于 2015-11-29T13:30:25.070 に答える