Forum: Mikrocontroller und Digitale Elektronik FATFS-SD-Card - Probleme mit f_puts und PingPong-Buffer auf STM32


von Sebastian B. (sebastian_b837)


Lesenswert?

Hallo an Alle,

mein Projekt läuft auf einem Nucleo Board mit STM32 L476. Ich nutze ein 
SD-Karten-Breakout mit SPI-Kommunikation und die 
FatFS-SD-Implementierung von Eziya 
(https://github.com/eziya/STM32_SPI_SDCARD).

Zum Umriss was ich versuche:
ADC-Messung soll laufen, über die HAL_ADC_ConvCpltCallback sollen 2 
Buffer abwechselnd auf eine SD-Karte geschrieben werden 
(Ping-Pong-Style). Die Messung läuft also und wird zeitgleich 
gespeichert bis man sie per Tastendruck beendet.

Mein Ursprungsdesign zum Test basierte darauf, dass nur ein Buffer 
vollgeschrieben und dieser dann an eine extra Funktion weitergegeben 
wird, welche die SD-Karte mountet, eine neue Datei erstellt, diese mit 
dem Array beschreibt und dann die Datei schließt. Dies funktioniert auch 
problemlos, weswegen ich Hardwarefehler und allgemeine Probleme mit der 
Library ausschließe.

Meine neue PingPong-Implementierung soll nun zuerst eine gesonderte 
Funktion "initSD" aufrufen, welche die ersten Schritte der alten 
Funktion übernimmt (f_mount(), f_open()) und dann die durch f_open() 
erstellte Datei zurückgibt. In der Callback-Funktion des ADC soll nun 
dieses File genommen und mittels f_puts() beschrieben werden.

Allerdings wird f_puts() nicht korrekt ausgeführt und die Funktion 
landet in einer Endlosschleife, ein verwertbares fresult wird nicht 
zurückgegeben. Googlen zu diesem Problem hat mir bis jetzt nichts 
gebracht. In der init-Funktion() wird überall FR_OK zurückgegeben, das 
scheint zu funktionieren. Auch das durch die Funktion rückgegebene 
file-Struct existiert in der Callback und sieht eigentlich gut aus 
(Breakpoint und Expression Viewer).

Lange Rede, kurzer Sinn. Hier meine Codebeispiele.

*Initfunktion in sd-card.c:*
1
//Structs
2
FATFS fs;  // file system
3
FIL fil; // File
4
FRESULT fresult;  // result
5
6
//Initfunktion
7
FIL initSD()
8
{
9
//SD-Card - Mount
10
fresult = f_mount(&fs, "/", 1);
11
12
/*
13
Hier würde vermutlich irrelevanter Code stehen, welcher die SD-Karte liest und einen neuen,ungenutzten Dateinamen findet.
14
Ausgabe ist das char[]-Array measurement_name (funktioniert).
15
*/
16
17
//Öffnen der Datei
18
fresult = f_open(&fil,measurement_name , FA_OPEN_ALWAYS | FA_READ | FA_WRITE);  
19
20
//Return der Datei
21
return fil;
22
}

*Precode beim Start der Messung in main.c:*
1
FATFS fs;  // file system
2
FIL fil; // File
3
FRESULT fresult;  // result
4
5
uint32_t k = 0; //Zählvariable für Buffer-Switching
6
7
//Initialisierung der SD Karte - Erstellung der Datei
8
fil = initSD();
9
10
//Initialisierung ADC
11
HAL_ADC_Start_DMA(&hadc2, (uint32_t*)&adc_buff1, adc_buff_size);
12
13
//Initialisierung Timer
14
HAL_TIM_OC_Start(&htim4, TIM_CHANNEL_4);

*ADC-Callback etwas später im Code der main.c:*
1
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
2
{
3
if(k % 2 == 0)
4
{
5
//ADC-Buffer-Switching (Ping-Pong)
6
/*
7
Es gibt 2 gleich lange Buffer adc_buff1 und adc_buff2, welche abwechselnd gefüllt oder auf die SD-Karte geschrieben werden sollen.
8
*/
9
HAL_ADC_Stop_DMA(&hadc2);
10
HAL_ADC_Start_DMA(&hadc2,(uint32_t* ) adc_buff2 ,adc_buff_size);
11
12
//Char Array measurement data
13
char measurement_value[4];
14
15
//SD-Card - Write measurement data
16
for(int i = 0; i <= ((adc_buff_size)-1) ; i++)
17
{
18
//Converting measurement to char - 1
19
sprintf(measurement_value, "%d", adc_buff1[i]);
20
21
//Writing measurement data (HIER IST DAS PROBLEM - Infinite Loop)
22
f_puts(measurement_value, &fil);
23
24
//Writing new column (Diese geht auch nicht, es liegt also nicht an "measurement_value")
25
f_puts(";\n", &fil);
26
}
27
28
else
29
{
30
//Gleicher Code für adc_buff2
31
}
32
k++;
33
}

Ich vermute ja es geht etwas bei der Weitergabe des Datei-Structs "fil" 
schief, habe auch schon versucht diese in der main.c als externe 
Variable zu definieren, jedoch mit selben Ergebnis.
Ich weiß nicht, ob man mir auf dieser Art und Weise groß helfen kann, 
aber vielleicht habe ich irgendetwas ganz offensichtliches übersehen 
(bin auf dem Gebiet gewiss kein Experte).
Vielleicht hatte auch jemand schon eine ähnliche Problemstellung mit der 
permanenten ADC-Wert-Speicherung und hat einen alternativen, besseren 
Vorschlag.

Ich bin euch für jeden Ratschlag/Hilfe dankbar, weil ich nun schon seit 
Tagen daran sitze.

Mit freundlichen Grüßen

Basti

: Bearbeitet durch User
von Sebastian B. (sebastian_b837)


Lesenswert?

Anscheinend funktioniert keine der FATFS-Funktionen in der ADC-Callback, 
außerhalb problemlos. Habe nun mänlich versucht den ganzen Prozess inkl. 
Mounting in diese zu packen, aber sämtliche Funktionen freezen. Das 
deutet darauf hin, dass meine Funktionen nicht mit dem Interrupt zu 
Recht kommen, oder? (wegen Delays oder ähnlichem).

von Sebastian B. (sebastian_b837)


Lesenswert?

Falls es jemanden in Zukunft interessiert es lag tatsächlich am 
Interrupt, da Eziya's Code diesbezüglich anscheinend etwas unsauber ist. 
Einfach in den NVIC-Settings des STM's die SysTick-Priority 
hochschrauben und es sollte laufen, so jedenfalls bei mir.

von Falk B. (falk)


Lesenswert?

Sebastian B. schrieb:
> Falls es jemanden in Zukunft interessiert es lag tatsächlich am
> Interrupt, da Eziya's Code diesbezüglich anscheinend etwas unsauber ist.
> Einfach in den NVIC-Settings des STM's die SysTick-Priority
> hochschrauben und es sollte laufen, so jedenfalls bei mir.

Warum unsauber? In den unteren Schichten des Treibers gibt es an 
mehreren Stellen eine Timeout-Funktion. Die braucht aber einen 
lauffähigen Interrupt. Wenn du nun aber die Funktion schon aus einem 
hochprioren Interrupt aufrufst, sind ggf. niederpriore Timer-Interrupts 
inaktiv.

Ich würde den Aufruf so oder so NICHT aus einem Interrupt heraus machen, 
auch wenn es jetzt geht. Wenn man schon einen Doppelpuffer hat, geht das 
spielend und sauber mit einem zyklischen Aufruf als normale Funktion in 
der Hauptschleife. Dann werden auch alle anderen Interrupts nicht 
blockiert, egal welche Priorität die haben.

Das kann sogar ein Arduino ;-)

Beitrag "Re: Arduino Nano, SD Card, PCM"

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.