Ich versuche mich gerade in cpp auf einem esp32 einzuarbeiten.
Dabei habe ich ein generelles Problem bei der Konvertierung in eine
Klasse. Speziell macht hier die isr Probleme.
Hier ein kleines Testprogramm für esp32, kompiliert mit dem Arduino
Framework.
Das Programm arbeitet wie gewünscht. Es ist nur für mich ein Beispiel
für das Zusammenwirken von isr->Queue->ControlTask.
Nun will ich die komplette Funktionalität in eine Klasse auslagern. Und
genau das bekomme ich nicht hin.
Das Problem ist offenbar die isr.
Mein erster Ansatz war:
Läßt sich zwar problemlos kompilieren. Aber die isr wird offenbar nicht
aufgerufen.
ChatGPT hat zwar einiges vorgeschlagen (u.a. eine Wrapperfunktion für
die isr) aber eine Lösung fand er auch nicht. Nach
einigen Stunden habe ich dann entnervt aufgeben;-)
Hat jemand einen Rat, wo es hier klemmen könnte?
> ChatGPT hat zwar einiges vorgeschlagen (u.a. eine Wrapperfunktion für> die isr) aber eine Lösung fand er auch nicht.
Das hat er, du siehst sie nur nicht. Ein Interrupthandler ist eine
globale Funktion. Soll diese eine Memberfunktion aufrufen, braucht sie
eine Instanz der Klasse - eine globale Referenz/Pointer/Objekt.
Irgendein dynamisches Object auf dem Stack reicht nicht. Woher soll der
Interrupthandler wissen, welche Instanz er nutzen soll?
gpio_isr_handler_add musst Du ebenfalls "this" als letztes Argument
geben. Außerdem hat der Vorposter Recht was die Queue betrifft. Diese
speichert nur Pointer. Da kann man nicht die Adresse einer Struktur vom
Stack reinstecken, "isr_data data" ist genau so lange definiert, wie die
ISR Funktion läuft, danach nicht mehr. Das ist bereits im C-Code falsch.
> gpio_isr_handler_add
Upps, das hatte ich garnicht gesehen. Ich war davon ausgegangen, dass
beim esp32 Interrupthandler ähnlich installiert werden wie bei anderen
CPUs, per globalem Namen und da ein solcher im o.g. Code nicht vorhanden
war, auch keiner installiert wurde.
Mit dieser Funktion ist meinen vorheriger Post ziemlicher Quatsch.
Sorry.
Foobar schrieb:> Das hat er, du siehst sie nur nicht. Ein Interrupthandler ist eine> globale Funktion. Soll diese eine Memberfunktion aufrufen, braucht sie> eine Instanz der Klasse - eine globale Referenz/Pointer/Objekt.> Irgendein dynamisches Object auf dem Stack reicht nicht.
Naja, jedenfalls hat er mir das prinzipielle Problem korrekt
beschrieben, so wie ihr auch schon angemerkt habt. Allerdings was sein
korrigierter Code nicht compilierbar und über die Hürde konnte er auch
nicht springen.
Hier sein Vorschlag:
Dieser dubiose Fehler scheint durch die CPU-Archtektur bedingt (also
kein Code-Fehler). Hier ist es etwas ausführlicher:
https://stackoverflow.com/questions/19532826/what-does-a-dangerous-relocation-error-mean
Ich würd mal versuchen, die Wrapper-Funktion anders zu plazieren, z.B.
als globale Funktion außerhalb der Klasse. Oder evtl begin() mit dem
handler_add auch IRAM_ATTR zu machen (nur damit sie im gleichen segment
landen). Solche Fehler sind häßlich und arten oft in viel
Rumprobiererei aus ...
Foobar schrieb:> Dieser dubiose Fehler scheint durch die CPU-Archtektur bedingt (also> kein Code-Fehler). Hier ist es etwas ausführlicher:> https://stackoverflow.com/questions/19532826/what-does-a-dangerous-relocation-error-mean>> Ich würd mal versuchen, die Wrapper-Funktion anders zu plazieren, z.B.> als globale Funktion außerhalb der Klasse. Oder evtl begin() mit dem> handler_add auch IRAM_ATTR zu machen (nur damit sie im gleichen segment> landen). Solche Fehler sind häßlich und arten oft in viel> Rumprobiererei aus ...
Danke für die hilfreichen Tipps!
> handler_add auch IRAM_ATTR zu machen
Daran habe ich noch gar nicht gedacht, das werde ich testen.
Außerdem will ich mal schauen, ob espressiv irgendwo in den Beispielen
der esp-idf-cxx brauchbare Hinweise versteckt hat.
Zum Glück komme ich in meinem Projekt auch ohne Klasse aus. Aber
irgendwie wurmt es mich schon, dass das nicht hinzubekommen sein soll.