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 ??
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.
Meine Datei ist aber nur 45KByte klein. Werden dann auch alle sektoren nacheinander angelegt?
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?
>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?
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
>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.
Entweder er springt in den Else-Zweig oder nicht und wenn ich dann mein I/O-Pin toggle dann sagt das doch alles!?
>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.
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.
>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.
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.
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
>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.
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
>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.
Die Daten werden vollständig gelesen. Ich nutze sie um ein Bild auf einem Display anzuzeigen und dieses wird vollständig dargestellt.
>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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.