F_Mount /FATFS / STM32F401RE

Gast #5566268
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]
Gast #5566332
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. :(
Gast #5566371
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.
Gast #5566394
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.
Gast #5566465
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.
#5566544
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.
Gast #5567122
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?
Gast #5567143
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.
#5567194
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
{
#5567203
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.
Gast #5567207
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.

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