Wie viel RAM braucht man mindestens um CF/SD/MMC mit FAT zu lesen/schreiben ?
=============================================================================
hk@holger-klabunde.de
http://www.holger-klabunde.de

20.10.2006

CF steht ab hier fr CompactFlash und SD/MMC Cards.

FAT lesen
=========
Beim lesen kann man auch mit sehr wenig RAM klar kommen.

Mein Mini-FAT braucht ca. 100 Byte RAM. Das funktioniert
immer dann wenn man gelesene Bytes gleich verarbeitet
und nicht irgendwo zwischenpuffern mu. Wie lange diese
Verarbeitung braucht ist egal. Es gibt scheinbar keine
maximale Beschrnkung bei den Lesezeiten von Byte zu Byte
wenn ein Sektor vom CF gelesen wird. Einen Verzeichniseintrag
zu lesen bentigt nur 32 Bytes. Eine Clusternummer aus der
FAT zu lesen braucht bei FAT32 nur vier Bytes.  

FAT schreiben
=============
Hier sieht es jetzt vllig anders aus ! Wenn der CF beschrieben
werden soll mu immer ein kompletter Sektor geschrieben werden.
Es ist mglicherweise auch hier egal wie lange es von Byte zu Byte
dauert bis der komplette Sektor beschrieben wurde. Fr einen
Datensektor gibt es bis hier noch keine Probleme wenn die Daten
Byte fr Byte sofort zum CF gesendet werden.

Die Probleme fangen an wenn man die FAT aktualisieren mu. Man mu
immer einen kompletten Sektor ins RAM lesen um den Verzeichniseintrag
oder die FAT zu aktualisieren und dann auf den CF zurckschreiben.
Das geht nicht anders. Ein Sektor ist 512 Bytes gro. Man braucht auch
noch einiges fr die Verwaltung der Daten. Sagen wir mal 50 Bytes. FAT
zu schreiben braucht also mindestens 562 Bytes. Eher mehr.

Was bringt ein FAT Buffer ?
===========================
Bei einem reinen Lesesystem kann man auf einen FAT Buffer meistens
verzichten. Da bringt er nicht mehr als 5-10 %.

Es kann aber nicht oft genug gesagt werden das man beim FAT schreiben
einen FAT Buffer verwenden sollte. Der bentigt aber weitere 512Byte RAM.
Je nach dem wie das Medium formatiert wurde bringt ein FAT Buffer unheimliche
Geschwindigkeiten beim schreiben.

Ein paar Beispiele fr den Idealfall unfragmentierte FAT:

Extrembeispiel ohne FAT Buffer:
32MB MMC Card, FAT16,  secPerCluster=1

Nur ein Sektor pro Cluster ! Was bedeutet das ohne FAT Buffer ?
Jedesmal wenn ein Datensektor geschrieben wurde mu die FAT
aktualisiert werden. Ohne FAT Buffer mu der FAT Sektor erst einmal
gelesen werden, dann macht man einen neuen Eintrag und schreibt den
FAT Sektor wieder auf das Medium. Das RAM wird ja fr den nchsten
Datensektor bentigt.  Die Schreibgeschwindigkeit halbiert sich also
auf jeden Fall schon mal. Dazu kommt noch das lesen des FAT Sektors.
Eigentlich macht man aber zwei Eintrge ! Der letzte Clustereintrag
wird mit der neuen Clusternummer beschrieben und der neue Clustereintrag
bekommt den Wert END_OF_CLUSTER_CHAIN. Das vernachlssige ich hier einfach mal.
Es ist also noch schlimmer als unten beschrieben.

Neues Beispiel ohne FAT Buffer:
32MB MMC Card, FAT16,  secPerCluster=2
Alle zwei Sektoren mu die FAT aktualisiert werden. Das schreiben
in die FAT verbraucht ein drittel der Schreibgeschwindigkeit.

Neues Beispiel ohne FAT Buffer:
32MB MMC Card, FAT16,  secPerCluster=4
Alle vier Sektoren mu die FAT aktualisiert werden. Das schreiben
in die FAT verbraucht ein fnftel der Schreibgeschwindigkeit.

Und so weiter.

Extrembeispiel MIT FAT Buffer:
32MB MMC Card, FAT16,  secPerCluster=1

Nur ein Sektor pro Cluster ! Jedesmal wenn ein Datensektor geschrieben
wurde wird ein Eintrag in den FAT Buffer gemacht. Der FAT Buffer mu
nach 512/2 (2 Byte Eintrge bei FAT16) Datensektoren geschrieben, und ein
neuer FAT Sektor in den FAT Buffer gelesen werden. Also nur alle 256
Datensektoren ! Die Schreibgeschwindigkeit wird durch den FAT Buffer fast
verdoppelt.

Man muss jetzt aber dazu sagen das es normalerweise bei greren CF
nicht vorkommt das nur ein Sektor pro Cluster benutzt wird. Bei z.B.
16MB-256MB Medien sind es eher 4 bis 32 Sektoren pro Cluster.

Ich habe allerdings eine 128MB SD Karte von takeMS die mir echt
Kopfzerbrechen bereitet hat. Geschichte:
                             ===========
                             
Schreiben ohne FAT Buffer, FAT16, 4 Sektoren pro Cluster.
Erst dachte ich das Programm hat sich aufgehngt, aber erstmal
laufen lassen. Ergebnis: Selbst wenn Fwrite() mit einem 64 Byte
Puffer gefttert wird kommt die Karte nur auf 8kB/s !

Karte umformatiert auf FAT16 und 32 Sektoren pro Cluster.
Die Karte kommt jetzt maximal auf 50kB/s. Mit FAT Buffer gehrt
die Karte mit ca. 300kB/s zu meinen schnellsten Karten !

Vermutung: Wenn Sektoren zu hufig nacheinander beschrieben
werden sinkt die Schreibgeschwindigkeit bei einigen Karten mehr als
man erwartet.

Eine Nokia 64MB MiniSD kam auch mit FAT Buffer gerade mal auf 30kB/s.
Die war aber auch beim schreiben mit USB2.0 Kartenleser nicht die schnellste.
Beim lesen ist die ziemlich fix. Mehr als 300kB/s.

Ein paar Messwerte:
===================

MMC 32MB extrememory
====================

ATMega FAT DOS-Read-Write-Test3 by Holgi  ATMega FAT DOS-Read-Write-Test3 by Holgi
FAT16                                     FAT16
bootSecOffset 0                           bootSecOffset 0
Reserved Sectors 4                        Reserved Sectors 4
FAT Sectors 62                            FAT Sectors 62
Num. of FAT's 2                           Num. of FAT's 2
secPerCluster 4                           secPerCluster 4
BytesPerCluster 2048                      BytesPerCluster 2048
FATFirstSector 4                          FATFirstSector 4
FirstRootSector 128                       FirstRootSector 128
RootDirSectors 32                         RootDirSectors 32
FirstDataSector 160                       FirstDataSector 160
maxsect 62720                             maxsect 62720
FirstDirCluster 0                         FirstDirCluster 0
maxcluster 15642                          maxcluster 15642
                                          
No FAT Buffer                             Using FAT Buffer
MMC/SD Card                               MMC/SD Card
FAST_SPI_WRITE                            FAST_SPI_WRITE
FAST_SPI_READ                             FAST_SPI_READ
FAST_FWRITE                               FAST_FWRITE
FAST_FREAD                                FAST_FREAD
F_CPU 16000000                            F_CPU 16000000
                                          
Start writing 7 files                     Start writing 7 files
FAT WR Hits 1003 FAT RD Hits 1006         FAT WR Hits 7 FAT RD Hits 9
01 45.1s 44.3kB/s                         01 41.0s 48.7kB/s
FAT WR Hits 1004 FAT RD Hits 1011         FAT WR Hits 9 FAT RD Hits 16
02 31.2s 64.1kB/s                         02 27.4s 72.9kB/s
FAT WR Hits 1004 FAT RD Hits 1015         FAT WR Hits 9 FAT RD Hits 20
04 24.3s 82.3kB/s                         04 20.1s 99.5kB/s
FAT WR Hits 1004 FAT RD Hits 1019         FAT WR Hits 9 FAT RD Hits 24
08 20.7s 96.6kB/s                         08 16.7s 119.7kB/s
FAT WR Hits 1004 FAT RD Hits 1023         FAT WR Hits 9 FAT RD Hits 28
16 19.0s 105.2kB/s                        16 14.9s 134.2kB/s
FAT WR Hits 1004 FAT RD Hits 1027         FAT WR Hits 9 FAT RD Hits 32
32 18.1s 110.4kB/s                        32 14.0s 142.8kB/s
FAT WR Hits 1004 FAT RD Hits 1031         FAT WR Hits 9 FAT RD Hits 36
64 17.5s 114.2kB/s                        64 13.6s 147.0kB/s
                                          
Start reading 7 files                     Start reading 7 files
FAT RD Hits 999                           FAT RD Hits 4
01 41.1s 48.6kB/s                         01 39.8s 50.2kB/s
FAT RD Hits 999                           FAT RD Hits 4
02 24.4s 81.9kB/s                         02 23.2s 86.2kB/s
FAT RD Hits 999                           FAT RD Hits 4
04 15.9s 125.7kB/s                        04 14.7s 136.0kB/s
FAT RD Hits 999                           FAT RD Hits 4
08 11.7s 170.9kB/s                        08 10.4s 192.3kB/s
FAT RD Hits 999                           FAT RD Hits 4
16 9.5s 210.5kB/s                         16 8.4s 238.0kB/s
FAT RD Hits 999                           FAT RD Hits 4
32 8.6s 232.5kB/s                         32 7.3s 273.9kB/s
FAT RD Hits 999                           FAT RD Hits 4
64 8.0s 250.0kB/s                         64 6.7s 298.5kB/s
Test done.                                Test done.

Hier die SD 128MB takeMS
========================
Mit den bereits verbesserten FAT Routinen beim schreiben ohne FAT Buffer.
Die FAT Zugriffe konnten halbiert werden.

ATMega FAT DOS-Read-Write-Test3 by Holgi  ATMega FAT DOS-Read-Write-Test3 by Holgi
FAT16                                     FAT16
bootSecOffset 0                           bootSecOffset 0
Reserved Sectors 4                        Reserved Sectors 4
FAT Sectors 30                            FAT Sectors 30
Num. of FAT's 2                           Num. of FAT's 2
secPerCluster 32                          secPerCluster 32
BytesPerCluster 16384                     BytesPerCluster 16384
FATFirstSector 4                          FATFirstSector 4
FirstRootSector 64                        FirstRootSector 64
RootDirSectors 32                         RootDirSectors 32
FirstDataSector 96                        FirstDataSector 96
maxsect 244480                            maxsect 244480
FirstDirCluster 0                         FirstDirCluster 0
maxcluster 7639                           maxcluster 7639
                                          
No FAT Buffer                             Using FAT Buffer
MMC/SD Card                               MMC/SD Card
FAST_SPI_WRITE                            FAST_SPI_WRITE
FAST_SPI_READ                             FAST_SPI_READ
FAST_FWRITE                               FAST_FWRITE
FAST_FREAD                                FAST_FREAD
F_CPU 16000000                            F_CPU 16000000
                                          
Start writing 7 files                     Start writing 7 files
FAT WR Hits 125 FAT RD Hits 125           FAT WR Hits 1 FAT RD Hits 0
01 50.7s 39.4kB/s                         01 33.7s 59.3kB/s
FAT WR Hits 125 FAT RD Hits 125           FAT WR Hits 1 FAT RD Hits 0
02 36.8s 54.3kB/s                         02 20.0s 100.0kB/s
FAT WR Hits 126 FAT RD Hits 127           FAT WR Hits 3 FAT RD Hits 3
04 29.7s 67.3kB/s                         04 12.9s 155.0kB/s
FAT WR Hits 125 FAT RD Hits 126           FAT WR Hits 1 FAT RD Hits 2
08 26.1s 76.6kB/s                         08 9.3s 215.0kB/s
FAT WR Hits 126 FAT RD Hits 128           FAT WR Hits 3 FAT RD Hits 5
16 24.3s 82.3kB/s                         16 7.5s 266.6kB/s
FAT WR Hits 125 FAT RD Hits 127           FAT WR Hits 1 FAT RD Hits 3
32 23.8s 84.0kB/s                         32 6.7s 298.5kB/s
FAT WR Hits 126 FAT RD Hits 129           FAT WR Hits 3 FAT RD Hits 6
64 23.0s 86.9kB/s                         64 6.1s 327.8kB/s
                                          
Start reading 7 files                     Start reading 7 files
FAT RD Hits 124                           FAT RD Hits 1
01 39.0s 51.2kB/s                         01 38.9s 51.4kB/s
FAT RD Hits 124                           FAT RD Hits 0
02 22.4s 89.2kB/s                         02 22.3s 89.6kB/s
FAT RD Hits 124                           FAT RD Hits 1
04 13.9s 143.8kB/s                        04 13.8s 144.9kB/s
FAT RD Hits 124                           FAT RD Hits 0
08 9.6s 208.3kB/s                         08 9.5s 210.5kB/s
FAT RD Hits 124                           FAT RD Hits 1
16 7.6s 263.1kB/s                         16 7.4s 270.2kB/s
FAT RD Hits 124                           FAT RD Hits 0
32 6.5s 307.6kB/s                         32 6.4s 312.5kB/s
FAT RD Hits 124                           FAT RD Hits 1
64 5.9s 338.9kB/s                         64 5.8s 344.8kB/s
Test done.                                Test done.


Andere Wege
===========
Es gibt Lsungen wo das schreiben der FAT und des Verzeichniseintrages
vermieden werden knnen. Einfach eine Datei erzeugen die den gesamten
CF belegt und dann nur noch die Datensektoren beschreiben. Problem:
Der CF darf nicht fragmentiert sein. Also frisch formatiert bevor die
Datei erzeugt wurde. Das kann man evtl. auch auf mehrere Dateien ausweiten.
Die Clusternummern der Datei liegen dann alle in aufsteigender Reihenfolge
in der FAT. Damit liegen auch die Sektoren einer Datei in einer aufsteigenden
Reihe. Ausgehend von dieser Annahme mu die FAT NICHT mehr gelesen oder
geschrieben werden !

Es ist aber eine Krcke mit erheblichem Fehlerpotential. Das hat mit einem
frei beschreibbaren FAT System nicht mehr viel zu tun.




