Forum: Mikrocontroller und Digitale Elektronik ELM Chan unaligned read


von Simon B. (zmon)


Lesenswert?

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.

von hansun (Gast)


Lesenswert?

>>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.

von Zmon (Gast)


Lesenswert?

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.

von Zmon (Gast)


Lesenswert?

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.

von Martin Beuttennüller (Gast)


Lesenswert?

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

von Jim M. (turboj)


Lesenswert?

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.

von Jim M. (turboj)


Lesenswert?

Übrigens stellt sich mir grade die Frage nach der Plattform, bei 
etlichen wären diese Fragen rein akademischer Natur.

von Jim M. (turboj)


Lesenswert?

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.

von Martin Beuttenmüller (Gast)


Lesenswert?

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

von Tassilo H. (tassilo_h)


Lesenswert?

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.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

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
von Simon B. (zmon)


Lesenswert?

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.

von Mampf F. (mampf) Benutzerseite


Lesenswert?

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
von Simon B. (zmon)


Lesenswert?

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?

von Markus F. (mfro)


Lesenswert?

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
von Mampf F. (mampf) Benutzerseite


Lesenswert?

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
Noch kein Account? Hier anmelden.