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.
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.
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.
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
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?
>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....
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.
Ein UART vierfach zu haben ist keine allzuhohe Belastung bei hinreichend tiefer Baudrate. Die Mega-Interruprs sind nicht priorisiert und unterbrechen einander nicht.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.