Forum: Mikrocontroller und Digitale Elektronik esp32c3 & interrupt service routine


von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

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?

: Bearbeitet durch User
von Stephan S. (uxdx)


Lesenswert?

Jan H. schrieb:
> bei einem ESP32

welcher ESP32?

von Jan H. (janiiix3)


Lesenswert?

UPS. Habe es aktualisiert.
Es geht speziell um den C3.
Danke für den Hinweis.

von Motopick (motopick)


Lesenswert?

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...

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

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?

von Rainer W. (rawi)


Lesenswert?

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.

von Jan H. (janiiix3)


Lesenswert?

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?

von Rainer W. (rawi)


Lesenswert?

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.

von Jan H. (janiiix3)


Lesenswert?

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?

von Motopick (motopick)


Lesenswert?

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

Ei sischa.

Edith: Wenn man sie geschickterweise im RAM haelt.

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

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
};

: Bearbeitet durch User
von Motopick (motopick)


Lesenswert?

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.

: Bearbeitet durch User
von Sherlock 🕵🏽‍♂️ (rubbel-die-katz)


Lesenswert?

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".

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

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 ;)

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

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.

von Jan H. (janiiix3)


Angehängte Dateien:

Lesenswert?

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.

Ich habe jetzt doch die passende Datei gefunden. Habe sie mal mit 
hochgeladen.

von Hannes J. (Firma: _⌨_) (pnuebergang)


Lesenswert?

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.

von Motopick (motopick)


Lesenswert?

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.

von Jan H. (janiiix3)


Lesenswert?

Vielen Dank euch. Werde weiter forschen.

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.