Forum: Mikrocontroller und Digitale Elektronik AVR Interrupt Vector Tabelle anstatt ISR


von Rangi J. (rangi)


Lesenswert?

Hallo Forum,

ich verwende GCC (WINAVR) für verschiedene ATmegas.
Ich suche nach einer Lösung für folgendes Problem:
ich hätte gerne eine zentrale Stelle im Quellcode, an dem die 
Interrupt-Routinen zu den entsprechenden Vectoren zugeordnet werden. 
Wenn ich die ISR(...)-Schreibweise verwende, verteilt sich die 
Interrupt-Belegung über alle Software-Module. Ich benötige die zentrale 
Verwaltung, da die Interrupts abhängig von einem Sub-System (per 
Compiler-Schalter) belegt werden. Das möchte ich nicht auf die Module 
verteilen. Nicht verwendete Interrupts sollen zusammen zu einer eigenen 
ISR laufen, in der dann eine Fehlerbehandlung abläuft. "__bad_interrupt" 
wird nicht gebraucht.

Plan 1 ist fertige ISR(...) für jeden möglichen Interrupt bereit 
zuhalten und von dort als Unterfunktion in das jeweilige Software-Modul 
zu verzweigen. Dadurch brauche ich aber in der ISR einen CALL und zudem 
werden alle Register gesichert, selbst wenn in der ISR nichts gebraucht 
wird.

Plan 2 ist per #define die jeweilge Funktion in "__vector_12" 
umzudefinieren. Das ist schon ganz brauchbar, aber nicht verwendete 
Interrupts können so nicht zusammengefasst werden. Ich bräuchte für 
jeden Interrupt einen eigenen Funktionssrumpf mit einem CALL zur 
Fehlerbehandlung. Das ergibt wieder die Plan 1-Probleme.

Gibts hier schon eine bessere Lösung?

von Test (Gast)


Lesenswert?

Nimm Möglichkleit und deklariere deine Interrupt-Handler als "static 
inline" - ist die sauberste Lösung... per Makros/defines gibt es 
irgendwann Probleme bei der Fehlersuche..

von Thomas E. (thomase)


Lesenswert?

Du kannst alle Interrupts in eine ISR umleiten:
1
ISR(PCINT0_vect)
2
{
3
...
4
// Code to handle the event.
5
}
6
ISR(PCINT1_vect, ISR_ALIASOF(PCINT0_vect));

mfg.

von Oliver S. (oliverso)


Lesenswert?

Thomas Eckmann schrieb:
> Du kannst alle Interrupts in eine ISR umleiten:

Oder gleich bad_interrupt verwenden. Spart eine Menge Tipparbeit, man 
kann keine Vektoren vergessen, und es funktioniert mit jedem AtMega.

Oliver

von Thomas E. (thomase)


Lesenswert?

Oliver S. schrieb:
> Oder gleich bad_interrupt verwenden. Spart eine Menge Tipparbeit, man
> kann keine Vektoren vergessen, und es funktioniert mit jedem AtMega.

Dann funktioniert das aber nicht:

Rangi Jones schrieb:
> Nicht verwendete Interrupts sollen zusammen zu einer eigenen
> ISR laufen, in der dann eine Fehlerbehandlung abläuft.

Brauchbar ist allerdings beides nicht, da man die Interruptquelle nicht 
feststellen kann.

mfg.

von Rangi J. (rangi)


Lesenswert?

Ich denke, ich hab jetzt eine Lösung. In allen Modulen ersetzt der 
Präprozessor den Modulnamen der Funktion durch den Vektornamen. Damit 
hängen alle ISR, egal in welchen Modul, direkt in der Tabelle.
1
...
2
#define NO_INT8                         INT7_vect /* External Interrupt Request 7 */
3
#if( HW_ID == HW_ID_123 )
4
#define IO_PCINT0_ISR                   PCINT0_vect/* Pin Change Interrupt Request 0 */
5
#else
6
#define NO_INT9                         PCINT0_vect/* Pin Change Interrupt Request 0 */
7
#endif
8
...
In der folgenden Liste werden die Funktionen als ISR deklariert:
1
...
2
void __vector_8(void) __attribute__ ((signal,__INTR_ATTRS));
3
void __vector_9(void) __attribute__ ((signal,__INTR_ATTRS));
4
...
Und dann gibt es noch eine Liste mit den unbenutzten Einträgen
1
...
2
#ifdef NO_INT8
3
ISR(_VECTOR(8), ISR_ALIASOF(_VECTOR(76)));
4
#endif
5
#ifdef NO_INT9
6
ISR(_VECTOR(9), ISR_ALIASOF(_VECTOR(76)));
7
#endif
8
...
Geändert wird nur in der ersten Liste mit den #define wenn keine eigene 
ISR verwendet wird, muss hier "NO_INTxx" stehen. Die anderen Listen 
werden einmal angelegt und bleiben unverändert in unterschiedlichen 
Subprojekten.

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.