AVR FAT32 microSD lesen beschleunigen

OP #2198999
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 ??
Gast #2199163
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.
Gast #2199804
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?
OP #2199818
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
Gast #2199833
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.
Gast #2199854
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.
Gast #2199873
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.
OP #2206627
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
Gast #2206639
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.
OP #2217780
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
Gast #2217806
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren