esp32c3 & interrupt service routine

OP #7803898

Ich frage mich gerade wie man bei einem ESP32 ohne jetzt das IDF Framework nutzen zu wollen, sondern in C auf Low Level Basis Interrupts zum laufen zu bekommen.

Im Datenblatt steht einiges zu der RISC-V Architektur und auch etwas zu den Interrupts.

Es gibt eine Tabelle "Tram Vector" dort gibt es 31 "Vektoren" für die jeweiligen Interrupts die vorher konfiguriert wurden.

Jetzt meine Frage.. Wie bekomme ich meine Funktion die ausgeführt werden soll dorthin "gemoppt"?

Kann ich meiner Funktion die ausgeführt werden soll bei dem Interrupt die Adresse des Vektors zuweisen? Oder wie ist hier die Vorgehensweise?

Angehängte Dateien:

Ueblicherweise gehoert zu einem C-Compiler eine Runtime, In der findet sich dann eine "startup.s" in der die Interruptvektoren "weak" auf vordefinierte Interruptroutinen zeigen. Will man selbst einen Interrupt bedienen, schreibt man eine gleichnamige Funktion, die eben nicht "weak" definiert ist, und so beim linken im Programm landet.

Das wird beim RISC-V auch nicht wesentlich anders ein...

OP

Motopick schrieb:

Ueblicherweise gehoert zu einem C-Compiler eine Runtime, In der findet sich dann eine "startup.s" in der die Interruptvektoren "weak" auf vorderinierte Interruptroutingen zeigen. Will man selbst einen Interrupt bedienen, schreibt man eine gleichnamige Funktion, die eben nicht "weak" definiert ist, und so beim linken im Programm landet. Das wird beim RISC-V auch nicht wesentlich anders ein...

Okay. Und die im Bild zu sehenden Adressen sind dann quasi die wo die Funktionen stehen bzw. die Adressen dafür?

OP

Rainer W. schrieb:

Jan H. schrieb:

Und die im Bild zu sehenden Adressen sind dann quasi die wo die Funktionen stehen bzw. die Adressen dafür?

Im Bild ist die Interruptvektortabelle zu sehen. Unter "Address" sind die Adressen aufgeführt, wo die Startadresse der aufzurufenden Interruptfunktion einzutragen ist.

Das heißt unter diesen Adressen kann ich jeweils die Adresse meiner aufzurufenden Funktion schreiben?

OP

Rainer W. schrieb:

Jan H. schrieb:

Das heißt unter diesen Adressen kann ich jeweils die Adresse meiner aufzurufenden Funktion schreiben?

Ja, normalerweise sollte es im Compiler eine Möglichkeit geben, der diese Eintragung der Startadresse der ISR in der Tabelle veranlasst.

Mir geht es auch darum zu lernen und zu verstehen wie das ganze funktioniert.

Ist es dann auch möglich während mein Programm läuft die Adressen in den Interrupt Vektoren zu verändern?

OP

Das heißt das ganze könnte dann ungefähr so aussehen?

Eine Funktion nimmt quasie die "Callback" Funktion entgegen, deren Adresse dann im besagten Interrupt Vektor gespeichert wird:

1
uint8_t int_map_interrupt( int_cpu_slot_t _slot, void (*_callback)() ){
2
    if( _slot > __INT_CPU_SLOT_MAX__ ) return 1; // slot unknown
3

4
    int_trap_vector[ _slot ] = _callback;
5

6
    return 0;
7
}

Das sind die ganzen 31 Vektoren:

1
#define MTVEC_REG          0x305                                                              
2
#define MTVEC_REG_OFFSET   0x04                                                  
3
#define MTVEC_CALC_SLOT(n) ( MTVEC_REG + ( n * MTVEC_REG_OFFSET ) )                                                
4

5
volatile uint32_t* int_trap_vector[] = {
6
    MTVEC_CALC_SLOT(1),
7
    MTVEC_CALC_SLOT(2),
8
    MTVEC_CALC_SLOT(3),
9
    MTVEC_CALC_SLOT(4),
10
    MTVEC_CALC_SLOT(5),
11
    MTVEC_CALC_SLOT(6),
12
    MTVEC_CALC_SLOT(7),
13
    MTVEC_CALC_SLOT(8),
14
    MTVEC_CALC_SLOT(9),
15
    MTVEC_CALC_SLOT(10),
16
    MTVEC_CALC_SLOT(11),
17
    MTVEC_CALC_SLOT(12),
18
    MTVEC_CALC_SLOT(13),
19
    MTVEC_CALC_SLOT(14),
20
    MTVEC_CALC_SLOT(15),
21
    MTVEC_CALC_SLOT(16),
22
    MTVEC_CALC_SLOT(17),
23
    MTVEC_CALC_SLOT(18),
24
    MTVEC_CALC_SLOT(19),
25
    MTVEC_CALC_SLOT(20),
26
    MTVEC_CALC_SLOT(21),
27
    MTVEC_CALC_SLOT(22),
28
    MTVEC_CALC_SLOT(23),
29
    MTVEC_CALC_SLOT(24),
30
    MTVEC_CALC_SLOT(25),
31
    MTVEC_CALC_SLOT(26),
32
    MTVEC_CALC_SLOT(27),
33
    MTVEC_CALC_SLOT(28),
34
    MTVEC_CALC_SLOT(29),
35
    MTVEC_CALC_SLOT(30),
36
    MTVEC_CALC_SLOT(31),
37
};

Wenn es der Compiler uebersetzt, heisst das noch nicht, dass es funktioniert. Du solltest dir fuer den Anfang erstmal ein kleineres Broetchen backen.

Z.B. einen Timerinterrupt. Und dann mit offenem Auge erkunden, was der Compiler zu welchem Zweck wohin positioniert hat, und was es tut.

Per Default, sind die weak definierten, bereits vorhandenen Interruptroutinen, schon mit einigermassen sinnvollen Aktionen belegt.

P.S.: Viele CPUs/Controller schuetzen auch solche Bereiche, und muessen kwasi erst "entsperrt" werden, wenn man darau herumturnen will.

Gast

ESP32 sind eigentlich nicht für diese bare-metal Programmierung vorgesehen. Viele Funktionen kann man mangels Doku gar nicht nutzen.

Meinst du nicht, daß ein normaler Mikrocontroller besser geeignet ist? Zum Lernen würde ich mit einem überschaubaren STM32L0 anfangen und später auf einen stärkeres Modell wechseln, falls nötig. Test-Boards findet man unter dem Namen "STM32 Nucleo".

OP

Sherlock 🕵🏽‍♂️ schrieb:

ESP32 sind eigentlich nicht für diese bare-metal Programmierung vorgesehen. Viele Funktionen kann man mangels Doku gar nicht nutzen.

Meinst du nicht, daß ein normaler Mikrocontroller besser geeignet ist? Zum Lernen würde ich mit einem überschaubaren STM32L0 anfangen und später auf einen stärkeres Modell wechseln, falls nötig. Test-Boards findet man unter dem Namen "STM32 Nucleo".

Ja Da gebe ich Dir zu 100% recht. Diese Mikrocontroller sind wirklich nicht leicht zu bedienen (bare metal) aber es macht mir spaß zu forschen und rum zu probieren bis es funktioniert.

Angefangen habe ich mit den kleinen 8 bitlern von ATMEL.

Da man die ESP32 sau günstig bekommt, habe ich mich einfach mal da dran getraut. Vieles läuft auch schon, einiges noch nicht so ganz perfekt. Dafür gibt es ja aber Foren wo man Hilfe bekommen kann ;)

OP

Motopick schrieb:

Wenn es der Compiler uebersetzt, heisst das noch nicht, dass es funktioniert. Du solltest dir fuer den Anfang erstmal ein kleineres Broetchen backen.

Z.B. einen Timerinterrupt. Und dann mit offenem Auge erkunden, was der Compiler zu welchem Zweck wohin positioniert hat, und was es tut.

Per Default, sind die weak definierten, bereits vorhandenen Interruptroutinen, schon mit einigermassen sinnvollen Aktionen belegt.

P.S.: Viele CPUs/Controller schuetzen auch solche Bereiche, und muessen kwasi erst "entsperrt" werden, wenn man darau herumturnen will.

Ich habe mal den ganzen Projekt Ordner auf eine "*.s" durchsuchen lassen, leider findet er nur eine "x509_crt_bundle.S" dort stehen aber keine ASM Befehle.

Jan H. schrieb:

Ich frage mich gerade wie man bei einem ESP32 ohne jetzt das IDF Framework nutzen zu wollen, sondern in C auf Low Level Basis Interrupts zum laufen zu bekommen.

...

Jetzt meine Frage.. Wie bekomme ich meine Funktion die ausgeführt werden soll dorthin "gemoppt"?

Schau nach wie es das IDF macht. Mach dir eine Kanne oder zwei deines bevorzugten Heißgetränkes, stell das Telefon auf Flugmodus und die Hausklingel ab, und dann schau in den IDF-Quelltext.

Mögliche, zufällig rausgesuchte Einstiegspunkte:

https://github.com/espressif/esp-idf/blob/master/components/esp_hw_support/intr_alloc.c https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/interrupt_clic_ll.h https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/interrupt_int_ll.h https://github.com/espressif/esp-idf/blob/master/components/hal/include/hal/interrupt_plic_ll.h https://github.com/espressif/esp-idf/blob/master/components/hal/esp32c3/include/hal/crosscore_int_ll.h https://github.com/espressif/esp-idf/blob/master/components/soc/esp32c3/interrupts.c https://github.com/espressif/esp-idf/blob/master/components/soc/esp32c3/register/soc/interrupt_core0_reg. https://github.com/espressif/esp-idf/blob/master/components/soc/esp32c3/include/soc/interrupts.h

Das sieht auf den ersten Blick nicht sehr Spaßig aus. Ich würde die Verwendung einer IDE vorschlagen die gut darin ist Querverweise aufzulösen.

Jan H. schrieb:

Ich habe mal den ganzen Projekt Ordner auf eine "*.s" durchsuchen lassen, leider findet er nur eine "x509_crt_bundle.S" dort stehen aber keine ASM Befehle.

"Dein" Projektordner ist da auch die flasche Stelle zum Suchen. Die fuer Interrupts darunterliegende Infrastruktur, stellt der Compiler und "seine" Runtime bereit. Da musst du suchen. :)

Etwa dort, wo der Compiler seine Libraries aufbewahrt, duerfte sich auch der Startup-Code, und dessen Bestandteile finden lassen.

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über ein Jahr alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.