Forum: Mikrocontroller und Digitale Elektronik Unterprogramm aus Interruptroutine aufrufen


von Zinkchromat (Gast)


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.
von (prx) A. K. (prx)


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?

Nichts.

Wenn ein Lehrbuch behauptet, das sei böse, dann verbrennen.
von Purzel H. (hacky)


Lesenswert?

Es geht ja nicht drum, ob sich der Code unterscheidet. Die Uarts 
unterscheiden sich nur durch die Daten. Also fuer jedes UART einen 
eignenen Datensatz und gut ist.
von Peter D. (peda)


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
von Wolfgang (Gast)


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?
von Matthias L. (Gast)


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....
von Dosmo (Gast)


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.
von Purzel H. (hacky)


Lesenswert?

Ein UART vierfach zu haben ist keine allzuhohe Belastung bei hinreichend 
tiefer Baudrate. Die Mega-Interruprs sind nicht priorisiert und 
unterbrechen einander nicht.
von Ulrich (Gast)


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