Forum: Compiler & IDEs ISR während der Laufzeit "auswechseln"?


von Gerhard (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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

von Skua (Gast)


Lesenswert?

Wo die Vektoren liegen kann man mit IVSEL im Register GICR bzw. MCUCR 
beeinflussen.
Wo es hingeht bstimmen dann die BOOTSZ Fuses.

MfG
Skua

von Peter (Gast)


Lesenswert?

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

von Falk B. (falk)


Lesenswert?

@  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

von Rolf Magnus (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Gerhard (Gast)


Lesenswert?

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.

von Karl H. (kbuchegg)


Lesenswert?

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.

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.