Moin,
Für mein Projekt setze ich neben einem fest verbauten FLASH Baustein
eine SD Karte ein um Daten zu speichern. Da es dem Nutzer relativ
einfach gemacht werden soll habe ich vor eine SD-Formatierungs Funktion
in mein Projekt mit einzubauen, so das man die SD Karte nicht vorher am
PC formatieren muss.
Elm Chan's FatFs liefert dafür ja eine passende Funktion: f_mkfs. Ich
nutze FatFs in der Version 0.14b.
Zum Testen bin ich nach dem Beispielcode von Elm Chan
vorgegangen(http://elm-chan.org/fsw/ff/doc/mkfs.html). Die Funktion
f_mkfs benötigt ein Arbeitspuffer welcher dort mit FF_MAX_SS belegt
wird. Nach der Beschreibung wird zwar gesagt das der Puffer ruhig größer
sein darf als FF_MAX_SS da dann weniger Schreibzugriffe auf der Karte
stattfinden und der Formatierungsprozess auch von kürzer Dauer ist.
Jedoch müsste der Puffer mindestens FatFs Sektorgröße haben(FF_MAX_SS)
somit sollte das mit FF_MAX_SS auch funktionieren. Tut es aber nicht.
Okay nicht immer sagen wir mal in 20 % der Fällen schlägt f_mkfs fehl
mit dem Fehlercode 1(FR_DISK_ERR). Auch vergrößern des Puffers anstatt
FF_MAX_SS(Bei mir auf 512 in der ffconf.h gesetzt) auf 1023 oder 2048
schlägt in der Regel immer noch fiel. Erst mit 4096 Bytes funktionierte
es bisher immer(5 Formatierungen durchgeführt).
Ich habe jetzt 20K RAM auf meinem STM32F103CBT6 von daher theoretisch
kein Problem jedoch sollte das ganze ja auch mit 512 Bytes als Puffer
funktionieren nur halt dann länger dauern.
Die SD-Karte ist nachdem FR_DISK_ERR zurückgeworfen wird unbrauchbar bis
man sie wieder richtig in FAT32 am PC formatiert. Die Dateien werden
wohl noch am PC angezeigt man aber auf sie nicht zugreifen oder neue
Dateien einfügen das quittiert Windows dann immer mit einem Fehler.
Hier mein Formatierungscode:
1
uint8_t formatSDCard(void) {
2
if(!useSD) return 99; //Only available if an SD card is inserted
3
4
if(f_unmount("") != FR_OK) return 98; //Unmount the current SD work area. SD is already mounted and initialized
5
FRESULT res = f_mkfs("", 0, formatBuffer, sizeof(formatBuffer)); //Format the SD card to FAT32
6
if(res != FR_OK) {
7
return res; //If f_mkfs fails to format the SD Card the error code of f_mkfs will returned here
8
}
9
10
return initSD(); //Initialize the SD Card again for the system.
11
}
Der Puffer "formatBuffer" ist wie folgt definiert:
1
BYTE formatBuffer[4096] __attribute__ ((aligned (4))) ; /* Working buffer */
So ist der Puffer auch in dem STM32 FatFs Examples
angelegt(ffsamples.zip). Mit 4096 Bytes funktioniert das Formatieren bis
jetzt immer. Mit FF_MAX_SS sollte es laut Beschreibung von der Elm Chan
Webseite auch gehen tut es aber nicht.
Hat jemand ne Ahnung warum das nur mit 4096 Bytes funktioniert oder hat
jemand die f_mkfs Funktion schonmal benutzt. Die restlichen Funktionen
von FatFs funktionieren immer bisher ohne Probleme. Angesprochen wird
die SD Karte vom STM32 mit 18MHz Takt. Als SD-Karte kommt im Moment eine
SanDisk Ultra 32GB microSD SDHC Karte zum Einsatz
Mfg
Felix N. schrieb:> Hat jemand ne Ahnung warum das nur mit 4096 Bytes funktioniert oder hat> jemand die f_mkfs Funktion schonmal benutzt. Die restlichen Funktionen> von FatFs funktionieren immer bisher ohne Probleme. Angesprochen wird> die SD Karte vom STM32 mit 18MHz Takt. Als SD-Karte kommt im Moment eine> SanDisk Ultra 32GB microSD SDHC Karte zum Einsatz
Versteh' ich nicht. Du hast die Quelltexte und einen Controller mit
einer guten Debugschnittstelle. Warum also steppst du nicht einfach mal
in die Funktion rein und schaust, wo genau sie scheitert?
Felix N. schrieb:> Okay nicht immer sagen wir mal in 20 % der Fällen schlägt f_mkfs fehl
Dann dekoriere mal die Disk Lese und Schreibfunktion so dass Du SD
Karten Fehler mitbekommst.
Bei diesem Verhalten ist nämlich eher die SD Karte selber das Problem.
Felix N. schrieb:> Okay nicht immer sagen wir mal in 20 % der Fällen schlägt> f_mkfs fehl mit dem Fehlercode 1(FR_DISK_ERR).Felix N. schrieb:> Erst mit 4096 Bytes funktionierte> es bisher immer(5 Formatierungen durchgeführt).
Wie willst Du auf der Basis von nur 5 Versuchen irgendwelche Schlüsse
ziehen, daß dadurch Dein Problem, das im Schnitt sowieso nur jedes 5.
Mal (20% der Fälle) auftritt, gelöst wurde?
Also mit weniger als 20 (erfolgreichen) Testläufen würd ich noch
nichtmal drüber nachdenken, ob ich das Problem als gelöst betrachte;
wobei selbst dann die Chance, daß alles nur ein (un)glücklicher Zufall
war noch über 1% liegt.
Felix N. schrieb:> Als SD-Karte kommt im Moment eine> SanDisk Ultra 32GB microSD SDHC Karte zum Einsatz
Moment Mal - willst Du damit sagen, daß bei ein und derselben Karte das
Formatieren mit 512 Byte Buffer in 20% der Fälle schiefgeht?
Das wäre dann nämlich eine eindeutige Bestätigung dieser Vermutung:
Jim M. schrieb:> Bei diesem Verhalten ist nämlich eher die SD Karte selber das Problem.
Moin! Sorry für die späte Antwort.
c-hater schrieb:> Warum also steppst du nicht einfach mal> in die Funktion rein und schaust, wo genau sie scheitert?
Das mit dem Debugger habe ich bereits versucht jedoch erfolglos. Ich
kenne mich nicht besonderes gut aus mit dem STM32 Debugger. Ein
entsprechenden Breakpoint habe ich gesetzt bei der Funktion. Jedoch wenn
ich das Programm als Debugging starte mit dem Debugging Level Default in
den Projekt Einstellungen. Startet es auch aber sobald ich auf "Resume"
klicke passiert nichts mehr. Wenn ich das Programm dann wieder anhalte
bleibt der Debugger bei der Initialisierung des OLED Display stehen,
auch wenn ich ihn dann wieder starte und später wieder anhalte bleibt
der an der genau gleichen stelle. Wahrscheinlich bediene ich aber den
Debugger auch einfach falsch.
Jim M. schrieb:> Dann dekoriere mal die Disk Lese und Schreibfunktion so dass Du SD> Karten Fehler mitbekommst.
Verstehe ich jetzt nicht ganz. Du meinst die disk_read und disk_write
Funktionen in der mmc.c Datei?
Jim M. schrieb:> Bei diesem Verhalten ist nämlich eher die SD Karte selber das Problem.mIstA schrieb:> Moment Mal - willst Du damit sagen, daß bei ein und derselben Karte das> Formatieren mit 512 Byte Buffer in 20% der Fälle schiefgeht?>> Das wäre dann nämlich eine eindeutige Bestätigung dieser Vermutung:
Nein. Ich habe mehrere SD-Karten mitterweile ausprobiert. Insgesamt 5
verschiedene SD Karten auch von unterschiedlichen Herstellern.
Folgende:
- SanDisk Ultra 32GB -> 1x von 10x erfolgreich bei 512 Bytes
- SanDisk Extreme 128GB(exFAT Support aktiviert) -> Fehlgeschlagen
- Hama microSD 2GB -> 2x von 10 mal geklappt FAT16
- Hama microSD 4GB -> 10x fehlgeschlagen
- Samsung EVO 64GB -> Fehlgeschlagen(exFAT). f_mkfs hängt teilweise
komplett hier.
Alles mit Puffer von FF_MAX_SS ausprobiert(512 Bytes).
Ich habe mal in der ff.c wo LEAVE_MKFS(FR_DISK_ERR) zurückgegeben wird
UART Nachrichten eingefügt folgender Codeteil wirft das FR_DISK_ERR
immer egal bei welcher SD-Karte mit welcher Größe:
1
/* Initialize FAT area */
2
memset(buf, 0, sz_buf * ss);
3
sect = b_fat; /* FAT start sector */
4
for (i = 0; i < n_fat; i++) { /* Initialize FATs each */
if (disk_write(pdrv, buf, sect, (UINT)n) != RES_OK) LEAVE_MKFS(FR_DISK_ERR); //<<<<<<<---!
16
memset(buf, 0, ss); /* Rest of FAT all are cleared */
17
sect += n; nsect -= n;
18
} while (nsect);
19
}
mIstA schrieb:> Also mit weniger als 20 (erfolgreichen) Testläufen würd ich noch> nichtmal drüber nachdenken, ob ich das Problem als gelöst betrachte;> wobei selbst dann die Chance, daß alles nur ein (un)glücklicher Zufall> war noch über 1% liegt.
Das dass Problem als gelöst betrachtet sei hab ich ja nicht behauptet.
Ich habe ja nur festgestellt das wenn der Puffer 4096 Bytes groß ist
anstatt der Mindestgröße von FF_MAX_SS(512 Bytes) die Funktion besser
funktioniert. Wenn ich jetzt 100 Testdurchläufe mache und 2 davon
fehlschlagen wären das 2%. Wenn ich wie jetzt 5 mache und davon mit 4096
Bytes alle funktionieren während bei 512 Bytes nur 1 oder 2
funktioniert. Kann man ja schonmal davon ausgehen das irgendwas damit
nicht stimmt.
Den Compiler habe ich aktuell bei Optimization level auf "Optimize of
Size (-Os)) stehen. Aber das dürfte ja eigentlich keine Auswirkung haben
oder?
mfg
Felix N. schrieb:> Wahrscheinlich bediene ich aber den> Debugger auch einfach falsch.
Davon kann man wohl ausgehen. Wie wäre es, wenn du den richtigen Umgang
damit einfach mal erlernst? Das hilft dir nur nicht nur bei dem
gegenwärtigen Problem, sondern auch bei jedem zukünftigen.
Genau deswegen schrieb ich oben dass Du disk_write mal so dekorieren
solltest das Schreibfehler ausgegeben werden.
Kann durchaus sein das da irgendwas nicht lange genug wartet zum
Bleistift.
Das originale Format (oder das mit dem Formatter von sdcard.org) packt
die FAT nämlich an die internen Blockgrenzen der Karte - das f_mkfs hat
davon überhaupt keine Ahnung.
Übrigens macht es bei SD Karten einen RIESEN Unterschied ob man sie mit
512 Byte oder 4KB Blöcken beschreibt. Bei 512 Byte fahren die nach dem
Schreiben in den Stromspar Modus runter, bei 4K Blöcken nicht.
Ich hatte hier schon Karten die >1 sec fürs Schreiben brauchen. Stelle
eventuell mal die Timeouts hoch.
Moin,
c-hater schrieb:> Wie wäre es, wenn du den richtigen Umgang> damit einfach mal erlernst?
Werde ich machen. Kannst du mir da gute Quellen nennen die das gut
erklären?
Jim M. schrieb:> Genau deswegen schrieb ich oben dass Du disk_write mal so dekorieren> solltest das Schreibfehler ausgegeben werden.
Ich habe die Funktion nun mal mit ein paar UART Nachrichten
überarbeitet. Die Funktion ist unten mal mit angehängt damit man das
nachvollziehen kann wo welche Nachricht ausgeben wird wenn ein Fehler
eintritt. Die disk_read Funktion hab ich vorsichtshalber auch mal mit
überarbeitet aber da erfolgt keine Fehlerausgabe.
Dem nach tritt der Fehler beim f_mkfs in der disk_write funktion auf
beim schreiben des blocks:
1
if ((send_cmd(CMD24, sect) == 0) /* WRITE_BLOCK */
2
&& xmit_datablock(buff, 0xFE)) {
Es wird beim Formatieren(f_mkfs) immer zurückgeben neben FR_DISK_ERR.
diskwrite() CMD24 failed.
Jim M. schrieb:> Übrigens macht es bei SD Karten einen RIESEN Unterschied ob man sie mit> 512 Byte oder 4KB Blöcken beschreibt. Bei 512 Byte fahren die nach dem> Schreiben in den Stromspar Modus runter, bei 4K Blöcken nicht.
Hmm okay. Also ich nutze hier ja den STM32F103CBT6 der hat 20K RAM. Da
könnte ich noch ein paar kB für die SD-Karte verwenden. Ist das der
FF_MIN_SS und FF_MAX_SS Parameter in der ffconf.h?
Jim M. schrieb:> Stelle> eventuell mal die Timeouts hoch.
Falls sich das auf die FF_MIN_SS und FF_MAX_SS bezieht. Die stehen
aktuell beide auf 512. Wenn ich beide auf 1024, 2048 oder 4096 stelle
wird die SD-Karte nicht mehr erkannt und ich kann sie nicht mehr
mounten.
disk_write:
1
#if FF_FS_READONLY == 0
2
DRESULT disk_write (
3
BYTE drv, /* Physical drive number (0) */
4
const BYTE *buff, /* Ponter to the data to write */
5
LBA_t sector, /* Start sector number (LBA) */
6
UINT count /* Number of sectors to write (1..128) */