FatFsモジュール アプリケーション・ノート


移植の際に配慮すべきこと

FatFsモジュールは移植性に関して次の点を前提としています。

メモリ使用量 (R0.06)

各種環境でのモジュールのメモリ使用量の例を示します。数値の単位はバイトで、Dは論理ドライブ数、Fは同時オープン・ファイル数を示します。最適化オプションはコード・サイズとしています。

AVRH8/300HPICMSP430TLCS870CV850ESSH2
コンパイラWinAVR(gcc)CH38C30(gcc)CL430CC870CCA850SHC
_MCU_ENDIAN1222112
FatFs Code
(Full, R/W)
92809348938767287538
FatFs Code
(Minimum, R/W)
58145798591340944742
FatFs Code
(Full, R/O)
44024236437130543474
FatFs Code
(Minimum, R/O)
30663158321321722630
FatFs Work (Static)D*2+2D*4+2D*2+2D*4+2D*4+2
FatFs Work (Dynamic)D*554+F*544D*554+F*550D*554+F*544D*554+F*550D*554+F*550
Tiny-FatFs Code
(Full, R/W)
7628766875607108950159786640
Tiny-FatFs Code
(Minimum, R/W)
4684482046984390632236784236
Tiny-FatFs Code
(Full, R/O)
3634360036183382455427223072
Tiny-FatFs Code
(Minimum, R/O)
2524270026012398339018622300
Tiny-FatFs Wrok (Static)4644466
Tiny-FatFs Work (Dynamic)544+F*28544+F*32544+F*28544+F*28544+F*28544+F*32544+F*32

FatFs vs. Tiny-FatFs

ポータブル・オーディオやデータ・ロガーなど、よくある用途ではTiny-FatFsで十分です。しかし、Tiny-FatFsは標準構成ではFAT32に対応していないので、使用できるディスクは2GBまでという制約があります。_FAT32オプションでFAT32対応を追加できますが、その分コード・サイズが膨らみます。FatFsは、複数ファイルを高速アクセスする場合や、複数ドライブの対応が必要な用途に適しています。

メモリ容量FATタイプ
64MB以下FAT12
128MB〜2GBFAT16
4GB以上FAT32

2GBまでのカードに限るなら、FAT32への対応は不要です。右の表にメモリ・カードの容量と規定のFATタイプ(SDメモリの場合)を示します。メモリ・カードの出荷時は、最大のパフォーマンスが出るようにデータ領域の境界が調整されたフォーマットになっています。したがって、PCでフォーマットするなどして規定と違うフォーマットになると、書き込み性能が大幅に低下する場合があるので注意が必要です。

効率の良いファイル・アクセスの方法

資源の限られた組み込みシステムで効率よくアクセスするためには、ファイル・アクセスの仕組みをある程度意識した使用が求められます。FatFsモジュールでは、ディスク上のファイル・データは f_read()内で次のような手順で読み出されます。

図1. セクタ・ミスアライメント・リード
fig.1

図2. セクタ・ミスアライメント・リード
fig.2

図3. セクタ・アライメント・リード
fig.3

ここでファイル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モジュールにおけるクリチカル・セクションと、その間の障害により起きうるエラーの状態を示します。

図4. 長いクリチカル・セクション
fig.4
図5. 最小化したクリチカル・セクション
fig.5

赤で示したセクションを実行中に障害が発生した場合、クロス・リンクが発生して操作対象のファイル・ディレクトリが失われる可能性があります。黄色で示したセクションを実行中に障害が発生した場合、つぎのうちいずれかまたは複数の結果が生じる可能性があります。

いずれも書き込み中や操作対象でないファイルには影響はありません。これらのクリチカル・セクションは、ファイルを書き込みモードで開いている時間を最小限にするか、f_sync()を適宜使用することで図5のようにリスクを最小化することができます。

現リビジョンの問題点とその改善案


そして、これらの機能拡張を行うとそれだけ多くのリソースが要求されるようになり、このプロジェクトの対象とする8/16ビット・マイコンのシステムに載せられなくなってしまうという問題もあります(これが一番の問題かも知れません)。

戻る