Unterprogramm aus Interruptroutine aufrufen

Gast #2467315
Lesenswert?

Hallo,

ich weiß, das ist nach Lehrbuch sehr böse. Aber vielleicht ist es 
manchmal doch ganz sinnvoll:

Angenommen, ich benutze einen ATMEGA mit 4 USARTs. 4 gleichartige 
Sensoren mit je einer seriellen Schnittstelle liefern die Daten an, alle 
nach dem gleichen Protokoll.

Ich brauche also vier USART-Empfangsroutinen, die sich auf die Präambel 
des Protokolls synchronisieren, die Daten einsammeln, die Checksumme 
"mitrechnen" und zum Schluss, wenn alle Daten eingetroffen sind, diese 
in einen Puffer umkopieren und ein Flag setzen.

Im Hauptprogramm in der Endlosschleife wird dann nur auf die Flags 
gewartet und dann der Parser aufgerufen, der für die eigentliche 
Verarbeitung der eingetroffenen Daten zuständig ist.

Was spricht eigentlich dagegen, die ISR nicht viermal zu kopieren, 
sondern von dort aus ein Unterprogramm aufzurufen, das als einzigen 
Parameter neben dem emfangenen Zeichen einen Index bekommt, welche der 
jeweils vier Puffer- und Statusvariablen zu benutzen ist?

Wäre über eure Meinungen dankbar! Ich denke, der Code entspricht dann 
zwar nicht ganz der Lehrmeinung, ist dafür aber besser zu warten.
#2467412
Lesenswert?

Zinkchromat schrieb:
> Ich denke, der Code entspricht dann
> zwar nicht ganz der Lehrmeinung, ist dafür aber besser zu warten.

Programmiertips sind kein Gesetz, sondern nur Empfehlungen. Wenn es 
einen triftigen Grund gibt, kann man natürlich davon abweichen.

Die AVRs haben einen Nachteil, daß sie keine Interruptprioritäten haben. 
Daher bestimmt der langsamste Interrupt die Latenz aller anderen 
Interrupts. Und deshalb die Empfehlung, sämtliche Interrupts schnell zu 
halten.

Andere MCs mit Interruptprioritäten können z.B. eine Software-PWM mit 
hoher Priorität ausführen und dann kann ein UART-Interrupt sich soviel 
Zeit nehmen, wie er lustig ist. Für die hohe Priorität sind alle anderen 
Interrupts quasi nicht vorhanden, sie laufen sozusagen auf Main-Level.


Falls Du noch schnelle andere Interrupts brauchst, kannst Du die 
Funktion als Inline definieren. Sie muß dann im h-File stehen, damit 
jeder Aufruf sie expandieren kann.


Peter
Gast #2467438
Lesenswert?

Zinkchromat schrieb:
> Was spricht eigentlich dagegen, die ISR nicht viermal zu kopieren,
> sondern von dort aus ein Unterprogramm aufzurufen, das als einzigen
> Parameter neben dem emfangenen Zeichen einen Index bekommt, welche der
> jeweils vier Puffer- und Statusvariablen zu benutzen ist?

Setze doch in der jeweiligen ISR den Index/Pointer für die Verarbeitung 
der Daten vom Port und springe dann mit einem GOTO in den gemeinsam 
verwendeten Code, der mit RTI endet. Was bringt eine Subroutine da für 
Vorteile, außer der zusätzliche Stackwurschtelei?
Gast #2467448
Lesenswert?

>Im Hauptprogramm in der Endlosschleife wird dann nur auf die Flags
>gewartet und dann der Parser aufgerufen,

Die ankommenden Daten kommen ja (bedingt durch die UART) Byteweise an. 
Warum diese beim Eintreffen nur auf Prüfsumme hin aufaddieren?

Tue die doch gleich beim Eintrudeln mittels einer StateMaschine parsen 
und das fertige Ergebnis per flag der main geben.

So läufst du nur einmal über die Daten, statt:
1.) Beim Empfang für die Summe,
2.) Beim èbergeben zum main,
3.) Beim Abholen von main,
4.) Beim Parsen....
Gast #2467456
Lesenswert?

Du mußt zwei Fälle berücksichtigen:
1. Eine Interruptserviceroutine kann nicht durch eine andere 
unterbrochen werden
-> dann wird die Unterfunktion immer ohne Unterbrechung abgearbeitet und 
es sind keine Probleme zu erwarten.
2. Ein höherpriorer Interrupt kann eine andere ISR unterbrechen und die 
Unterfunktion kann von der hochprioren ISR neu aufgerufen werden, 
während sie gerade abgearbeitet wird
-> dann muß die Unterfunktion "reentrant" programmiert sein, d.h. für 
eben diesen Fall ausgelegt sein.
Beides ist möglich und erlaubt, allerdings ist Reentranz aufwendiger und 
eher fehlerträchtig.
Gast #2468250
Lesenswert?

Wenn man GCC verwendet, und eventuell auch bei anderen Compilern führt 
der Unterprogrammaufruf zu einem relativ großen Stackverbrauch und die 
ISR wird auch länger / Langsamer.  So lange man genug Flasch speicher 
frei hat, könnte man den Code eventuell noch mit Unterprogramm schreiben 
und dann per Inline dafür sorgen das der Code trotzdem einfach 4 mal 
hineinkopiert wird, und man ohne den Overhead auskommt. Wie weit das 
gleiche Problem auch bei Goto auftritt müsste man sehen. Da muss man 
dann aber aufpassen das jeweils gleichen Register gerettet werden - das 
könnte ein Problem werden !.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren