FatFsモジュールは移植性に関して次の点を前提としています。
各種環境でのモジュールのメモリ使用量の例を示します。数値の単位はバイトで、Dは論理ドライブ数、Fは同時オープン・ファイル数を示します。最適化オプションはコード・サイズとしています。
AVR | H8/300H | PIC | MSP430 | TLCS870C | V850ES | SH2 | |
---|---|---|---|---|---|---|---|
コンパイラ | WinAVR(gcc) | CH38 | C30(gcc) | CL430 | CC870C | CA850 | SHC |
_MCU_ENDIAN | 1 | 2 | 2 | 2 | 1 | 1 | 2 |
FatFs Code (Full, R/W) | 9280 | 9348 | 9387 | 6728 | 7538 | ||
FatFs Code (Minimum, R/W) | 5814 | 5798 | 5913 | 4094 | 4742 | ||
FatFs Code (Full, R/O) | 4402 | 4236 | 4371 | 3054 | 3474 | ||
FatFs Code (Minimum, R/O) | 3066 | 3158 | 3213 | 2172 | 2630 | ||
FatFs Work (Static) | D*2+2 | D*4+2 | D*2+2 | D*4+2 | D*4+2 | ||
FatFs Work (Dynamic) | D*554+F*544 | D*554+F*550 | D*554+F*544 | D*554+F*550 | D*554+F*550 | ||
Tiny-FatFs Code (Full, R/W) | 7628 | 7668 | 7560 | 7108 | 9501 | 5978 | 6640 |
Tiny-FatFs Code (Minimum, R/W) | 4684 | 4820 | 4698 | 4390 | 6322 | 3678 | 4236 |
Tiny-FatFs Code (Full, R/O) | 3634 | 3600 | 3618 | 3382 | 4554 | 2722 | 3072 |
Tiny-FatFs Code (Minimum, R/O) | 2524 | 2700 | 2601 | 2398 | 3390 | 1862 | 2300 |
Tiny-FatFs Wrok (Static) | 4 | 6 | 4 | 4 | 4 | 6 | 6 |
Tiny-FatFs Work (Dynamic) | 544+F*28 | 544+F*32 | 544+F*28 | 544+F*28 | 544+F*28 | 544+F*32 | 544+F*32 |
ポータブル・オーディオやデータ・ロガーなど、よくある用途ではTiny-FatFsで十分です。しかし、Tiny-FatFsは標準構成ではFAT32に対応していないので、使用できるディスクは2GBまでという制約があります。_FAT32オプションでFAT32対応を追加できますが、その分コード・サイズが膨らみます。FatFsは、複数ファイルを高速アクセスする場合や、複数ドライブの対応が必要な用途に適しています。
メモリ容量 | FATタイプ |
---|---|
64MB以下 | FAT12 |
128MB〜2GB | FAT16 |
4GB以上 | FAT32 |
2GBまでのカードに限るなら、FAT32への対応は不要です。右の表にメモリ・カードの容量と規定のFATタイプ(SDメモリの場合)を示します。メモリ・カードの出荷時は、最大のパフォーマンスが出るようにデータ領域の境界が調整されたフォーマットになっています。したがって、PCでフォーマットするなどして規定と違うフォーマットになると、書き込み性能が大幅に低下する場合があるので注意が必要です。
資源の限られた組み込みシステムで効率よくアクセスするためには、ファイル・アクセスの仕組みをある程度意識した使用が求められます。FatFsモジュールでは、ディスク上のファイル・データは f_read()内で次のような手順で読み出されます。
ここでファイルI/Oバッファとは、データ・セクタの一部を読み書きするための1セクタ長のバッファで、FatFsではそのファイル・オブジェクト内の、Tiny-FatFsではワークエリア内のバッファのことを指しています。
Tiny-FatFsでは、全てのデータ転送とFATやディレクトリへのアクセスをただ一つのセクタ・バッファで行っているため、データ転送によりFATのキャッシュが失われ、クラスタ境界を通過するたびにFATセクタを読み直す必要があります。FatFsの場合は、データ用バッファはFAT用とは別なので、FATセクタを読む頻度はTiny-FatFsの 1/341, 1/256 または 1/128で済みます(クラスタが連続している場合)。つまり、Tiny-FatFsは性能低下の代償を払ってRAM使用量を削減しているわけです。
転送領域のうちセクタ全体を含む部分は(図2)のようにファイルI/Oバッファを介さず、ディスクとの間で直接転送されます。完全なセクタ・アライメント・アクセスの場合(図3)は、ファイルI/Oバッファは全く使用されません。直接転送では、可能ならdisk_read()に複数セクタを指定して最大限のマルチ・セクタ転送が行われます。ただし、クラスタ境界をまたぐときはクラスタが隣接していたとしても転送は分割されます。
このように、極力セクタ・アライメント・アクセスになるように配慮すれば、無駄なメモリ・コピーが減って性能が向上します。さらに、Tiny-FatFsではFATのキャッシュが生きるようになり、省メモリ特性とFatFsの性能とが同時に得られます。
ディスク上のFAT構造を操作している途中で、停電、不正なメディアの取り外し、回復不能なデータ・エラー等の障害が発生すると、処理が中途半端な状態で中断され、その結果としてFAT構造が破壊される可能性があります。次にFatFsモジュールにおけるクリチカル・セクションと、その間の障害により起きうるエラーの状態を示します。
赤で示したセクションを実行中に障害が発生した場合、クロス・リンクが発生して操作対象のファイル・ディレクトリが失われる可能性があります。黄色で示したセクションを実行中に障害が発生した場合、つぎのうちいずれかまたは複数の結果が生じる可能性があります。
いずれも書き込み中や操作対象でないファイルには影響はありません。これらのクリチカル・セクションは、ファイルを書き込みモードで開いている時間を最小限にするか、f_sync()を適宜使用することで図5のようにリスクを最小化することができます。
そして、これらの機能拡張を行うとそれだけ多くのリソースが要求されるようになり、このプロジェクトの対象とする8/16ビット・マイコンのシステムに載せられなくなってしまうという問題もあります(これが一番の問題かも知れません)。