Hallo,
ich programmiere einen ATmega mit avr-gcc. ich möchte auf ein Interrupt
möglichst schnell reagieren. Um den Code aber einfach zu halten, will
ich vermeiden, die komplette Routine in Assembler zu schreiben.
Ist es sicher, aus einer "naked"-Routine einen Funktionsaufruf zu
starten?
AVR-Nutzer schrieb im Beitrag #4897532:
> Ist es sicher, aus einer "naked"-Routine einen Funktionsaufruf zu> starten?
Natürlich nicht!
Zumindest "SO" nicht.
Schon das PORTC = GPIOR1 ist nicht "sicher", weil das nicht ohne
Zuhilfenahme eines Registers funktioniert, welches wegen des naked ja
nicht gesichert und wiederhergestellt wird.
Du kannst aus einer ISR_NAKED eine ISR aufrufen, dann sichert der
Compiler dann die Register und du kannst beliebig Funktionen aufrufen.
Siehe dazu diesen sehr interessanten Beitrag (englisch) auf Stack
Overflow:
http://arduino.stackexchange.com/questions/8758/arduino-interruption-on-pin-change
Der Mensch bekommt genau das hin was du auch versuchst, schnellstmöglich
auf ein Port-Register zuzugreifen.
P.S.: nicht vom “Arduino“in der URL irritieren lassen, der Autor geht
tief in die Materie rein und schafft es durch modifizieren der
Interrupt-Tabelle auf eine Latenz von fünf Takten zu kommen.
Hallo,
da ist mir wohl leider zu später Stunde doch ein Fehler passiert.
Natürlich greift PORTC = GPIOR1; auf ein weiteres Register zu, dass ich
hätte sichern müssen. Meine Frage zielte daraufhin ab, in wie weit ein
Aufruf einer void-Funktion Register ändert, ohne den Ursprungszustand
wieder herzustellen.
Der Link von "Bla" scheint da wohl die wesentlichen Antworten zu bieten.
Ich werde das mal durchlesen.
AVR-Nutzer schrieb im Beitrag #4897842:
> Meine Frage zielte daraufhin ab, in wie weit ein> Aufruf einer void-Funktion Register ändert, ohne den Ursprungszustand> wieder herzustellen.
Das sagt Dir das C ABI. Die "Clobber" Register werden nicht
wiederhergestellt, d.h. es gibt Register die eine Funktion beliebeig
ändern darf. Die müsste man im ISR vorher alle sichern.
Eventuell ist C ohne "naked" effizienter - wenn der Compiler nämlich den
Inhalt der Funktion kennt und nur benötigte Register sichert.
Bla schrieb:> P.S.: nicht vom “Arduino“in der URL irritieren lassen, der Autor geht> tief in die Materie rein und schafft es durch modifizieren der> Interrupt-Tabelle auf eine Latenz von fünf Takten zu kommen.
Hallooo! Konstante Latenz! Die ist nahezu immer das kleinere Problem.
Überdies klappt selbst das nur bei den ATMegas und auch bei denen nur,
wenn sie mehr als 8K Flash haben. Denn nur dann ist genug Platz in der
Vektortabelle für zwei Befehlswörter pro Vektor.
Der Nutzen so einer Konstruktion ist überdies sowieso recht zweifelhaft.
Denn wie oben schon angemerkt, gibt es neben der konstanten
Interuptlatenz auch noch die variable.
Das fängt schon damit an, das jedes Wald- und Wiesenprogramm, selbst
wenn es sich komplett in main() abspielt, mit an Sicherheit grenzender
Wahrscheinlichkeit auch Instruktionen enthält, die mehr als nur einen
Takt zur Ausführung erfordern. Jeglicher SRAM-Zugriff z.B. mindestens
zwei Takte, jeder Datenzugriff auf den Flash drei und jedes "ret" sogar
mindestens vier. Allein damit bist du dann im ungünstigsten Fall
schonmal bei 9 Takten Latenz.
Aber es geht natürlich noch viel weiter: Jeder konkurrierende Interrupt
(jedenfalls der Teil des ISR-Codes, der exclusiv läuft) und jeder
cli()-sei()-Block erhöht die variable Latenz um eben seine eigene
Laufzeit.
Fazit: ein optimiertes Interruptsystem kann nicht daraus bestehen,
eine ISR hochgradig zu optimieren. Das ist nutzloser Bullshit.
c-hater schrieb:> Der Nutzen so einer Konstruktion ist überdies sowieso recht zweifelhaft.> Denn wie oben schon angemerkt, gibt es neben der konstanten> Interuptlatenz auch noch die variable.
Lieber c-hater! Damit hast du natürlich Recht. Es geht dem Autor
zweifelsfrei nur darum, im Rahmen einer akademischen Übung zu
demonstrieren, wo die rein technischen Grenzen des Atmega liegen.
Bestimmt ist auch dir beim sorgfältigen Lesen des Beitrags aufgefallen,
dass der Autor mehrmals sagt "hier ist genug optimiert, du kannst das
Lesen aufhören. Aber was wäre wenn..."
Außerdem ist bestimmt jedem fortgeschrittenem Entwickler klar: wenn die
Performance so bitter nötig ist, dass zu so unorthodoxen Methoden
gegriffen werden muss, ist ein Wechsel zu einem System mit
ausgefeilterem (N)VIC naheliegend, die Cortexe sind ja preislich nicht
so weit von den Atmegas weg. Da der TO in Kenntnis von "naked" ISRs ist,
zählt er bestimmt auch schon als fortgeschritten. Dadurch musste er uns
allen bewusste Konzepte wie variable Latenz und Interruptprioritäten
nicht erwähnen.
Sicherlich bist du auch schon ein fortgeschrittener Entwickler und dir
dieser Tatsachen selbstredend bewusst, so dass dein Kommentar bestimmt
nur unterhaltend gemeint war.
> Fazit: ein optimiertes Interruptsystem kann nicht daraus bestehen,> eine ISR hochgradig zu optimieren. Das ist nutzloser Bullshit.
Nein, nein, das mit der überschriebenen Vektortabelle ist nur eine
harmlose Grenzwertbetrachtung, rein interessehalber. Dein Beitrag
hingegen
> Das ist nutzloser Bullshit.
Glücklicherweise ist die Anfangsfrage des Threads ja beantwortet, damit
können wir uns zu den irrelevanteren Diskussionspunkten bewegen.
Eine eigene Frage?
Dieser Thread ist über 9 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.