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?
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, ¤tVolume, 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 | }
|
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.