Forum: Mikrocontroller und Digitale Elektronik F_Mount /FATFS / STM32F401RE


von FATHM (Gast)


Lesenswert?

Hallo,

folgendes Problem beschäftigt mich seit kurzem:

Ich bekommen Daten über UART1 und Interrupt des F401RE rein, speichere 
diese in einem Buffer und möchte dessen Inhalt auf eine µSD-Karte 2GB 
Class 4  speichern.
Die HW lass ich mir mittels CubeMX erstellen.

Dazu folgenden Code, der auch funktioniert:
1
while(1)
2
{
3
fresult1=f_mount(&myFATAFS,SDPath,1) ;
4
      
5
 if(fresult1==FR_OK)
6
        {
7
         
8
        char MyPath[]="testfile.TXT";
9
        char MyData[]="Wieder ein Test.";
10
        f_open(&myFILE,MyPath,FA_WRITE|FA_CREATE_ALWAYS);
11
        f_write(&myFILE,MyData,sizeof(MyData),&testByte);
12
        f_close(&myFILE);
13
        f_mount(&myFATAFS,SDPath,0);
14
}
15
}
-> Funktioniert, Datei und Inhalt können z.B. am PC gelesen werden.
1
{
2
if(received)
3
    { fresult1=f_mount(&myFATAFS,SDPath,1) ;
4
       if(fresult1==FR_OK)
5
        {
6
         
7
        char MyPath[]="testfile.TXT";
8
        char MyData[]="Wieder ein Test.";
9
        f_open(&myFILE,MyPath,FA_WRITE|FA_CREATE_ALWAYS);
10
        f_write(&myFILE,MyData,sizeof(MyData),&testByte);
11
        f_close(&myFILE);
12
        f_mount(&myFATAFS,SDPath,0);
13
     }
14
   received=0;
15
}
-> funktioniert nicht. Der Code bleibt bei f_mount stehen. Nichts geht 
mehr.

Was genau übersehe ich? Hat jemand Lösungen für dieses Problem?

[Mod: Fehlendes C-Tag eingefügt]

: Bearbeitet durch Moderator
von Falk B. (falk)


Lesenswert?

Warum hast du das Mount in der while(1) Schleife? Das macht man einmal 
am Programmanfang und dann nie wieder. Damit die Daten komplett 
geschrieben werden reicht das f_close(), das schreibt alle Restdaten aus 
dem Puffer in die Datei.

von Εrnst B. (ernst)


Lesenswert?

FATHM schrieb:
> Ich bekommen Daten über UART1 und Interrupt des F401RE rein, speichere
> diese in einem Buffer

Du hast dein f_mount &co aber schon im Haupt-Programm, nicht in der ISR?
Wird aus deinem Beispiel-Code nicht ersichtlich...

von FATHM (Gast)


Lesenswert?

Danke für die schnelle Antworten.

>Du hast dein f_mount &co aber schon im Haupt-Programm, nicht in der ISR?
>Wird aus deinem Beispiel-Code nicht ersichtlich...


Ja, das ist mein Hauptprogramm, nicht die ISR. In der ISR wird nur die 
globale variable receive = 1  gesetzt.

>Warum hast du das Mount in der while(1) Schleife? Das macht man einmal
>am Programmanfang und dann nie wieder. Damit die Daten komplett
>geschrieben werden reicht das f_close(), das schreibt alle Restdaten aus
>dem Puffer in die Datei.

Danke für den Tipp. Ich habe nun das f_mount vorher initialisiert. Jetzt 
hängt sich das Programm im f_open auf. Also eine Zeile weiter. :(

von Falk B. (falk)


Lesenswert?

@ FATHM (Gast)

>Danke für den Tipp. Ich habe nun das f_mount vorher initialisiert.

Hast du auch dessen Rückgabewert geprüft?

http://elm-chan.org/fsw/ff/doc/mount.html

von FATHM (Gast)


Lesenswert?

>Hast du auch dessen Rückgabewert geprüft?

Der Rückgabewert lautet FR_OK. Wenn die Karte nicht im Slot steckt: 
FR_NOT_READY

von Johannes S. (Gast)


Lesenswert?

Wie ist die SD angeschlossen? Per SDIO hatte ich auch gerade das Problem 
das der HAL Code im Pollingmode zu langsam ist, besonders im debug build 
ohne Optimierungen. Das führte zuverlässig zu Fehlern bei der 
Datenübertragung. Mit DMA sieht es besser aus und es läuft mit 24 MHz 
SDIO Clock.

von FATHM (Gast)


Lesenswert?

>Wie ist die SD angeschlossen? Per SDIO hatte ich auch gerade das Problem
>das der HAL Code im Pollingmode zu langsam ist, besonders im debug build
>ohne Optimierungen. Das führte zuverlässig zu Fehlern bei der
>Datenübertragung. Mit DMA sieht es besser aus und es läuft mit 24 MHz
>SDIO Clock.

Ich nutze SDIO 1Bit. Somit sind CMD, D0 und CLK an der Karte 
angeschlossen + 3,3V und gemeinsame Masse aufgebaut auf einer 
Lochrasterplatine.

Ich habe das Problem, dass das gesamte Programm abschmirrt.

von Frank M. (ukw) (Moderator) Benutzerseite


Lesenswert?

FATHM schrieb:
> funktioniert nicht. Der Code bleibt bei f_mount stehen.

Wenn Dein Testcode ohne ISR funktioniert und der identische Code mit 
ISR nicht, dann muss es an dem Code liegen, den Du nicht gepostet 
hast.

von Falk B. (falk)


Lesenswert?

Kann es sein, daß die Interruptfunktion für das Timeout fehlt? Dann 
bleibt der Zugriff natürlich stehen . . .

von kyrk.5 (Gast)


Lesenswert?

Hallo,

was heißt genau: abschmirrt

Kannst du mit dem debugger stop machen? Ist der Context dann ok? Wo bist 
du? While schleife oder interrupt? Sind die Variablen die du da hast 
noch ok? Kommen noch irgendwelche interrupts durch? Timer?

Versuche mal den f_mount zu debuggen. Wie lange kommst du noch durch? 
Ist nicht so schwer, ich habe den auch paar mar gedebugt nach paar Tagen 
geht es wie geschmiert.

von Falk B. (falk)


Lesenswert?

@ kyrk.5 (Gast)

>Versuche mal den f_mount zu debuggen. Wie lange kommst du noch durch?
>Ist nicht so schwer, ich habe den auch paar mar gedebugt nach paar Tagen
>geht es wie geschmiert.

Genau sooo macht man es bestimmt nicht. FATfs ist sehr gut getestet, da 
muß man nicht in den Innereien rumdebuggen. Man sollte einfach die 
Rückgabewerte auswerten und ernst nehmen. Einzig und allein die Low 
Level Funktionen, die man an die Hardware selber anpassen muß sind 
debugwürdig.

von FATHM (Gast)


Lesenswert?

>Kann es sein, daß die Interruptfunktion für das Timeout fehlt? Dann
>bleibt der Zugriff natürlich stehen . . .

Tut mir leid Falk, aber das habe ich nicht verstanden. Könntest du mir 
das genauer erklären, bzw. eine Quelle nennen wo ich die Hintergründe 
genauer nachlesen könnte?

von kyrk.5 (Gast)


Lesenswert?

Ich habe das genau so gemacht und festgestellt dass es bei mir damals an 
der Low Level Funktion gelegen hat. Wobei bei mir war ein Delay Funktion 
nicht richtig integriert wurde und deswegen nie zu Ende lief. Dadurch 
gab es keinen Rückgabewert. Dann hatte ich noch ewig probleme mit nicht 
laufenden SD Karten, weil der SPI nicht dediziert war und ein MP3 chip 
hing da auch drauf. Die SD Karte nahm das aber über, weil er ja in SDIO 
mode hochstartet und wenn da erst der MP3 chip initializiest wird nehmen 
das manche karten nicht so gut an (sprich denken die werden gerade 
angesprochen)

Aber prinzipiell hast du recht. Erstmal Doku lesen und so machen wie es 
da drin steht. Wenn aber immer noch nicht tut dann muss man einfach 
reindebuggen. Die 2 Dinge helfen in 80% der Fällen.

von Johannes S. (Gast)


Lesenswert?

in der hsd Struktur ist noch ein Member 'ErrorCode', das ist der letzte 
Fehler vom LL Treiber. Die Bedeutungen sind in stm32f4xx_ll_sdmmc.h zu 
finden.

von Falk B. (falk)


Lesenswert?

@ FATHM (Gast)

>>Kann es sein, daß die Interruptfunktion für das Timeout fehlt? Dann
>>bleibt der Zugriff natürlich stehen . . .

>Tut mir leid Falk, aber das habe ich nicht verstanden. Könntest du mir
>das genauer erklären, bzw. eine Quelle nennen wo ich die Hintergründe
>genauer nachlesen könnte?

Für FATfs muss im 10ms Zeitraster eine kleine Funktion aufgerufen 
werden, welche die Timeouts regelt. Die liegt im avr Beispiel in

mmc_avr_spi.c
1
/*-----------------------------------------------------------------------*/
2
/* Device Timer Interrupt Procedure                                      */
3
/*-----------------------------------------------------------------------*/
4
/* This function must be called in period of 10ms                        */
5
6
void mmc_disk_timerproc (void)
7
{

von Jim M. (turboj)


Lesenswert?

FATHM schrieb:
> eine µSD-Karte 2GB
> Class 4  speichern.

Hast Du mal eine andere SD(HC) Karte probiert? Die billigen 2GB Class 4 
sind mitunter ab Werk defekt beim Kunden angekommen.

Das mit dem Timeout hilft Dir auch kaum weiter, denn wenn der zuschlägt 
kannste die Karte nur durch Unterbrechen der Stromversorgung resetten.

Im Normalbetrieb sollte kein Timeout auftreten - dann ist immer 
irgendwas nicht OK.

von Johannes S. (Gast)


Lesenswert?

für die Timeouts nutzt die HAL Implementierung den SysTick, das wird 
alles im generierten Code vom Zauberwürfel gemacht.
In main.c ist noch eine leere Fehlerbehandlung:
1
void _Error_Handler(char *file, int line)
2
  /* USER CODE BEGIN Error_Handler_Debug */
3
  /* User can add his own implementation to report the HAL error return state */
4
  while(1)
5
  {
6
  }
7
  /* USER CODE END Error_Handler_Debug */
da wäre ein printf() mit Fehlerausgabe auf Display oder UART hilfreich. 
Oder wenigstens hektisches LED blinken damit man sieht der µC hängt in 
der Fehlerschleife.
Aber wie Uwe schon schrieb, wenn der nahezu gleich Code schon lief 
müssen noch woanders Änderungen sein.
Fehlerträchtig ist auch das Konzept mit den __weak Deklarationen das mit 
HAL viel genutzt wird. Ich hatte Interrupthandler und Callbacks in eine 
C++ Quelle verschoben und schon wurde es wegen C++ name mangling nicht 
mehr aufgerufen, der Compiler kann da aber nichts prüfen und dem Linker 
ist es egal ob eine __weak Funktion überschrieben wird oder nicht.

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.