Forum: Mikrocontroller und Digitale Elektronik GCC-AVR: Wie Interrupt-Routine direkt in die Vektortabelle schreiben?


von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Hallo...

bei einer zeitkritischen Anwendung in C würde ich gerne ein paar 
CPU-Takte sparen und die ISR direkt in die Interrupt-Vektortabelle 
schreiben – so wie ich das von Assembler her gewohnt bin.

Geht das in C überhaupt?

von netseal (Gast)


Lesenswert?

Hallo,

google ist dein Freund:


ISR(TIMER1_OVF_vect, ISR_NAKED)
{
  PORTB |= _BV(0);  // results in SBI which does not affect SREG
  reti();
}

mehr gibt es unter:
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html

Grüße

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

netseal schrieb:
> ISR(TIMER1_OVF_vect, ISR_NAKED)

Hallo und danke für den Link!

"ISR_NAKED" hilft zwar bei Optimierungen, aber es zeigt trotzdem nicht, 
wie man eine ISR direkt in die Vektortabelle schreibt.

Hast du eine Idee?

von netseal (Gast)


Lesenswert?

Ja, doch das ist eigentlich genau das wonach du gefragt hattest.

Der andere weg ist:

Neue ASM Datei mit Vectortabelle. Die Vectortabelle muss in eine neue 
Section gebettet werden. Dann musst du ein eigenes Linker-Script 
einbinden um die Tabelle an einem Platz im Flash zu platzieren.

Achso, jetzt verstehe ich was du willst.
Du kannst deinen Vector typischerweise nicht komplett in die 
vectortabelle schreiben. Da ist kein Platz.

0x0     Reset Vector
0x04    IRQ XY Vector
0x08    IRQ z  Vector

Du musst normalerweise mit einem Jump ohne Modifikation des 
Link-Registers
in deine ISR springen:

 0x0     Reset Vector
0x04    IRQ XY IsrAdress
0x08    IRQ z  Vector

und mit einem reti beendest du den ganzen Zauber dann.
se ist doch nur'n JMP :)

Beim Arm gibt es die Möglichkeit einen FIQ (für fast) zu implementieren:

0x0     Reset Vector
0x04    IRQ XY Vector
0x08    FIQ Code Beginnt hier, nachfolgende adressen sind nicht belegt.

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Also, erstmal danke für die Geduld mit mir. ;-)

netseal schrieb:
> Achso, jetzt verstehe ich was du willst.
> Du kannst deinen Vector typischerweise nicht komplett in die
> vectortabelle schreiben. Da ist kein Platz.

Ja, genau das habe ich gemeint! Platz ist dort aber oft genug.

Bei vielen Programmen verwende ich nur einen oder zwei 
Interruptvektoren. Oft ist zwischen dem ersten und dem zweiten genügend 
Platz für ein paar Befehle. Wenn es der zweite oder überhaupt der 
einzige verwendete Interruptvektor ist, dann gibts eh kein Problem, weil 
die ISR dann (fast) beliebig lang sein kann, die nachfolgenden Adressen 
werden in diesem Fall ja nicht für weitere Interruptvektoren benötigt.

Bei den 8-Bit-AVRs stehen in der Vektortabelle sinnigerweise nicht 
einfach Vektoren, sondern echte Befehle. Normalerweise sind das 
RJMP-Befehle, aber wenns schnell gehen soll, wird man nicht erst noch 
springen wollen.

Hoffentlich hab ich mich jetzt klar genug ausgedrückt... :-)

von Karl H. (kbuchegg)


Lesenswert?

Markus Weber schrieb:


> Bei den 8-Bit-AVRs stehen in der Vektortabelle sinnigerweise nicht
> einfach Vektoren, sondern echte Befehle. Normalerweise sind das
> RJMP-Befehle, aber wenns schnell gehen soll, wird man nicht erst noch
> springen wollen.

Dann musst du in Assembler arbeiten.
Für einen Compiler ist das zuviel geforderte Flexibilität. Das kriegt er 
nicht mehr gebacken. Zumal ja erst beim Linken feststeht, ob der Platz 
in der Vektor-Tabelle überhaupt frei wäre.


Wie lange braucht der rjmp? Sind die (ich glaube es sind) 2 Takte 
wirklich das entscheidende Kriterium für deine Anwendung?

von Markus W. (Firma: guloshop.de) (m-w)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Wie lange braucht der rjmp? Sind die (ich glaube es sind) 2 Takte
> wirklich das entscheidende Kriterium für deine Anwendung?

Ja, ich mein auch, es sind 2 Takte. In dem speziellen Fall stört nicht 
die Dauer der ISR, sondern die Tatsache, dass sie dann einen für mich 
wichtigeren Interrupt mehrere Takte lang blockieren würde.

Letztlich würde es mir reichen, wenn in der Vektortabelle ein SEI vor 
dem RJMP steht. ISR_NOBLOCK macht zwar dasselbe, aber vermutlich auch 
erst nach dem Jump.

Ich werd mir da etwas anderes einfallen lassen müssen. Rein Assembler 
geht bei diesem Projekt schlecht, der Aufwand ist einfach zu hoch, es 
komplett umzukrempeln.

Auf alle Fälle danke für die Hilfe! Jetzt weiß ich wenigstens, in welche 
Richtung sich das Weiterforschen eher nicht lohnt. :-)

Markus

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.