Forum: Mikrocontroller und Digitale Elektronik Läuft Pointer aus dem Scope?


von Torsten (Gast)


Lesenswert?

Ich bin gerade dabei auf Basis des Arduino-Frameworks einen mp3-Player 
für Kinder zu realisieren. Das ursprüngliche Projekt dazu ist Tonuino - 
ich verwende hier jedoch aus verschiedenen Gründen einen ESP32. Da der 
ESP32 ja zwei Cores besitzt, Freertos drauf läuft und ich damit explizit 
mal was machen wollte, habe ich einen Task definiert, der auf dem 
zweiten Core läuft - dort findet die mp3-Dekodierung statt. Zugriff hat 
man von dort auch auf globale Variablen, ich habe den Datenaustausch 
primär jedoch so ausgelegt, dass er über Queues läuft. So habe ich eine 
Queue für eine Playlist, eine für die Lautstärke und eine zur Steuerung 
(pause, nächster Titel, letzter Titel etc pp). Die Playlist ist 
technisch ein char**, dessen Pointer ich mit malloc allokiert habe und 
dessen Strings mit strdup() allokiert wurden. Im ersten Element des 
char** speichere ich ab, wieviele Titel-Elemente vorhanden sind damit 
ich bereits vorher weiß, wie groß meine Playlist ist und damit ich meine 
"Pointer-Grenzen" sicher nicht verlasse.
So ein Task sieht vom Gerüst aus wie normale eine Funktion, beinhaltet 
jedoch eine Endlossschleife, die nicht verlassen werden darf. In der 
Schleife befindet sich dann der Code, der repetitiv ausgeführt werden 
soll. Wieso wie loop() in Arduino. Nun bin ich hingegangen und habe in 
dieser Funktion oberhalb der for(;;)-Schleife lokale Variablen 
deklariert, in denen ich die Inhalte dessen speichere, was aus den 
Queues kommt. So habe ich dort also "char **cTRack" deklariert und 
speichere dort die Adresse des Pointers der Playlist. Über die 
Titelsteuerung habe ich dann über diesen Pointer iteriert und alles hat 
wie gewünscht funktioniert. Habe ich jedoch die Lautstärke geändert (hat 
ebenfalls funktioniert) und anschließend nochmal versucht, den Titel zu 
wechseln, so hat der uC eine Exception geworfen und sich neu gestartet. 
Beheben konnte ich es damit, indem ich cTrack mit static deklariert 
habe.

Mein Problem habe ich damit behoben, aber ich würde das Ganze gerne 
verstehen. Läuft cTrack aus dem Scope, weil ich mich in einer 
Endlosschle-Schleife befinde und wird dann entsorgt? Oder ist das eine 
spezielle Eigenart von Freertos und ich habe es einfach falsch benutzt?

von Torsten (Gast)


Lesenswert?

Hier noch ein Auszug aus dem Code:
1
void playAudio(void *parameter) {
2
    audio.setPinout(I2S_BCLK, I2S_LRC, I2S_DOUT);
3
    audio.setVolume(initVolume);
4
5
    uint8_t currentVolume;
6
    char **cTrack;
7
    BaseType_t trackQStatus;
8
    uint32_t numberOfTracks = 0;
9
    uint32_t currentTrackNumber = 0;
10
    uint8_t trackCommand = 0;
11
12
    for (;;) {
13
        if (xQueueReceive(volumeQueue, &currentVolume, 0) == pdPASS ) {
14
            ...
15
            audio.setVolume(currentVolume);
16
        ...
17
        }
18
19
        if (trackControlQueue, &trackCommand, 0) == pdPASS) {
20
            ...do play/pause/next track/prev track....
21
        }
22
23
        trackQStatus = xQueueReceive(trackQueue, &cTrack, 0);
24
        if (trackQStatus == pdPASS || trackFinished || trackCommand != 0) {
25
            ...
26
            audio.connecttoSD(*(cTrack + currentTrackNumber));
27
            ...
28
    }
29
    esp_task_wdt_reset();
30
    }
31
    vTaskDelete(NULL);
32
}

von Torsten (Gast)


Lesenswert?

Ich sehe gerade, dass ich xQueueReceive() vergessen habe im zweiten 
if-Block. Die Funktionsweise ist auf jeden Fall wie im ersten Block. Im 
letzten if-Block puss ich auf den Status noch mehrfach zugreifen und 
speichere ihn daher zwischen.

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.