Hallo,
folgendes Problem. In meiner ISR(USART1_RX_vect) sammele ich ankommende
Zeichen und schreibe diese in einen Puffer. Bei einem bestimmten Zeichen
oder einer Zeichenkombination (z.B. <CR> <LF>) kopiere ich den Puffer in
einen global definierten String und setze ein Flag für einen Parser,
damit der angekommene Datensatz außerhalb der ISR entsprechend
ausgewertet werden kann.
Soweit ist alles ja noch Standard und nicht weiter kompliziert.
Die Schnittstelle wird hardwareseitig allerdings umgeschaltet und dient
zwei verschiedenen Zwecken (Datenaustausch mit Benutzer über USB und
Konfiguration eines Funkmoduls auf der Platine). Beide Dinge kommen
nicht gleichzeitig vor, so dass die Schnittstelle problemlos für beides
genutzt werden kann.
Jetzt brauche ich natürlich verschiedene Parser für beide Zwecke, und
auch das "Ende des Datensatzes"-Zeichen ist bei beiden Einsätzen
verschieden. Das könnte ich über zusätzliche Flags regeln, die jeweils
den einen oder anderen Parser aufrufen und die Entscheidung auf das eine
oder andere Ende-Zeichen umstellen.
Schöner wäre es allerdings, wenn ich zwei verschiedene zur Laufzeit
umschaltbare ISRs bauen könnte. Weiß jemand, ob und ggf. wie das geht?
Gerhard schrieb:> Schöner wäre es allerdings,
Das ist etwas 2-schneidig.
Natürlich ist das schöner, aber es kostet auch Resourcen. Und das
unangenehme ist: ohne einen Funktionsaufurf geht es nicht und wenn du
das tust zwingst du den Compiler dazu, bei Eintritt in die ISR erst mal
alle Register zu sichern, was wiederrum teuer sein kann im Vergleich zum
Rest
> wenn ich zwei verschiedene zur Laufzeit> umschaltbare ISRs bauen könnte. Weiß jemand, ob und ggf. wie das geht?
zb mittels einem Funktionspointer.
In der ISR rufst du die eigentliche Funktion über einen Funktionspointer
auf und extern weist du dem Funktionspointer die Funktion zu (also bei
dir eine von 2 möglichen) die benutzt werden soll um das Zeichen zu
verarbeiten.
http://www.mikrocontroller.net/articles/FAQ#Funktionszeiger
>Schöner wäre es allerdings, wenn ich zwei verschiedene zur Laufzeit>umschaltbare ISRs bauen könnte. Weiß jemand, ob und ggf. wie das geht?
Nee, das finde ich gar nicht schön! Zudem veschwendest Du Memory, weil
Du dann auch unterschidliche Puffer für die ISRs und die Parser.
mach das lieber über das Flag! Gib doch dem Flag einfach unterschidliche
Werte mit, jenachdem für welchen Parser die Message sein soll.
@ Gerhard (Gast)
>verschieden. Das könnte ich über zusätzliche Flags regeln, die jeweils>den einen oder anderen Parser aufrufen und die Entscheidung auf das eine>oder andere Ende-Zeichen umstellen.
Was bitte schön ist an einer einfachen if() Abfrage so kompliziert? Da
kann man die beiden verschiedenen ISRs reinpacken. Einfach und schnell.
>Schöner wäre es allerdings, wenn ich zwei verschiedene zur Laufzeit>umschaltbare ISRs bauen könnte.
Was ist daran schöner? Akademischer Firlefanz.
> Weiß jemand, ob und ggf. wie das geht?
Dann wäre es sinnvoll zu sagen, um welchen Prozessor es geht. Jaja, ich
rate mal, es ist ein AVR. NEIN, geht nicht, weil die ISR VEktoren fest
im Flash liegen, und ein Überschreiben per SPM sinnfrei ist.
MFG
Falk
Karl heinz Buchegger schrieb:> Gerhard schrieb:>>> Schöner wäre es allerdings,>> Das ist etwas 2-schneidig.> Natürlich ist das schöner, aber es kostet auch Resourcen. Und das> unangenehme ist: ohne einen Funktionsaufurf geht es nicht und wenn du> das tust zwingst du den Compiler dazu, bei Eintritt in die ISR erst mal> alle Register zu sichern, was wiederrum teuer sein kann im Vergleich zum> Rest
Man könnte die Funktionen mit __attribute__((always_inline))
deklarieren. Dann kann man den Code immer noch sauber auf zwei
Funktionen aufteilen, hat aber den Overhead nicht.
Ich bezweifle aber mal den Sinn der Aktion. Ein Parser hat in einer ISR
eigentlich nichts verloren. Die sollte so kurz wie möglich sein, und die
eigentliche Arbeit gehört ins Hauptprogramm, wo man das auch sauber über
zwei getrennte Funktionen regeln kann, ohne da noch einen besonderen
Overhead zu bekommen.
Karl heinz Buchegger schrieb:>> wenn ich zwei verschiedene zur Laufzeit>> umschaltbare ISRs bauen könnte. Weiß jemand, ob und ggf. wie das geht?>> zb mittels einem Funktionspointer.
Das hat aber auch keinen wirklichen Vorteil gegenüber einem Flag, über
das mit einer einfachen Verzweigung zwischen den beiden Funktionen
gewählt wird.
Gerhard schrieb:> Jetzt brauche ich natürlich verschiedene Parser für beide Zwecke, und> auch das "Ende des Datensatzes"-Zeichen ist bei beiden Einsätzen> verschieden.
Nun, der Parser hat ja mit dem Interrupt nichts zu tun, den rufst Du ja
im Main auf. Und das wird ja aus seinem Kontext heraus wissen, welchen
es aufrufen muß. Es hat ja auch die Hardware umgeschaltet.
Der Interrupt macht nur die FIFO, ist also immer gleich. Er kann ja
beide Endezeichen testen und das Main fragt dann das zutreffende Flag
ab.
Peter
Gut, ihr habt mich überzeugt, ich mache das über Flags.
Wegen der "Schönheit": Ein über Flags umschaltbarer Parser zerschießt
mir halt meine schöne Modularisierung des Programms und verschlechtert
die spätere Verständlichkeit und Lesbarkeit.
Gerhard schrieb:> Gut, ihr habt mich überzeugt, ich mache das über Flags.>> Wegen der "Schönheit": Ein über Flags umschaltbarer Parser zerschießt> mir halt meine schöne Modularisierung des Programms und verschlechtert> die spätere Verständlichkeit und Lesbarkeit.
Mir ist nicht ganz klar, was du da immer mit deinem Parser hast.
Der eigentliche Parser ist doch ausserhalb der ISR. In der ISR geht es
doch nur darum Zeichen zu sammeln und beim Erreichen des End-of-Input
Zeichens der Hauptschleife eine Benachrichtigung zu geben.
Dann mach es doch so, dass du der ISR das gewünschte End-Of-Input
Zeichen extern zur Verfügung stellst. Beim Kontextwechsel wird dieses
ausgetauscht und die ISR macht weiterhin was sie tut: Zeichen sammeln,
bis das vorgegebene End-Of-Input Zeichen eintrudelt.