Hallo zusammen, bin gerade dabei die Interrupt Latenzzeit eines Standard Mikrocontrollers wie dem ATmega8 oder vergleichbarem zu berechnen. Wo verstecken sich denn die Hinweise auf die Interrupt Latenzzeit in den Datenblättern ? Scheine den richtigen Suchbegriff noch nicht gefunden zu haben. Kann man davon ausgehen, dass im Vergleich zu einem internen Interrupt, bei einem extern ausgelösten lediglich die Takte für die Signalsynchronisierung dazu kommen (ca. 2-4 Takte im Normalfall) ? Grüße Uwe
UweLoh schrieb: > Wo verstecken sich denn die Hinweise auf die Interrupt Latenzzeit in den > Datenblättern ? Ich nehme mal an, du meinst mit "Latenzzeit" die Zeit, die zwischen dem Ereignis und der Ausführung der eigentlichen Interrupt-Routine vergeht. Die Zeit ist nicht fest sondern von mehreren Faktoren - wie z.B. dem Code und dem Compiler abhängig. Vor dem Anspringen des Interrupts werden die notwendigen Register gesichtert. Die Befehle sind "push" (sichern) und "pop" (zurücklesen) Wenn viele Register gesichtert werden müssen, dauert es natürlich länger.
UweLoh schrieb: > den richtigen Suchbegriff "atmega interrupt latency" bringt gut 30.000 Beiträge. Im Datenblatt unter "Interrupt Response Time" findet man auch Hinweise. Hier im Forum "Wie viele Taktzyklen benötigt ein Interruptaufruf beim AVR INT0 (Assembler)".
UweLoh schrieb: > Scheine den richtigen Suchbegriff noch nicht gefunden zu haben. > Kann man davon ausgehen, dass im Vergleich zu einem internen Interrupt, > bei einem extern ausgelösten lediglich die Takte für die > Signalsynchronisierung dazu kommen (ca. 2-4 Takte im Normalfall) ? Was meinst du mit "internen Interrupt"?
Rolf M. schrieb: > Was meinst du mit "internen Interrupt"? Vermutlich einen, der nicht extern ist? Sowas wie Zählerüberlauf oder oder odet
Rolf M. schrieb: > Was meinst du mit "internen Interrupt"? INT0, INT1, PCINT0, PCINT1 usw. sind externe Interrupt, z.B. die TimerN mit ihren unterschiedlichen Interruptquellen wären dann interne Interrupt.
UweLoh schrieb: > Interrupt Latenzzeit eines Standard > Mikrocontrollers wie dem ATmega8 Sobald Du mehr als 1 Interrupt hast wird diese Berechnung eher akedemisch. Denn die maximale Latenz verlängert sich um die Laufzeit der vorher (bzw. gleichzeitig) aufretretenen Interrupt Handler. Daher lautet bei AVR die Device: Interrupts so schnell wie möglich abarbeiten.
Wenn du die Abarbeitungszeit wissen willst schalt ne LED an und aus in den Routinen und Messe mit dem Oszi doch mal die Zeiten.....
Karl M. schrieb: > Rolf M. schrieb: >> Was meinst du mit "internen Interrupt"? > > INT0, INT1, PCINT0, PCINT1 usw. sind externe Interrupt, > z.B. die TimerN mit ihren unterschiedlichen Interruptquellen wären dann > interne Interrupt. Und warum sollte da ein Unterschied in der Interrupt-Latenz sein? Für mich sind beide aus Sicht des Interrupt-Handling das gleiche: Durch Peripherie-Einheiten ausgelöste Interrupts. Ob das jetzt ein Timer oder ein I/O-Port ist, spielt doch gar keine Rolle.
Was mir immer hilft ist schlicht: messen. In der ISR mit Pin wackeln. Externen Int über Pin auslösen, der von der Mainloop gewackelt wird. Und dann mit dem LogicAnalyser beobachten. Kosten <10€ + 0€ für sigrok/pulseview. Wenn z.B. alle ISR's den selben Pin wackeln lassen, dann kann man mit dem "PWM-Decoder" die ISR-Auslastung in % einfach anzeigen lassen.
Stefan S. schrieb: > Vor dem Anspringen des Interrupts werden > die notwendigen Register gesichtert. Das ist gleich doppelt falsch. Denn natürlich wird nicht der Interrupt angesprungen, sondern die Interrupt Service-Routine (ISR). Und Register werden nicht vor dem Aufruf der ISR gesichert, sondern in der ISR. Das einzige was automatisch auf den Stack geht, ist der PC. So wie bei einem normalen Unterprogrammaufruf auch.
Also. Ein AVR beendet die gradige Instruktion, welche 1 oder 2 takte dauern kann. Dann kommt push(PC) & call(ISR). In der ISR macht man als Minimum noch ein push(Status) und wenn der Compiler nichts kann, wird noch ein push(alle Register) durchgefuehrt. Ich glaub der AVR Siumlator kann auch Interrupts simulieren.
Hi Zwölf M. schrieb: > In der ISR macht man als Minimum noch ein push(Status) Im Normalfall ja, wenn keine Statusregister verändert werden, kann man Sich Das sparen. Z.B. setze ich in der WatchDog-ISR nur ein Flag
1 | sbr rFlag,(1<<fWatchDog) |
2 | reti |
Wobei rFlag (Register mit dem Namen Flag) diverse Flags enthält. Das fWatchDog (Flag mit dem Namen WatchDog) ist eine Bitposition 0...7 und wird in der ISR nur gesetzt. Im Hauptprogramm wird dann darauf reagiert und das Flag wieder entfernt (und der WatchDog-ISR erneut scharf geschaltet, sonst gibt's beim nächsten Wachhund-Biss einen Reset). Aber Ja, Du hast Recht: Wenn man sich in der ISR ein Register des Hauptprogramm versaut, sind die Fehler vielfältig, bösartig unregelmäßig und kaum zu finden :) AUf dem 80286 (unter DOS mit DEBUG) wurde großzügig gepushed und gepoped, auf dem ATtiny muß ich aber manch Mal auf die Laufzeit achten und nur sichern, was wirklich nötig ist. MfG
Jim M. schrieb: > Sobald Du mehr als 1 Interrupt hast wird diese Berechnung eher > akedemisch. Nein. Man muss einfach nur wissen, wie man das richtig berechnet... > Denn die maximale Latenz verlängert sich um die Laufzeit der vorher > (bzw. gleichzeitig) aufretretenen Interrupt Handler. Nein. Sie verlängert sich nur um jedes Teil, was EXKLUSIV läuft. Das ist nicht notwendigerweise die komplette ISR, sondern sind im Extremfall nur 5 Takte. Nämlich der allfällige ISR-Entry-Overhead (im günstigsten Fall halt 4 Takte) und die Zeit, für eine sei-Anweisung auf der Adresse des Interrupt-Vectors benötigt wird, also ein weiterer Takt. Bei AVR8 mit sehr viel Flash (>128k) oder AVRs mit externem RAM können da noch weitere Takte hinzukommen, im worst case (22-Bit PC und Stack im externen RAM) sind das nochmal 5 Extra-Takte für den ISR-Entry-Overhead, also dann insgesamt 10 statt 5. > Daher lautet bei AVR die Device: Interrupts so schnell wie möglich > abarbeiten. Unsinn, das scheint nur unwissenden C-lern so... Tatsächlich ist es so: jegliche Instanz von exklusiv ausgeführtem Code sollte so kurz wie möglich sein. Exklusiv ausgeführter Code sind aber erstens nicht nur ISRs (sondern auch jeglicher mit cli/sei oder hochsprachentechnischen Verwandten geklammerter Kram) und zweitens nicht zwingend komplette ISRs, sondern nur der Teil dieser bis zum ersten sei... Natürlich ist es selten sinnvoll, die ISR gleich mit einem sei zu beginnen, aber es ist sehr oft sinnvoll, kurz nach dem Beginn ein sei einzufügen. Nämlich genau dann, wenn alles erledigt ist, was man sinnvollerweise erledigen sollte, solange der eigene Code noch exklusiv läuft. Und wenn man das immer so macht, ergeben sich komplette Anwendungen, die nur aus solcherart konstruierten ISRs bestehen. Kein dümmliches, sinnlos Rechenzeit und Energie verbrauchendes Polling in main() ist dann mehr nötig. main() dient ausschließlich dazu, freie Rechenzeit "wahrzunehmen" und unmittelbar dazu zu nutzen, das System einzuschläfern. Wozu soll es auch laufen, wenn es keine Änderung des Status geben kann, da ja kein Ereignis eingetreten ist, was irgendwas am Status ändern könnte? Du musst noch viel lernen...
Zwölf M. schrieb: > Also. Ein AVR beendet die gradige Instruktion, welche 1 oder 2 takte > dauern kann. Oder mehr. Die längste Instruktion ist je nach Größe des Flash 4 oder 5 Taktzyklen lang. Beim Atmega8 sind es 4, z.B. bei RET. > Dann kommt push(PC) & call(ISR). Eher so: push(PC) CLI call(Interrupt-Vektor) und in dem Interrupt-Vektor-Eintrag steht dann in der Regel ein RJMP ISR. Was noch gar nicht erwähnt wurde: Wenn der Prozessor gerade im Sleep-Modus ist und durch den Interrupt aufgeweckt wird, verlängert sich die Reaktionszeit. > In der ISR macht man als Minimum noch ein push(Status) Kann man nicht. Man kann nur die Register r1 bis r15 pushen. Also muss man erst eins davon sichern, dann das SREG da rein kopieren, dann das Register nochmal pushen. Später dann vor Verlassen der ISR das umgekehrte. > und wenn der Compiler nichts kann, wird noch ein push(alle Register) > durchgefuehrt. Oder wenn man dem Compiler keine andere Wahl lässt, z.B. weil man in der ISR eine Funktion aufruft, deren Inhalt der Compiler an der Stelle nicht kennt. Dann ist er gezwungen, prophylaktisch alle Register zu sichern. c-hater schrieb: > Tatsächlich ist es so: jegliche Instanz von exklusiv ausgeführtem Code > sollte so kurz wie möglich sein. Exklusiv ausgeführter Code sind aber > erstens nicht nur ISRs (sondern auch jeglicher mit cli/sei oder > hochsprachentechnischen Verwandten geklammerter Kram) und zweitens nicht > zwingend komplette ISRs, sondern nur der Teil dieser bis zum ersten > sei... Auch nach dem SEI blockiert die ISR weiterhin das Hauptprogramm. Das erklärt dann auch, warum du unbedingt das komplette Programm in die ISRs stecken willst. Jeglichen anderen Weg hast du dir ja verbaut. > Natürlich ist es selten sinnvoll, die ISR gleich mit einem sei zu > beginnen, aber es ist sehr oft sinnvoll, kurz nach dem Beginn ein sei > einzufügen. Nämlich genau dann, wenn alles erledigt ist, was man > sinnvollerweise erledigen sollte, solange der eigene Code noch exklusiv > läuft. Das ist aber fast immer auch die Stelle, an der die ISR am besten komplett zu ende sein sollte. Somit erübrigt sich das SEI dann. > Und wenn man das immer so macht, ergeben sich komplette Anwendungen, die > nur aus solcherart konstruierten ISRs bestehen. Unnötig komplex und schlecht wartbar. Schlecht überschaubare Stackgröße und im Extremfall (Interrupt wird schneller ausgelöst als ISR ausgeführt werden kann) Stack-Overflow. Mehrwert: Praktisch keiner. > Kein dümmliches, sinnlos Rechenzeit und Energie verbrauchendes Polling in > main() ist dann mehr nötig. ? > main() dient ausschließlich dazu, freie Rechenzeit "wahrzunehmen" und > unmittelbar dazu zu nutzen, das System einzuschläfern. Wozu soll es auch > laufen, wenn es keine Änderung des Status geben kann, da ja kein > Ereignis eingetreten ist, was irgendwas am Status ändern könnte? Muss es nicht. Das hat aber nichts damit zu tun, ob man nun die ISRs kurz hält oder das ganze Programm da reinstopft.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.