Forum: Compiler & IDEs ISR als Funktionszeiger?


von sep (Gast)


Lesenswert?

Hey,

ich habe mal eine kleine Frage. Ich möchte beispielsweise eine ISR via 
einem Funktionszeiger registrieren. Beispielsweise wie folgt.
1
typedef void (*isr)( void );
2
extern void registriereISR( void* isrVect, isr funktion );
3
// oder
4
isr[isr_Vect] = resetFunktion;
So was in der Art. Grund dafür ist einfach folgender. Der Code wird 
eventuell übersichtlicher da ich alle ISR's an einer zentralen Stelle 
registrieren kann. Die Definition der Funktionen kann jedoch an der 
Stelle erfolgen, wo spezielle Hardware definiert wird.

Folgende Vorgangsweise hatte ich mir dazu überlegt.

1. Zeiger umwandeln (also Zeiger/2 - ISR_vect)
2. Das rjmp mit anbinden für den Sprungbefehl
3. Position an dem Programmspeicher auslesen, wo der ISR_vect liegt
4. Beide Werte vergleichen
5. Ggf. neuen rjmp-Befehl mit Adresse einfügen.
6. Danach ist der Interrupt registriert und kann angesprungen werden.

Nun zu den Fragen.
Erstens, ist das praktikabel?
Zweitens, rjmp kann ja nur an die aktuelle Position + 2k bzw -2k +1 
springen. Dies würde Probleme machen, wenn das Programm größer als 4kB 
ist. Was gäbe es dort für Möglichkeiten dies zu umgehen? Einen 
zwischensprung mit rjmp? Oder die InterruptRoutine durch (ich weiß nicht 
welche) Attribute möglichst weit vorne im Programmspeicher anlegen?

Weiterhin würde ich zum testen einen ATmega88 hier haben und 
programmiert wird der mittels asm oder avr-gcc und C. Des Weiteren habe 
ich kein konkretes Einsatzbeispiel. Ich würde nur mal gerne eure 
Meinungen dazu hören und wie man das anstellen könnte.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Meine Kristallkugel sagt, daß du das auf einem AVR machen willst.

Auf der Architektur ist sowas nicht praktikabel, da die Vektortabelle 
nicht schreibbar ist -- zumindest nicht einfach vom Programmcode aus.

Die Adresse einer ISR ist also spätestens zur Lokatierzeit festgelegt. 
Du kannst allerdings jede ISR implementieren und dort einen Dispatcher 
bemühen. Daß du den Aufwand und die Codeverschwendung wirklich willst, 
sei mal dahingestellt.

Was ist daran schlecht, wenn nur ein UART-Modul an den UART-ISRs 
rumbastelt? Es obliegt diesem Modul, wie es eine UART-Kommunikation 
implementiert; somstige Module hat das nichts zu interessieren.

von sep (Gast)


Lesenswert?

Johann L. schrieb:
> Was ist daran schlecht, wenn nur ein UART-Modul an den UART-ISRs
> rumbastelt?

Wie gesagt, war das nur mal gerade eine Idee von mir. Aber zu der UART 
Sache habe ich mal ein kleines Bsp. In meinem Ausbildungsbetrieb haben 
wir Waagen programmiert. Die kamen von der Firma GSE und hatten nen 
kleinen m68k Prozessor drin. An der Seriellen Schnittstelle konnte man 
verschiedene Interpreter einstellen. Was mit dem Konzept auch relativ 
einfach möglich wäre. Nur mal als fixes Bsp.

Johann L. schrieb:
> Meine Kristallkugel sagt, daß du das auf einem AVR machen willst.

sep schrieb:
> Weiterhin würde ich zum testen einen ATmega88 hier haben und
> programmiert wird der mittels […]

Jop! ;)

von Tim (Gast)


Lesenswert?

Die Interpreter gehören aber nicht in die ISR.
In der ISR sollte nur ein FIFO befüllt werden.
Rest ist dann Sache von main().

von Oliver (Gast)


Lesenswert?

Da du, wie schon gesagt wurde, auf einem AVR die Vektortabelle nicht 
ohne Aufwand verändern kannst, müsstes du die Registrierung und 
Verwaltung in die ISR legen, und dort eine eigene Sprungatabelle 
verwalten. Von dort aus kannst du ohne Probleme über Funktionszeiger in 
erst zur Laufzeit ausgewählte Funktionen springen.

Ob das bei solch einem kleinen Prozessor überhaupt sinnvoll ist, glaube 
ich allerdings nicht.

Oliver

von Rolf Magnus (Gast)


Lesenswert?

Vor allem produziert es einen recht großen Overhead, weil du die ISR 
damit zwingst, sämtliche Register zu sichern.

von sep (Gast)


Lesenswert?

Oliver schrieb:
> Von dort aus kannst du ohne Probleme über Funktionszeiger in
> erst zur Laufzeit ausgewählte Funktionen springen.

Das hatte ich mir auch schon gedacht. Da wäre es doch toll, wenn in der 
Interrupt-Tabelle kein rjmp erfolgt, sondern ein rcall. Dann könnte man 
die Adresse von dem Interrupt-Einstiegspunkt einfach mittels pop vom 
Stack nehmen und dann in der eigenen Tabelle nach schauen. Dann hätte 
man das alles in einer ISR und könnte mit ISR_ALIAS das allen zuordnen. 
Dann einen indirekten Sprung und schon ist man in seinem 
Funktionszeiger. Bloß wie sage ich dem GCC dass er die Interrupt-Tabelle 
nicht mittels rjmp anlegt, sondern mit rcall? Das wäre dann ein bisschen 
weniger Overhead und es gehen vlt 5 - 10 Takte verloren.

Rolf Magnus schrieb:
> weil du die ISR
> damit zwingst, sämtliche Register zu sichern.

Das kapiere ich gerade nicht so wirklich. Warum zwinge ich die ISR alle 
Register zu sichern?

von sep (Gast)


Lesenswert?

Tim schrieb:
> Die Interpreter gehören aber nicht in die ISR.

Sry, hab dich gerade fast überlesen. Ich weiß, das war gerade ein 
kleines, schlechtes Bsp. Aber wie gesagt, war auch ein fixes.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

Mich dünkt du machst dir den Wolf und ne Baustelle auf wo überhaupt 
keine ist. Wizu das ganze. De ist ein AVR -Hänfling, und nicht C++ oder 
was auch immer auf nem Boliden ;-)

von Rolf Magnus (Gast)


Lesenswert?

sep schrieb:
> Oliver schrieb:
>> Von dort aus kannst du ohne Probleme über Funktionszeiger in
>> erst zur Laufzeit ausgewählte Funktionen springen.
>
> Das hatte ich mir auch schon gedacht. Da wäre es doch toll, wenn in der
> Interrupt-Tabelle kein rjmp erfolgt, sondern ein rcall.
> Dann könnte man die Adresse von dem Interrupt-Einstiegspunkt einfach
> mittels pop vom Stack nehmen und dann in der eigenen Tabelle nach
> schauen. Dann hätte man das alles in einer ISR und könnte mit ISR_ALIAS
> das allen zuordnen.

Ich verstehe irgendwie den Sinn nicht. Man braucht doch nur sehr selten 
die Möglichkeit, im laufenden Betrieb die ISR auszutauschen.

> Rolf Magnus schrieb:
>> weil du die ISR
>> damit zwingst, sämtliche Register zu sichern.
>
> Das kapiere ich gerade nicht so wirklich. Warum zwinge ich die ISR alle
> Register zu sichern?

Weil der Compiler nicht weiß, welche Register die aufgerufene Funktion 
benutzt. Und da eine ISR sicherstellen muß, daß nach ihr alles so ist 
wie vorher, ist die Konsequenz eben, daß der Compiler vorsorglich alle 
Register sichert.

von Rolf Magnus (Gast)


Lesenswert?

Hier mal ein Beispiel. Erstmal die ISR ohne den Funktionsaufruf:
1
volatile unsigned char zaehler = 0;
2
ISR (TIMER1_COMPA_vect)
3
{
4
    zaehler++;
5
}

Daraus macht mein GCC:
1
__vector_6:
2
        push __zero_reg__
3
        push r0
4
        in r0,__SREG__
5
        push r0
6
        clr __zero_reg__
7
        push r24
8
/* prologue: Signal */
9
/* frame size = 0 */
10
        lds r24,zaehler
11
        subi r24,lo8(-(1))
12
        sts zaehler,r24
13
/* epilogue start */
14
        pop r24
15
        pop r0
16
        out __SREG__,r0
17
        pop r0
18
        pop __zero_reg__
19
        reti

Woegen er daraus:
1
void (*func)(void);
2
ISR (TIMER1_COMPA_vect)
3
{
4
    func();
5
}

folgendes macht:
1
__vector_6:
2
        push __zero_reg__
3
        push r0
4
        in r0,__SREG__
5
        push r0
6
        clr __zero_reg__
7
        push r18
8
        push r19
9
        push r20
10
        push r21
11
        push r22
12
        push r23
13
        push r24
14
        push r25
15
        push r26
16
        push r27
17
        push r30
18
        push r31
19
/* prologue: Signal */
20
/* frame size = 0 */
21
        lds r30,func
22
        lds r31,(func)+1
23
        icall
24
/* epilogue start */
25
        pop r31
26
        pop r30
27
        pop r27
28
        pop r26
29
        pop r25
30
        pop r24
31
        pop r23
32
        pop r22
33
        pop r21
34
        pop r20
35
        pop r19
36
        pop r18
37
        pop r0
38
        out __SREG__,r0
39
        pop r0
40
        pop __zero_reg__
41
        reti

Er sichert also zwar nicht alle Register, aber doch erheblich mehr.

von sep (Gast)


Lesenswert?

Den Eintritt in die ISR könnte man via InlineAssembler realisieren. Laut 
GCC avr-libc gibt es ja auch Register, welche "frei" zur Verfügung 
stehen, welche man nicht aufräumen muss. Diese könnte man dafür nutzen. 
Außerdem kümmert, soweit wie ich das bei mir sehe, sich der callee darum 
die Register zu sichern. So weit wie er diese braucht.
1
00000620 <limits_isFull>:
2
 620:   df 93           push    r29
3
 622:   cf 93           push    r28
4
 624:   cd b7           in      r28, 0x3d       ; 61
5
 626:   de b7           in      r29, 0x3e       ; 62
Ich weiß nun nicht genau. Hier ist das ja ein einzelner Funktionsaufruf 
und nicht aus einer ISR. Ich werd mir das nochmal ganz genau anschaun. 
Aber wenn dem so ist, wie ich mir das Denke, dann sollte das ja kein 
Problem sein.

Johann L. schrieb:
> Wizu das ganze. De ist ein AVR -Hänfling, und nicht C++ oder
> was auch immer auf nem Boliden ;-)

Zum einen, weil ich von den kleinen AVR-Dingern ganz gut begeistert bin. 
Was die alles können. ^^ Zum Nächsten, weil ich einfach ein bisschen was 
lernen will, Möglichkeiten ausschöpfen und neue Methoden ausprobieren! 
;)
Das sind so die Gründe denke ich. Wie ich ja schon zu Anfang sagte, habe 
ich noch kein konkretes Einsatzbeispiel.


Rolf Magnus schrieb:
> Weil der Compiler nicht weiß, welche Register die aufgerufene Funktion
> benutzt.

Rolf Magnus schrieb:
> Er sichert also zwar nicht alle Register, aber doch erheblich mehr.

Das stimmt wohl. Aber wie gesagt. Der Callee sichert auch nochmal die 
Register, welche er braucht. Von den Arbeitsregistern. Also sollte es 
doch reichen SREG weg zu sichern und nach dem Austritt aus der ISR 
diesen wieder herzustellen.

von Stefan E. (sternst)


Lesenswert?

sep schrieb:
> Den Eintritt in die ISR könnte man via InlineAssembler realisieren. Laut
> GCC avr-libc gibt es ja auch Register, welche "frei" zur Verfügung
> stehen, welche man nicht aufräumen muss.

Das gilt aber nicht für Interrupts. Da musst du alle verwendeten 
Register sichern und wiederherstellen.

sep schrieb:
> Das stimmt wohl. Aber wie gesagt. Der Callee sichert auch nochmal die
> Register, welche er braucht. Von den Arbeitsregistern. Also sollte es
> doch reichen SREG weg zu sichern und nach dem Austritt aus der ISR
> diesen wieder herzustellen.

Nein, reicht nicht. Der callee sichert nämlich nicht die Register, die 
du oben als "frei" bezeichnet hast. In einer ISR sind diese aber nicht 
"frei" und daher muss die ISR selber diese zusätzlich sichern.

von sep (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Nein, reicht nicht. Der callee sichert nämlich nicht die Register, die
> du oben als "frei" bezeichnet hast.

Kann ich einer Funktion auch nicht sagen sie soll nur call-saved 
Register nutzen. Denn diese sichert ja dann der callee automatisch. Ich 
habe dazu nun nicht wirklich viel gefunden.

Aber anscheinend wird das wohl doch nichts...

Aus <http://www.mail-archive.com/avr-gcc-list@nongnu.org/msg06782.html>;
> The register set is divided into "volatile" or "call-used" registers,
> "non-volatile" or "call-saved" registers, and fixed-function registers.

von Stefan E. (sternst)


Lesenswert?

sep schrieb:
> Kann ich einer Funktion auch nicht sagen sie soll nur call-saved
> Register nutzen.

Nicht, dass ich wüsste.
Was du aber machen kannst, ist der Funktion zu sagen, dass sie eine ISR 
ist. Dann sichert sie selber alle verwendeten Register und du musst in 
deiner "Verteiler-ISR" nicht mehr vorsorglich alle call-used-Register 
sichern. Du darfst dann aber nicht vergessen, ein cli direkt hinter das 
call zu setzten, sonst riskierst du nested Interrupts (wegen dem reti am 
Ende der gerufenen Funktion). Und du hast dann wieder anderen 
zusätzlichen unnötigen Overhead in der Funktion.
Sehr fraglich, ob das alles irgendwie lohnend ist.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

sep schrieb:
> Stefan Ernst schrieb:
>> Nein, reicht nicht. Der callee sichert nämlich nicht die Register, die
>> du oben als "frei" bezeichnet hast.
>
> Kann ich einer Funktion auch nicht sagen sie soll nur call-saved
> Register nutzen. Denn diese sichert ja dann der callee automatisch. Ich
> habe dazu nun nicht wirklich viel gefunden.
>
> Aber anscheinend wird das wohl doch nichts...
>
> Aus <http://www.mail-archive.com/avr-gcc-list@nongnu.org/msg06782.html>;

Original:
http://lists.nongnu.org/archive/html/avr-gcc-list/2009-11/msg00032.html

>> The register set is divided into "volatile" or "call-used" registers,
>> "non-volatile" or "call-saved" registers, and fixed-function registers.

Mit Verlaub, das ist Unsinn.

Es gibt
- Call-clobbered Register (zB r30)
- Call-saved Register (zB r29)
- Fixe Register (zB r1)

Zudem kann man eine Variable global oder lokal an ein Register binden, 
was aber nix mit der obigen Einteilung zu tun hat. Ditto Register, in 
denen Parameter übergeben werden bzw. die nicht der Parameterübergabe 
dienen.

Ein Register volatile zu machen dient bestenfalls der eigenen 
Verwirrung: Qualifier volatile dient für Speicher, für (globale) 
Register ist er wirkungslos.

Eigentlich muss man das ABI in-und-auswendig kennen, wenn man sowas wie 
oben vor hat -- oder man landet früher oder später auf der Nase. 
Idealerweise, nachdem es eine Zeit lang funktioniert hat, so daß man 
sich den Wolf komplett woanders absucht.

von sep (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Was du aber machen kannst, ist der Funktion zu sagen, dass sie eine ISR
> ist. Dann sichert sie selber alle verwendeten Register und du musst in
> deiner "Verteiler-ISR" nicht mehr vorsorglich alle call-used-Register
> sichern.

Danke. Ich hab nun mal ein bisschen geschaut und auch was feines dazu 
gefunden. Wie folgt.
1
__attribute__( ( signal ) )
2
void foo ( void ) {
3
  // ISR
4
}
Der Assembler schaut dann folgendermaßen aus.
1
        push __zero_reg__
2
        push r0
3
        in r0,__SREG__
4
        push r0
5
        clr __zero_reg__
6
        push r24
7
        push r29
8
        push r28
Also alles erst einmal so ganz toll. Nun habe ich mir das so gedacht den 
"Verteiler Interrupt so zu definieren.
1
__attribute__( ( naked ) )
2
ISR( BADISR_vect ) {
3
  /* richtige ISR suchen */
4
}
Das sollte dann auch so weit funktionieren. Nun habe ich nur noch ein 
Problem. Woher soll die Verteiler ISR wissen, welcher ISR ausgelöst hat. 
Dazu hab ich folgede Idee.
1
00000000 <__vectors>:
2
   0:   19 c0           rjmp    .+50            ; 0x34 <__ctors_end>
3
   2:   33 c0           rjmp    .+102           ; 0x6a <__bad_interrupt>
4
[…]
So schaut ja die Tabelle für die Interrupts aus. Wenn ich das rjmp durch 
ein rcall ersetzen könnte, dann habe ich die Adresse des ausgelösten 
Interrupts auf dem Stack und könnte damit weiter arbeiten. Nur habe ich 
dazu bisher nichts gefunden. Leider.

Johann L. schrieb:
> Eigentlich muss man das ABI in-und-auswendig kennen, wenn man sowas wie
> oben vor hat

Aus genau diesem Grund frage ich ja nach. Ich weiß, dass es Leute gibt 
welche von dieser Materie sehr viel mehr Ahnung haben als ich.

Und Danke bisher für die vielen nützlichen Anstöße.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

sep schrieb:
> Stefan Ernst schrieb:
>> Was du aber machen kannst, ist der Funktion zu sagen, dass sie eine ISR
>> ist. Dann sichert sie selber alle verwendeten Register und du musst in
>> deiner "Verteiler-ISR" nicht mehr vorsorglich alle call-used-Register
>> sichern.
>
> Danke. Ich hab nun mal ein bisschen geschaut und auch was feines dazu
> gefunden. Wie folgt.
>
1
__attribute__( ( signal ) )
2
> void foo ( void ) {
3
>   // ISR
4
> }
> Der Assembler schaut dann folgendermaßen aus.
>
1
        push __zero_reg__
2
>         push r0
3
>         in r0,__SREG__
4
>         push r0
5
>         clr __zero_reg__
6
>         push r24
7
>         push r29
8
>         push r28
9
>

Was du noch brauchst (gesetzt du springst hier mit rcall/call hin) ist 
noch dir Anzahl der Register, die im ISR-Prolog auf den Stack 
geschrieben wurden. Diese ist a priori nicht bekannt. Im s-File wird ein 
Symbol dafür definiert; es wird also inline asm Hack notwendig um 
ranzukommen. Oder die Verteiler-ISR steht direkt in asm, was sinnvoller 
ist. Vielleicht ist für die ISR-Handler auch OS_task sinnvoll, leider 
fehlt dafür die Doku, du musst also durch die GCC-Quellen:

http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.c?view=markup

resp. für die GCC-Version, die du einsetzt.

Falls das ganze in einem OS eingesetzt werden soll, kann es durchaus 
sinnvoll/erforderlich sein, GCC/Binutils/libc darauf anzupassen und 
mitzuliefern, damit die Anwender ihre Applikation mit dem erweiterten 
GCC übersetzen können.

> Also alles erst einmal so ganz toll. Nun habe ich mir das so gedacht den
> "Verteiler Interrupt so zu definieren.
>
1
__attribute__( ( naked ) )
2
> ISR( BADISR_vect ) {
3
>   /* richtige ISR suchen */
4
> }
> Das sollte dann auch so weit funktionieren. Nun habe ich nur noch ein
> Problem. Woher soll die Verteiler ISR wissen, welcher ISR ausgelöst hat.
> Dazu hab ich folgede Idee.
>
1
00000000 <__vectors>:
2
>    0:   19 c0           rjmp    .+50            ; 0x34 <__ctors_end>
3
>    2:   33 c0           rjmp    .+102           ; 0x6a <__bad_interrupt>
4
> […]
> So schaut ja die Tabelle für die Interrupts aus. Wenn ich das rjmp durch
> ein rcall ersetzen könnte, dann habe ich die Adresse des ausgelösten
> Interrupts auf dem Stack und könnte damit weiter arbeiten. Nur habe ich
> dazu bisher nichts gefunden. Leider.

Die Vektortabelle steht im crt:

http://svn.savannah.nongnu.org/viewvc/trunk/avr-libc/crt1/gcrt1.S?root=avr-libc&view=markup

Vielleich ist -nostartfiles was du suchst, nebst eigenen crts.

Sollte aber auch mit ld-script gehen, indem nicht Standard-Vektortabelle 
genommen wird, sondern eine eigene Tabelle die nicht in -vectors liegt.

> Johann L. schrieb:
>> Eigentlich muss man das ABI in-und-auswendig kennen, wenn man sowas wie
>> oben vor hat
>
> Aus genau diesem Grund frage ich ja nach. Ich weiß, dass es Leute gibt
> welche von dieser Materie sehr viel mehr Ahnung haben als ich.

Das sollte nicht arrogant klingen. Ich versteh nur nicht, warum man sich 
ohne Not den ganzen Huddel aufhalsen will :-)

von sep (Gast)


Lesenswert?

Johann L. schrieb:
> Was du noch brauchst (gesetzt du springst hier mit rcall/call hin) ist
> noch dir Anzahl der Register, die im ISR-Prolog auf den Stack
> geschrieben wurden. […] Oder die Verteiler-ISR steht direkt in asm

So in der Art habe ich das dann vor. Theoretisch wird doch bei einem 
Eintritt in einen Interrupt nur die Adresse auf den Stack geschrieben, 
an welcher der Code unterbrochen wurde. Wenn ich dann aus der 
Interrupt-Tabelle mit rcall in die Verteiler-ISR springe habe ich dann 
noch die Interrupt-Nummer welche ausgelöst wurde.
Dort habe ich das dann wie folgt vor. SREG sichern und ggf. noch 
Register sichern, welche ich in der ISR brauche. Dann die 
Rücksprungadresse vom Stack nehmen (Die in dem Bereich der 
Interrupt-Tabelle liegt). Danach kann ich mit Hilfe der Adresse in 
meiner Tabelle nach schauen. Dann kommen wieder alle Register + SREG vom 
Stack gepoppt. Auch die Adresse durch den rcall wird wieder vom Stack 
genommen. Wenn ich dann aus der dynamischen ISR komme, setzt er wieder 
ganz normal fort.

Viel mehr sollte dann doch nicht auf dem Stack sein.

Johann L. schrieb:
> Falls das ganze in einem OS eingesetzt werden soll

Mal schauen, was daraus wird! ;)

Johann L. schrieb:
>> Johann L. schrieb:
>>> Eigentlich muss man das ABI in-und-auswendig kennen, wenn man sowas wie
>>> oben vor hat
>>
>> Aus genau diesem Grund frage ich ja nach. Ich weiß, dass es Leute gibt
>> welche von dieser Materie sehr viel mehr Ahnung haben als ich.
>
> Das sollte nicht arrogant klingen. Ich versteh nur nicht, warum man sich
> ohne Not den ganzen Huddel aufhalsen will :-)

Damit ich auch mal arrogant klingen kann! :p
Nein, Spaß beiseite. Zur Zeit ist es bei mir so, dass ich ein bisschen 
in der Luft hänge. Da ich Spaß an genau solchen Sachen habe, hab ich mir 
gedacht ich kann so was mal probieren. Dann mach ich kein Unfug! ^^

Danke auch für den Beitrag. Ich glaube ich habe nun erst einmal einiges 
zu lesen. Ein tolles Konzept ist das auch geworden. Wenn man sich meine 
erste Idee so anschaut. Danke also.

von Johann L. (gjlayde) Benutzerseite


Lesenswert?

sep schrieb:
> Johann L. schrieb:
>> Was du noch brauchst (gesetzt du springst hier mit rcall/call hin) ist
>> noch dir Anzahl der Register, die im ISR-Prolog auf den Stack
>> geschrieben wurden. […] Oder die Verteiler-ISR steht direkt in asm
>
> So in der Art habe ich das dann vor. Theoretisch wird doch bei einem
> Eintritt in einen Interrupt nur die Adresse auf den Stack geschrieben,
> an welcher der Code unterbrochen wurde.

Auch praktisch.

> Wenn ich dann aus der
> Interrupt-Tabelle mit rcall in die Verteiler-ISR springe habe ich dann
> noch die Interrupt-Nummer welche ausgelöst wurde.
> Dort habe ich das dann wie folgt vor. SREG sichern und ggf. noch
> Register sichern, welche ich in der ISR brauche. Dann die
> Rücksprungadresse vom Stack nehmen (Die in dem Bereich der
> Interrupt-Tabelle liegt). Danach kann ich mit Hilfe der Adresse in
> meiner Tabelle nachschauen. Dann kommen wieder alle Register + SREG vom
> Stack gepoppt. Auch die Adresse durch den rcall wird wieder vom Stack
> genommen. Wenn ich dann aus der dynamischen ISR komme, setzt er wieder
> ganz normal fort.

Problem: Um deinen Code vom Dispatcher aus zu erreichen brauchst du ein 
ICALL oder PUSH/PUSH/RET. Für beides brauchst du Register, die dir 
niemand anderes wieder herstellt als du selbst.

>>> [...]
>>
>> Das sollte nicht arrogant klingen. Ich versteh nur nicht, warum man sich
>> ohne Not den ganzen Huddel aufhalsen will :-)
>
> Damit ich auch mal arrogant klingen kann! :p
> Nein, Spaß beiseite. Zur Zeit ist es bei mir so, dass ich ein bisschen
> in der Luft hänge. Da ich Spaß an genau solchen Sachen habe, hab ich mir
> gedacht ich kann so was mal probieren. Dann mach ich kein Unfug! ^^

Forscherdrang ist ok.

von sep (Gast)


Lesenswert?

Johann L. schrieb:
> PUSH/PUSH/RET

Hmm, auf das bin ich nicht mal so direkt gekommen. Das werde ich mal im 
Hinterkopf behalten.
Ansonsten fange ich nun mal an mich bei den ldscripts und den crts 
einzuarbeiten. Vlt kann ich dann nach Ostern was präsentieren.
Also, vielen Dank euch und ein frohes Osterfest!

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.