Hallo, kurze Frage. Ich habe 3 ISR Routinen. Beispiel. Eine wird getriggert, springt dort rein. Von dort aus mache ich eine Funktion (kein Inline). Springt er dann in die Funktion. Könnte er, wenn in der Zeit ein anderer ISR getriggert wird, dort reinspringen, oder ist das in der Zeit blockiert, solange ein ISR nicht verlassen wurde (Flag nicht gelöscht). Geht um AVRs Mega, Tiny
Der Interrupt ist solang blockiert, bis Du die Interruptroutine wieder verläßt oder den Interrupt wieder einschaltest. Achtung! die ISR sollte möglichst schnell abgearbeitet werden, beim UART z.b schreibst Du das ankommende Byte in nen globalen Ringpuffer und verläßt die Routine wieder. die weitere Bearbeitung sollte dann in der Hauptschleife erfolgen. mfg
Noppi schrieb: > Könnte er, wenn in der Zeit ein anderer ISR getriggert wird, dort > reinspringen, oder ist das in der Zeit blockiert, solange ein ISR nicht > verlassen wurde (Flag nicht gelöscht). Ob die ISR verlassen wurde, spielt keine Rolle. Entscheidend ist, dass der Interrupt freigegeben ist. Beim Einsprung in eine ISR werden erstmal weitere gesperrt und spätestens beim RTI wieder erlaubt. Freigabe innerhalb der ISR ist aber genauso möglich.
Genau!! Mach die Interruptroutine erstmal als Normalroutine. Steppe sie dann bitte im Debugger sorgfälig durch, auch die von ihr aufgerufene Funktion, bevor Du sie als ISR definierst! Ein Bug in ner ISR ist ekelig! mfg
Noppi schrieb: > Könnte > er, wenn in der Zeit ein anderer ISR getriggert wird, dort reinspringen, > oder ist das in der Zeit blockiert, solange ein ISR nicht verlassen > wurde Im Normalfall sind andere Interrupts gesperrt. Jedoch gibt es die Möglichkeit, auch auf einem AVR "Nested Interrutps" zu nutzen.
:
Bearbeitet durch User
my2ct schrieb: > Freigabe > innerhalb der ISR ist aber genauso möglich. Das Problem ist aber, daß im Gegensatz zu CPUs mit echten Interruptleveln auch der ursprüngliche Interrupt wieder erlaubt wird und er sich selber unterbrechen kann, bis zum Stacküberlauf. Daher macht man das beim AVR für professionelle Anwendungen nicht. Es ist einfach zu gefährlich (den Drachen kitzeln).
Wenn die basagte Routine aber schon abgearbeitet wird, wird der Interrupt dazu führen, dass sie sich selbst unterbricht. Such mal nach Reentrant. Diese Eigenschaft muss sie dann haben, sonst gibt es die tollsten Nebeneffekte.
Peter D. schrieb: > Daher macht man das beim AVR für professionelle Anwendungen nicht. > Es ist einfach zu gefährlich (den Drachen kitzeln). Ich würde es so sagen: es gibt nur 2 Arten von Menschen, die das tun. 1. blutige Anfänger, die es nicht besser wissen und meinen, so ihr "Problem" lösen zu können. und 2. erfahrene Profis, die möglicherweise leider gezwungen sind, das zu tun und die potentiellen Gefahren ganz genau kennen. Alle anderen kommen mit 1 aktiven Interrupt zurecht. Interrupt schrieb: > Wenn die basagte Routine aber schon abgearbeitet wird, wird der > Interrupt dazu führen, dass sie sich selbst unterbricht. Das Nesting von Interrupts wird eigentlich nur über SEI wieder freigegeben: https://ucexperiment.wordpress.com/2013/05/20/nested-interrupts/ Und deshalb kann ein Interrupt sich nicht selber unterbrechen, weil es dafür ja nur 1 Quelle gibt und dieses Flag schon aktiv ist. Extrem wäre es natürlich, zusätzlich zum Aktivieren des globalen Enables auch gleich das auslösende Interruptflag zurückzusetzen. Aber dann kann man sich auch gleich ins Knie schießen, das tut sicher auch weh!
> Und deshalb kann ein Interrupt sich nicht selber unterbrechen, weil es > dafür ja nur 1 Quelle gibt und dieses Flag schon aktiv ist. Extrem wäre > es natürlich, zusätzlich zum Aktivieren des globalen Enables auch gleich > das auslösende Interruptflag zurückzusetzen. Aber dann kann man sich > auch gleich ins Knie schießen, das tut sicher auch weh! Also lt. DaBla des 328p passiert das Löschen des Flags automatisch beim Eintritt in die ISR (bzw. beim Aufruf des Vektors): "Bit 1 – INTF1: External Interrupt Flag 1 When an edge or logic change on the INT1 pin triggers an interrupt request, INTF1 will be set. If the I-bit in SREG and the INT1 bit in EIMSK are set, the MCU will jump to the corresponding Interrupt Vector. The flag is cleared when the interrupt routine is executed. Alternatively, the flag can be cleared by writing '1' to it. This flag is always cleared when INT1 is configured as a level interrupt." Wenn also die ISR(..., NO_BLOCK) deklariert wurde, kann der Interrupt in der ISR erneut ausgelöst werden und die ISR wird auch erneut aufgerufen, oder?
Da haben sich viele Autoren so viel Mühe mit dem Wiki hier im Forum gegeben, und niemand liest es. https://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Allgemeines_.C3.BCber_die_Interrupt-Abarbeitung Ingo E. schrieb: > lso lt. DaBla des 328p passiert das Löschen des Flags automatisch beim > Eintritt in die ISR (bzw. beim Aufruf des Vektors): Das ist bei den meisten Interruptquellen so, aber nicht bei allen. Oliver
Ingo E. schrieb: > Also lt. DaBla des 328p passiert das Löschen des Flags automatisch beim > Eintritt in die ISR (bzw. beim Aufruf des Vektors): > "Bit 1 – INTF1: External Interrupt Flag 1 Hier war aber kein bestimmter Interrupt angegeben. Z.B. Schnittstellen (UART, SPI, I2C, CAN) löschen das Flag nicht. Ingo E. schrieb: > Wenn also die ISR(..., NO_BLOCK) deklariert wurde Dann schmiert bei Schnittstellen der AVR gnadenlos ab.
Nicht jammern.... oder immer das Schlimmste annehmen. Die Lösung hat sogar irgendwann mal ihren Namen erhalten. Reentrance, oder Wiedereintrittsfähig.
Ingo E. schrieb: > Wenn also die ISR(..., NO_BLOCK) deklariert wurde, kann der Interrupt in > der ISR erneut ausgelöst werden und die ISR wird auch erneut aufgerufen, > oder? Ja, wie gesagt: in bestimmten Fällen. Beim Timer geht das, weil ja der Aufruf der ISR an sich schon das gewünschte Ergebnis ist. Bei der seriellen Schnitte wird das Flag aber sinnvollerweise erst beim Lesen des UDR gelöscht. Man muss sich also das Datenblatt genau anschauen. Und auch die Ressourcennutzung in den möglicherweise betroffenen ISR. EAF schrieb: > Die Lösung hat sogar irgendwann mal ihren Namen erhalten. > Reentrance, oder Wiedereintrittsfähig. Ja, war auch schon im Gespräch. Ich bin mir aber ziemlich sicher, dass ein Anfänger so eine Funktion, die vollständig reentrant ist, nicht hinbekommt. Besonders, weil ja solche ISR gerne mit Hardware zu tun haben, die nur 1x vorhanden ist. Und wenn was nur einmal da ist und ein anderer nimmt es zwischendurch in die Finger, dann gibt das beliebig zufälige Effekte: nehmen wir nur mal an, die erste ISR liest einen 16-Bit-Zähler aus, also Low- und High-Byte (im Schattenregister) nacheinander. Aber dann kommt nach dem Auslesen des Low-Bytes die zweite ISR und liest diesen Timer via Low- und High-Byte ein paar µs später auch aus, überschreibt dabei den Wert im Schattenregister(!!) und danach geht es zurück zur ersten ISR, die dann das anstelle "ihres" High-Bytes das der zweiten ISR nochmal ausliest ... rumpeldipumpel, wenn zwischendurch ein Überlauf im High-Byte stattgefunden hat... Drehen wir den Spieß aber einfach mal um: ich halte einfach die Interruptroutinen so kurz, dass es sich gar nicht lohnt, sie extra noch zu unterbrechen.
:
Bearbeitet durch Moderator
Der AVR sollte das bei korrekt geschriebenen ISRs können, auch wenn man das möglicherweise beim Start jeder ISR explizit erlauben muß, jedenfalls so lange bis der Stack voll ist (danach zerschießt man sich den RAM-Inhalt). Es geht aber nicht bei jedem Interrupt, sondern nur bei solchen, die nicht dauerhaft aktiv sein können. Sonst erzeugt man eine sehr schnell laufende Endlosschleife und der RAM-Inhalt wird quasi sofort geschreddert. Es geht auch nicht besonders gut, wenn man in den ISR Daten verarbeitet, also beispielsweise ein vom UART empfangenes Zeichen ins RAM schreibt. Solche Routinen sollten ohne Unterbrechung durchlaufen. Ansonsten würde ein zweiter Aufruf zu Problemen führen wenn die erste Instanz lange genug unterbrochen wurde.
Lothar M. schrieb: > Und deshalb kann ein Interrupt sich nicht selber unterbrechen, weil es > dafür ja nur 1 Quelle gibt und dieses Flag schon aktiv ist. Doch, das geht. Ich möchte ein Beispiel zeigen. Ein Pulsgenerator erzeugt mittels Timer-IRQ (192k/s) einen Impuls bei Überlauf eines Akkumulators (DDS-Prinzip). Dass hier kein Aufruf ausgelassen werden darf leuchtet ein. Abhängig davon, ob ein Puls erzeugt wurde, wird eine neue Berechnung des Frequenzwortes fällig. Es werden zwei Differenzen gebildet, eine Entscheidung getroffen, eine Multiplikation durchgeführt, eine Wurzel gezogen und eine Begrenzung (16 Bit) durchgeführt. Abgesehen von der Begrenzung jeweils in 32 Bit. Die Berechnung dauert ca. 350 Takte (Wenn ich mich nicht irre - ich müsste nochmal nachzählen) und kann nicht losgelöst vom IRQ in der Main passieren, da hier noch weitere Dinge passieren, die eine Berechnung nur noch weiter hinauszögern. Außerdem dürfen IRQs nicht verboten werden, was die Übergabe neuer Werte erschweren würde. Der Timer-IRQ wird alle 96 Takte ausgelöst, die Pulsausgabe benötigt ca. 30 Takte, sofern ein Puls ausgegeben wird. Sonst ist sie nur halb so lang. Nach dieser Ausgabe wird die Routine wieder unterbrechbar. Eine Verriegelung sorgt nun dafür, dass immer nur eine Berechnung in Arbeit ist. Erst wenn die Berechnung abgeschlossen wurde, darf ein weiterer IRQ eine neue Berechnung starten. Dieser Mechanismus darf auch durch andere IRQs nicht gestört werden, alles weitere läuft deshalb in der main per polling. Viel ist da aber auch nicht mehr. Gesteuert wird der ganze Apparat über die UART, auf welcher ein Kommandointerpreter Befehle entgegen nimmt. Bei voller Geschindigkeit mit 192000 Pulsen/s merkt man bei einem bestimmten Kommando schon die geringere verbleibende Rechenleistung. Dabei bleiben alle 3 bis 4 IRQs nur eine Hand voll Takte für die Main übrig. Das Überspringen der Berechnungen für einige Impulse ist bei hohen Pulsraten akzeptabel. Ich möchte noch ein weiteres Beispiel zur Unterbrechung von ISRs durch andere IRQs aus meinem Fundus zeigen: Ein Timer, welcher einen Hardware-Impuls ausgibt. Mit diesem Impuls werden Daten des SPI Jitterfrei an die parallelen Ausgänge eines Schieberegisters übernommen. Außerdem wird durch die Hardware eine AD-Wandlung angestoßen. Weiterhin erzeugt dieses Timerereignis einen IRQ, welcher dafür sorgt, dass neue Daten per SPI in das Schieberegister gelegt werden. Dieser IRQ unterbricht nun die ISR des ADC, welche die Daten aus der Wandlung des vorherigen Ereignisses verarbeitet. Die in der Timer-ISR erzeugten Daten werden in der ADC-ISR benötigt, weshalb absolute Synchronität notwendig ist. Also wieder kein Fall für die Main. Allerdings ist hier noch genug restliche Zeit für diese übrig, auch wenn auch hier schon wieder mit ~75k/s gearbeitet wird. Gruß Jobst
Noppi schrieb: > Von dort aus mache > ich eine Funktion (kein Inline). Erst noch machen? Die Funktion ist sicherlich schon vorhanden und soll aufgerufen werden. Kann man machen und man kann die Interrupts auch verschachtelt ausführen lassen, allen Unkenrufen hier zum Trotz. Das Hauptargument gegen einen Funktionsaufruf aus einer ISR bei einem AVR8 ist für mich die zusätzliche Latenz, die durch das Sichern und Restaurieren (push/pop) aller CPU-Register auftritt. Da beim Eintritt in die ISR nicht überprüft wird, welche Register die aufgerufene Funktion verwendet, müssen eben alle Register gesichert werden. Das kostet richtig Zeit.
Hallo, ich möchte kurz einen Teil aus einer PDF zeigen, deren URL nicht mehr verfügbar ist. Tritt ein Interrupt auf, dann wird das I-Bit im Statusregister gelöscht und alle anderen Interrupts gesperrt. Dieses I-Bit wird wieder gesetzt, sobald der aufgetretene Interrupt abgearbeitet wurde und der Befehl RETI zur Rückkehr an die Stelle im Programm zum Zeitpunkt des Aufrufes ausgeführt wurde. Wird ein Interrupt-Flags gesetzt, dann bleibt es bis zur Abarbeitung oder Löschung durch das Programm erhalten. Treten mehrere Interrupts auf, werden sie nacheinander abgearbeitet. Da einem externen Interrupt kein Flag zugeordnet ist, bleibt dieser nur solange in Evidenz, solange jene Bedingung besteht, die zu seinem Auftreten geführt hat. Tritt ein INT auf, der auch freigegeben ist z.B durch u.a Register GIMSK, werden wie beim Befehl CLI (Global Interrupt Disable) alle weiteren INT gesperrt und durch RETI wieder freigegeben (wie RET + SEI gleichzeitig). Genaueres im Datenblatt. Gruß Carsten
Carsten-Peter C. schrieb: > Hallo, ich möchte kurz einen Teil aus einer PDF zeigen, deren URL nicht > mehr verfügbar ist. Sehe ich nicht. > mehrere Interrupts auf, werden sie nacheinander abgearbeitet. Da einem > externen Interrupt kein > Flag zugeordnet ist, bleibt dieser nur solange in Evidenz, solange jene > Bedingung besteht, die zu seinem Auftreten geführt hat. Stimmt nicht. Das gilt bestenfallst für einen low level Interrupt. Die flankensensitiven, externen Interrupts setzen ein Bit.
Jobst M. schrieb: > Ich möchte ein Beispiel zeigen. Du sagst nur, welche Schritte diese beiden Beispiele ausführen. Mich würde aber mehr interessieren, wozu man sowas praktisch einsetzen kann. Mir fällt da erstmal nichts ein, was solche Berechnungen im Interrupt benötigt. Was sind das für konkrete Anwendungen oder ist das geheim? Ich fand das damals (1997) schon einen herben Rückschritt vom 8051 mit 4 Interruptleveln zum AVR ohne Interruptlevel.
Peter D. schrieb: > Ich fand das damals (1997) schon einen herben Rückschritt vom 8051 mit 4 > Interruptleveln zum AVR ohne Interruptlevel. Als ich zum ersten mal den Umgang mit AVR lernte war ich sehr irritiert, dass es dort keine Interrupt-levels gibt. Bis dahin dachte ich, das sei allgemeiner Standard. Andererseits hat mich das bei der praktischen Anwendung noch nie ernsthaft behindert. Für großartige Hochleistungs-Programme würde ich ohnehin andere Mikrocontroller verwenden.
Lothar M. schrieb: > Und deshalb kann ein Interrupt sich nicht selber unterbrechen, weil es > dafür ja nur 1 Quelle gibt und dieses Flag schon aktiv ist. Extrem wäre > es natürlich, zusätzlich zum Aktivieren des globalen Enables auch gleich > das auslösende Interruptflag zurückzusetzen. Es gibt kein "schon aktives Flag", was man "zurücksetzten" kann oder muß. Das Flag ist entweder gesetzt, oder nicht. Die CPU kennt auch gar keinen Status "in Interrupt" o.ä. Ist ein ISR-FLAG gesetzt, und ist der Interrupt freigegeben, wird der ISR-Vector bei nächter Gelegenheit (= Ende der Ausführung des aktuell laufenden Befehls) angesprungen. Ob das Flag neu gesetzt wurde, oder schon gesetzt war, oder vergessen wurde, es zu löschen, spielt keine Rolle. Oliver
:
Bearbeitet durch User
Jobst M. schrieb: > Ein Pulsgenerator erzeugt mittels Timer-IRQ (192k/s) einen Impuls bei > Überlauf eines Akkumulators (DDS-Prinzip). Jobst M. schrieb: > Es > werden zwei Differenzen gebildet, eine Entscheidung getroffen, eine > Multiplikation durchgeführt, eine Wurzel gezogen und eine Begrenzung (16 > Bit) durchgeführt. Das sieht nach einer G-Code-gesteuerten CNC-Steuerung aus. Dabei gibt es nur eine ISR, die alle anderen unterbrechen darf (um den Jitter klein zu halten). Kein Anfängerprojekt, aber auch kein Grund für merkwürdige Klimmzüge.
:
Bearbeitet durch User
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.