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
charMyPath[]="testfile.TXT";
9
charMyData[]="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
charMyPath[]="testfile.TXT";
8
charMyData[]="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]
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.
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...
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. :(
@ 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
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.
>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.
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.
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.
@ 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.
>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?
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.
@ 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
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.
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,intline)
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.