Mir fällt noch eine ziemlich rüde Variante ein, wie man das
Retten der überflüssigen Register vermeiden könnte. Ist
aber ein ziemlicher Hack, und ich bin mir gerade nicht im
Klaren, ob das vorzeitige Freigeben der Interrupts (durch
das RETI der indirekt gerufenen ISRs) vor dem Aufräumen des
Stacks (pop r31, pop r30) nicht eventuell böse Seiteneffekte
haben könnte. Die Benutzung von rr30 für den ICALL ist ja
Pflicht, insofern ist die implizite Annahme, dass man genau
diese beiden Register retten und rückspeichern muss, wohl
gerechtfertigt.
1 | #include <avr/io.h>
|
2 | #include <avr/interrupt.h>
|
3 |
|
4 | void (*funcptr)(void);
|
5 |
|
6 | void INT0_vect(void) __attribute__((naked));
|
7 | void INT0_vect(void)
|
8 | {
|
9 | asm volatile("push r30" "\n\t"
|
10 | "push r31");
|
11 | funcptr();
|
12 | asm volatile("pop r31" "\n\t"
|
13 | "pop r30");
|
14 | }
|
15 |
|
16 | ISR(vect0)
|
17 | {
|
18 | PORTB = 0;
|
19 | }
|
20 |
|
21 | ISR(vect1)
|
22 | {
|
23 | PORTB = 0xFF;
|
24 | }
|
25 |
|
26 | int
|
27 | main(void)
|
28 | {
|
29 | funcptr = vect0;
|
30 | // initialize interrupts here
|
31 |
|
32 | for (;;) {
|
33 | if (funcptr == vect0)
|
34 | funcptr = vect1;
|
35 | else
|
36 | funcptr = vect0;
|
37 | }
|
38 | return 42;
|
39 | }
|