Hallo Miteinander! Ich bin derzeit mit dem FATFS von ELM-Chan beschäftigt - Es klappt soweit. Nun habe ich (wie vermutet) festgestellt, dass meine Programmierung betreffend Speicherbedarf und Laufzeit äußerst verschwenderisch ist (ich mach das als Hobby), es steht die Optimierung an. Was ich nicht ganz verstehe (Siehe Link): http://elm-chan.org/fsw/ff/doc/appnote.html#fs1 So wie sich mir das darstellt: Bild 1 zeigt die Auslesung von zwei Teilsektoren. Die Funktin "f_read" liest nur Teile des physikalischen Sektors. Irgendwann "ragt" sie in den nächsten Sektor, der dann ausgelesen und in den Buffer übertragen wird. Bild 2 zeigt die Auslesung von mehreren Sektoren, Anfang und Ende mitten im Sektor, dazwischen ganze Sektoren. Wie Bild 1, nur dass dazwischen "direct-transfer" stattfindet, was (siehe Bild 3) schneller gehen soll. Bild 3 zeigt das "fully sector alligned read". Das müsste doch betreffend Speicherverbrauch und Laufzeit der Idealfall sein. Warum wird davon abgeraten weil dann ein "direct transfer" entsteht? Was ist ein "unaligned read request"? Wie kann dieser "unaligned read request" bei "direct Transfer" auftreten? Bild 3 müsste doch das gelbe vom Ei sein? Die Funktion "disk_read" liest doch immer einen ganzen Sektor aus. Wie kann das "fully sector alligned read" nicht "Word aligned" sein? Es sind doch immer 512 Byte oder ein vielfaches davon? Was ist mit "Word aligned" gemeint? Ich verstehe es nicht.
>>Therefore taking effort to sector aligned read/write accesss eliminates buffered
data transfer and the read/write performance will be improved.
Da steht doch daß sector aligned anzustreben ist.
Word aligned heißt daß die Adresse ein Vielfaches des ,,word"-Datentyps
ist also anders ausgedrückt die untersten Bits 0 sind.
hansun schrieb: >>>Therefore taking effort to sector aligned read/write accesss eliminates buffered > data transfer and the read/write performance will be improved. Ja, soweit schon klar, aber der Satz "On the f_read() calls, avoid long read request that includes a whole of sector. - Any direct transfer never occures" besagt, dass ich den "direct transfrer" vermeiden soll, um unaligned read request zu vermeiden. Ich bin da echt ratlos.
Was ich nicht verstehe: "The unaligned read/write request can occure at direct Transfer" direct Transfer ist laut Beschreibung betreffend Speicherverbrauch und Rechenarbeit das Nonplusultra. wie kann da ein "unaligned Read" auftreten? Wie kann beim direct Transfer (der immer Sektorenweise erfogt und den ich selbst in der Funktion disk_read programmiere) ein "unaligned request" auftreten? Meine Funktion hat immer 512 Bytes zu lesen, was ein vielfaches von vier ist. ich kapiers echt nicht.
Guten Abend. Frage: benutzt Du den (original-)Code von ElmChan für Dein Projekt, oder nutzt Du den Code als Vorlage für eine Neuimplementierung? Gedankenspiel: Mir geht da der Begriff "off-by-one" durch den Kopf. Eventuell gibt es bei der H/C/S-Rechnerei einen "Rutscher". Was ist mit LBA? Schlußfolgerung: Irgendwie sind Deine Block-Einheiten kürzer/länger als 512 Bytes und verschieben sich (zyklisch). Hätte die Adressierung der Blöcke einen "Knacks", hättest Du nicht (zwischendrinn) korrektes Alignment. --- Ist nur als Anregung/Suchkriterium zu sehen, evtl. habe Dich auch mißverstanden ... Viel Erfolg Martin
Zmon schrieb: > "The unaligned read/write request can occure at direct Transfer" > > direct Transfer ist laut Beschreibung betreffend Speicherverbrauch und > Rechenarbeit das Nonplusultra. wie kann da ein "unaligned Read" > auftreten? Gaaanz einfach: Dein Zielpuffer ist eventuell nicht aligned. Da er hier 512 Bytes auf Einmal kopiert, könnte er auf die Idee kommen mit Word- anstatt Byte- Transfers zu arbeiten. Wenn man sicherstellt dass auch der Zielpuffer aligned ist dann sollten keine Probleme auftreten.
Übrigens stellt sich mir grade die Frage nach der Plattform, bei etlichen wären diese Fragen rein akademischer Natur.
Martin Beuttennüller schrieb: > Gedankenspiel: > Mir geht da der Begriff "off-by-one" durch den Kopf. > Eventuell gibt es bei der H/C/S-Rechnerei einen "Rutscher". > Was ist mit LBA? SD Karten benutzen grundsätlich LBA. Ein Beispiel für unaligned read wäre das Lesen von 1024 Bytes ab Offset 511 im File. Man überlege sich wie die Sektor Grenzen im Zielpuffer aussehen.
Guten Abend. @turboj: Eventuell ist meine Ausdrucksweise etwas ungeschickt gewesen, doch genau das war gemeint. Entweder ein Rechenfehler in der Adressierung (sei es auf der Karte oder des Speicherblocks) oder der Blocklänge selbst. Die meisten Blockgeräte (wenn nicht alle) arbeiten heute mit LBA. Ich ging davon aus, daß die Umrechnung von H/C/S nach LBA transparent und nur aus "historischen Gründen (TM)" erfolgt. Ich glaube mich zu erinnern, daß diese Umrechnung in der Vergangenheit öfter zu Verwirrungen/Problemen geführt hat und wollte sie als Fehlerquelle ausschließen. Ich lerne gerne dazu, danke Martin
Wenn man ganze Sektoren mit der f_read Funktion liest, dann wird der FATFS-Interne Buffer umgangen, und der Buffer, den man an die Funktion übergibt, direkt benutzt. Z.B. beim Beispielcode für den STM32, den man im Netz so findet, wird das notwendige Alignment an einer 4-Byte-Grenze (und ein paar weitere Alignment-Notwendigkeiten des Buffers für DMA) ignoriert. Wenn man dann der f_read-Funktion einen Buffer übergibt, der nicht ordentlich ausgerichtet ist (z.B. ein uint8_t buffer[512]), geht das schief.
Beim Lesen von eines Sektors über Sektorgrenzen hinweg hatte ich damals gelegentlich Probleme. SDKarte oder FatFS hing sich gelegentlich auf - so ganz konnte ich es nicht nachvollziehen, aber irgendwas lief da schief. Problem lies sich lösen, wenn man erst den angefangenen Sektor fertig liest und dann immer sektorweise weiter. So in etwa wie hier (hat meine Probleme gelöst):
1 | if (fpos % 512) { // partial sector |
2 | res = f_read(&MyFile, scratch, 512 - (fpos % 512), &bytesread); |
3 | } else { |
4 | res = f_read(&MyFile, scratch, min(filesize, 8192), &bytesread); |
5 | }
|
Also mein Rat wäre definitiv, wirklich nur ganze Sektoren auszulesen und nicht über Sektorgrenzen hinweg :)
:
Bearbeitet durch User
Guten Morgen zusammen! Danke für eure Beiträge, ich denke wir kommen der Sache auf die Spur! Tassilo H. schrieb: > Wenn man ganze Sektoren mit der f_read Funktion liest, dann wird der > FATFS-Interne Buffer umgangen, und der Buffer, den man an die Funktion > übergibt, direkt benutzt. Das ist mir soweit klar, ist ja in der Grafik ersichtlich. Ich glaube erkannt zu haben, dass mein Verständnisproblem in diesem Absatz zu finden ist: > Z.B. beim Beispielcode für den STM32, den man im Netz so findet, wird > das notwendige Alignment an einer 4-Byte-Grenze (und ein paar weitere > Alignment-Notwendigkeiten des Buffers für DMA) ignoriert. Wenn man dann > der f_read-Funktion einen Buffer übergibt, der nicht ordentlich > ausgerichtet ist (z.B. ein uint8_t buffer[512]), geht das schief. Wenn ich mit der f_read Funktion 512 Bytes auslesen lassen will, wird der an die f_read Funktion übergebene 512 Bytes breite Buffer direkt an die von mir programmierte disk_read Funktion übergeben. Diese schreibt den ausgelesenen Sektor 1:1 in diesen Buffer. Wo kann hier ein misalignment stattfinden? Mein Projekt funktioniert, die Musik läuft. Derzeit lese ich die Sektoren immer zu Blöcken von 32 Bytes aus, die mein VS1011 gerade aufnehmen kann. Wenn ich das 16x gemacht habe, ist der aktuelle Sektor fertig gelesen, und es wird der nächste ausgelesen; ich arbeite also nach dem ersten Bild in der Grafik, und vermeide somit zwangsweise direct read. Ich möchte die Lesezugriffe aber optimieren, damit der Controller auch noch Zeit hat während des Abspielens von Musik z.B. die Lautstärke einzustellen. @Martin: Ich glaube du hast mich tatsächlich missverstanden, das kann aber durchaus an meiner Beschreibung liegen, ich neige dazu gelegentlich zu viel Text zu verwenden. @Mampf: Chan rät allerdings davon ab ganze Sektoren auszulesen, um direct read und somit mögliches misalignment zu vermeiden.
Simon B. schrieb: > @Mampf: Chan rät allerdings davon ab ganze Sektoren auszulesen, um > direct read und somit mögliches misalignment zu vermeiden. Mmhmm, ist mir ein Rätsel, was du damit meinst ... Hier gibt es zu partial-Sector-Read bisserl was: http://elm-chan.org/fsw/ff/doc/appnote.html Kleines Teil des Webseite: > Figure 3 shows that the case of entier transfer data is aligned to the > sector boundary. In this case, file I/O buffer is not used. On the > direct transfer, the maximum extent of sectors are read with disk_read > function at a time but the multiple sector transfer is divided at > cluster boundary even if it is contiguous. > Therefore taking effort to sector aligned read/write accesss eliminates > buffered data transfer and the read/write performance will be improved. Für mich hört sich "will be improved" nach einen Vorteil und nicht nach einen Nachteil an. So vom common-sense her, macht es aber Sinn ganze Sektoren zu lesen. Nichts kann effizienter sein, als Sektor für Sektor komplett und ohne Rest zu lesen - quasi das, was die SD-Karte am besten kann.
:
Bearbeitet durch User
Mampf F. schrieb: > Mmhmm, ist mir ein Rätsel, was du damit meinst ... Das hier: •On the f_read() calls, avoid long read request that includes a whole of sector. - Any direct transfer never occures. zu finden in der Beschreibung der disk_read Funktion: http://elm-chan.org/fsw/ff/doc/dread.html Es ist ein Tipp, wie man direct transfer vermeiden kann. Mampf F. schrieb: > Für mich hört sich "will be improved" nach einen Vorteil und nicht nach > einen Nachteil an. Das lese ich auch so, weshalb es mich wundert warum er auch empfiehlt das zu vermeiden wegen misalignmet. Mehr alignment als mit direct Transfer ist doch kaum möglich?
M.E. bezieht sich die entsprechende Stelle in der Dokumentation im wesentlichen auf Hardware (DMA, z.B. oder ein 16-bit IDE Interface), die nicht auf/von ungerade(n) Adressen schreiben/lesen kann. Man könnte ja durchaus auf die Idee kommen, auch mit solcher Hardware auf ungerade Adressen zu schreiben oder könnte von einer ungeraden Startposition aus (die man z.B. mit f_lseek() erreicht hat) grössere Transfers machen wollen. Dann geht's ohne Zwischenpufferung nicht.
:
Bearbeitet durch User
Simon B. schrieb: > Das hier: > > •On the f_read() calls, avoid long read request that includes a whole of > sector. - Any direct transfer never occures. Ja, dann les die Sektoren in zB 4k-Blöcken. "a whole of" heißt auf deutsch "eine ganze Menge". Vlt war das ein Verständnisproblem? :) Ich hatte bei mir versucht, eine Blockgröße zu verwenden, die durch 512Byte teilbar ist - und perfekt in einen Cluster passt (bei FAT32 default 32kB). Hat gut geklappt und das ist am "schonensten" :)
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.