Forum: Mikrocontroller und Digitale Elektronik AVR FAT32 microSD lesen beschleunigen


von Matthias L. (mcl024)


Lesenswert?

Hallo zusammen,

ich nutze die FAT32 Lib von diesem Artikel AVR FAT32 . Unter dem 
Punkt lesen steht das bei einer unfragmentierten FAT alles Cluster 
aneinander liegen und somit der lese Zugriff extrem beschleunigt werden 
kann.

Mein Frage ist nun wie erstelle ich eine unfragmentierte FAT. Ist das 
nicht ein Widerspruch FAT -> unfragmentiert ??

von micha (Gast)


Lesenswert?

Medium frisch formatieren und große Datei anlegen dann sind alle 
Sektoren schön sequentiell. Dann geht das lesen quasi "automatisch" da 
die Sektoren-Nr (IMHO bei SD-Cards) automatisch weitergesetzt wird. 
Fragmentiert sind eventuell Sektoren 1-10-2-100-99-20 etc auszuwählen, 
d.h. man muss jeden Sektor anwählen, anspringen etc.

von Matthias L. (mcl024)


Lesenswert?

Meine Datei ist aber nur 45KByte klein. Werden dann auch alle sektoren 
nacheinander angelegt?

von Matthias L. (mcl024)


Lesenswert?

Also wenn ich die microSD Karte formatiere und anschließend nur meine 
ca. 45KByte kleine Datei auf die Karte kopiere, hängen leider nicht alle 
Sektoren in einer Reihe.

Was kann ich tun?

von holger (Gast)


Lesenswert?

>Also wenn ich die microSD Karte formatiere und anschließend nur meine
>ca. 45KByte kleine Datei auf die Karte kopiere, hängen leider nicht alle
>Sektoren in einer Reihe.

Doch, tun sie. Wie hast du das festgestellt?

von Matthias L. (mcl024)


Lesenswert?

Also es gibt folgende funktion in der FAT-Lib:
1
//-----------------------------------------------------------------------------
2
// fat_getFatChainClustersInRow
3
//-----------------------------------------------------------------------------
4
//
5
// Return Value : None
6
// Parameters   : unsigned long int offsetCluster
7
//
8
//
9
// sucht verkettete cluster einer datei, die in einer reihe liegen. worst case: nur ein cluster.
10
// sieht in der fat ab dem cluster offsetCluster nach. sucht die anzahl von MAX_CLUSTERS_IN_ROW,
11
// am stueck,falls möglich. prueft ob der cluster neben offsetCluster dazu gehört...
12
// setzt dann fat.endSectors und fat.startSectors. das -1 weil z.b. [95,98] = {95,96,97,98} = 4 sektoren
13
//-----------------------------------------------------------------------------
14
void fat_getFatChainClustersInRow( unsigned long int offsetCluster)
15
{
16
  unsigned short cnt = 0;
17
18
  fat.startSectors = fat_clustToSec(offsetCluster);    // setzen des 1. sektors der datei
19
  fat.cntSecs = fat.secPerClust;
20
21
  while( cnt<MMC_MAX_CLUSTERS_IN_ROW ){
22
    if( (offsetCluster+cnt+1)==fat_getNextCluster(offsetCluster+cnt) )    // zählen der zusammenhängenden sektoren
23
      fat.cntSecs += fat.secPerClust;
24
    else {
25
      PORTA ^= (1<<PA7);         // Trigger PA7 toggle
26
      file.lastCluster = offsetCluster+cnt;      // hier landet man, wenn es nicht MAX_CLUSTERS_IN_ROW am stueck gibt, also vorher ein nicht passender cluster gefunden wurde.
27
      return;
28
    }
29
    cnt+=1;
30
  }
31
32
  file.lastCluster = offsetCluster+cnt;          // hier landet man, wenn MAX_CLUSTERS_IN_ROW gefunden wurden
33
}

Da habe ich in den else zweig einen Trigger gesetzt und mit dem Oszi 
gemessen.

MAX_CLUSTERS_IN_ROW steht auf 256

von holger (Gast)


Lesenswert?

>Da habe ich in den else zweig einen Trigger gesetzt und mit dem Oszi
>gemessen.

Ja, klar mit dem Osci gemessen;)
Lass dir besser mal die Sektornummern beim lesen
ausgeben. Das ist viel aussagekräftiger.

von Matthias L. (mcl024)


Lesenswert?

Entweder er springt in den Else-Zweig oder nicht und wenn ich dann mein 
I/O-Pin toggle dann sagt das doch alles!?

von holger (Gast)


Lesenswert?

>Entweder er springt in den Else-Zweig oder nicht und wenn ich dann mein
>I/O-Pin toggle dann sagt das doch alles!?

Und wenn deine Datei keine 256 Cluster belegt landet er auch dort.

von ich (Gast)


Lesenswert?

Oh sorry da habe ich wohl etwas Mißverstanden. Mhh das bedeutet also das 
mein Datei bereits in einem Stück auf der Karte liegt. Mißt ich dachte 
ich könnte damit das lesen beschleunigen.

von holger (Gast)


Lesenswert?

>Mißt ich dachte
>ich könnte damit das lesen beschleunigen.

Wie schnell ist es denn jetzt?
Wie schnell soll es werden?
Und wie liest du die Datei?

Ich denke mal beim letzten Punkt könnte dein Problem liegen.

von Markus (Gast)


Lesenswert?

Es könnte sein, dass auf der untersten Ebene, da wo die Bytes gelesen 
und geschrieben werden, noch etwas zu holen ist. Schau dir den 
Assemblercode  (oder poste ihn hier) der Schleife an, in der das SPDR 
gelesen bzw. beschrieben wird.

von Matthias L. (mcl024)


Lesenswert?

Hallo,

erstaml danke für eure Antworten.

Ich benötige ca. 5ms pro 1KByte. Geht das schneller? Ich hoffe!!

Hier die sd_read_byte funktion in C und Assembler
1
unsigned char sd_read_byte(void)
2
{
3
  SPDR = 0xff;
4
  while( ! (SPSR & (1<<SPIF)));  // warten bis SPIF=1 (Uebrtragung beendet)
5
  return (SPDR);
6
}
1
00004488 <sd_read_byte>:
2
    4488:  8f ef         ldi  r24, 0xFF  ; 255
3
    448a:  8f b9         out  0x0f, r24  ; 15
4
    448c:  77 9b         sbis  0x0e, 7  ; 14
5
    448e:  fe cf         rjmp  .-4        ; 0x448c <sd_read_byte+0x4>
6
    4490:  8f b1         in  r24, 0x0f  ; 15
7
    4492:  08 95         ret

Ich nutze den Code aus dem Artikel FAT FAT32

von holger (Gast)


Lesenswert?

>Ich benötige ca. 5ms pro 1KByte. Geht das schneller? Ich hoffe!!
>Hier die sd_read_byte funktion in C und Assembler

Versuchs mit inline.

inline unsigned char sd_read_byte(void)
{
  SPDR = 0xff;
  while( ! (SPSR & (1<<SPIF)));  // warten bis SPIF=1 (Uebrtragung 
beendet)
  return (SPDR);
}

Viel mehr ist da nicht zu holen.
Evtl. noch die Eigenschaften des SPI Moduls
ausnutzen und während der Übertragung schon
andere Sachen machen wie Werte abspeichern.
Mehr als 10% holst du da aber nicht mehr raus.

von Matthias L. (mcl024)


Lesenswert?

Hallo Zusammen,

ich bin immer noch nicht weiter gekommen mit meinem Problem.

Habe jetzt heraus gefunden das, dass lesen einer Datei mit 46464 Byte 
belegt 96 Sectoren (a 512 Byte) gerade mal 2,5ms dauert. Warum genau 96 
Sectoren weiss ich nicht genau spielt auch keine entscheidene Rolle.

Das was ich nicht verstehe ist warum nur 2,5ms?

Meine SPI läuft mit 8Mhz => 0,125µs für 1Byte benötige ich also 
8x0,125µs=1µs daraus folgt das ich für 46464 Byte mindestens ca. 46ms 
benötige, brauche aber nur 2,5ms. Wo ist mein Denkfehler?

Die 2,5ms habe durch messen am Oszi ermittelt an folgenden Stellen im 
Code
1
         PORTA |= (1<<PA7);         // Trigger PA7 High
2
        // lesen eines chars und Ausgabe des chars.
3
        // solange bis komplette Datei gelesen wurde.
4
        do{
5
          // start data transmission
6
          byte = ffread();
7
          seek--;
8
9
        }while(seek);
10
11
        PORTA &= ~(1<<PA7);         // Trigger PA7 Low
ffread() liefert mir 8Byte der Datei.

Ja die Datei ist tatsächlich 46464 Byte groß, denn wenn ich mir den Wert 
von seek anschaue ist dieser auch 46464.

Danke für eure Unterstützung

von holger (Gast)


Lesenswert?

>Meine SPI läuft mit 8Mhz => 0,125µs für 1Byte benötige ich also
>8x0,125µs=1µs daraus folgt das ich für 46464 Byte mindestens ca. 46ms
>benötige, brauche aber nur 2,5ms. Wo ist mein Denkfehler?

Du hast keinen Denkfehler. Deine Software bricht beim Lesen
vermutlich frühzeitig ab und liest die Sektoren gar nicht.

von Matthias L. (mcl024)


Lesenswert?

Die Daten werden vollständig gelesen. Ich nutze sie um ein Bild auf 
einem Display anzuzeigen und dieses wird vollständig dargestellt.

von holger (Gast)


Lesenswert?

>Die Daten werden vollständig gelesen. Ich nutze sie um ein Bild auf
>einem Display anzuzeigen und dieses wird vollständig dargestellt.

Dann hast du falsch gemessen.

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.