Hallo, wollte mal kurz fragen obs eine Möglichkeit gibt verschiedenen Interrups eine Priorität zuzuweisen? Mir fällts nur so ein das ich am Anfang einer wichtigen Int.-Routine einfach die Interrups ausschalte um nicht gestört zu werden, oder gibt es eine möglichkeit Prioritäten zu verteilen. Braucht keine fertige Lösung sein sondern eine Idee/Vorschlag genügt mir schon.
hi, der "normale" weg ist es, zu beginn einer (längeren, kritischen) interrupt-routine das ie-register zu sichern, interrupts auszuschalten, befehle ausführen, ie zurückschreiben, interrupts an und feddich. prioritäten bei irq's gibts afaik nicht, würde bei RISC auch wenig sinn machen...
Hallo, ok danke für die schnelle Antwort. Heißt "sichern" auf den Stack legen und zurückholen(push/pop) oder ist das unsicher?
Ja, der AVR hat leider keine Interruptprioritäten. Was das aber mit RISC zu tun haben soll, ist mir schleierhaft. Egal ob RISC oder CISC, es macht in jedem Fall komplexere Anwendungen einfacher. Sogar einige neuere PICs haben das. Bisher habe ich es beim AVR immer geschafft, mit nur einer Interruptpriorität auszukommen, indem ich die Interrupts so kurz wie möglich halte, d.h. alle nicht eiligen Schritte ins Hauptprogramm verlagere. Interruptprioritäten in Software zu machen ist zwar theoretisch möglich, aber sehr kompliziert. Man muß dabei höllisch aufpassen, daß sich Interrupts nicht selber wieder aufrufen können und das auch wirklich die richtigen Register richtig gesichert werden. Da die Interrupt-Enable-Bits leider überall verteilt sind und obendrein die Interrupt-Pending-Bits ausmaskiert werden müssen, ist das eine äußerst langwierige Angelegenheit, wärend der alle Interrupts gesperrt sind. Mit anderen Worten, die Interrupt-Response-Zeit kann sich dadurch drastisch verschlechtern. Peter
Hallo, immer wieder heißt es, der AVR hätte keine Interrupt-Prioritäten. Im Manual, z.B. zum 2313, liest man jedoch: "The complete list of vectors is shown in Table 2. The list also determines the priority levels of the diferent interrupts. The lower the adress, the higher the priority level. Reset has the highest priority,...." Widersprechen sich die beiden Aussagen nicht? Klar ist, daß man als Anwender an diese Tabelle gebunden ist, außer man bemüht sich in der Software, das zu ändern. Wie lassen sich denn beide Aussagen in Einklang bringen? Gruß
Ich vermute mal, daß es sich dabei um einen Übersetzungsfehler handelt. In anderen Architekturen wird das richtiger als Auflösungsreihenfolge bezeichnet. D.h. es ist damit die Reihenfolge gemeint in der entschieden wird, welcher Interrupt angesprungen wird, wenn mehrere Interruptquellen gleichzeitig gesetzt sind, z.B. wenn alle Interrupts über eine längere Zeit global gesperrt waren. Peter
Genau so ist es. Denn der AVR löscht ja bei jedem Eintritt in eine ISR das Interrupt-Enable-Bit. Nach der ISR wird es wieder gesetzt. Also gibt es eigentlich eine Unterbrechung der ISR durch eine andere. Ich habe das aber in einer Anwendung schon benötigt. Also hab ich in meiner, um einiges längere, Routine das dazugehörige Interrupt-Enable-Bit gelöscht und dann die Interrupts Global wieder freigegeben. Am Ende der Routine hab ich das Bit dann wieder gesetzt. So konnte diese ISR durch eine andere (in diesem Fall höhere ISR) unterbrochen werden, aber Sie konnte sich nicht selbst aufrufen. Gruß, Florian
Dann grabe ich mal dieses schöne Thema wieder aus! :-) Wie sieht es denn bei folgenden Beispiel aus! Ich habe zum Beispiel einen Overflow Timer Interrupt und ein INT0 Interrupt, wo ein Taster dran ist. Beim Timer Interrupt wird eine Variable hochgezählt. Btw. muss die volatile sein? So jetzt halte ich den Taster gedrückt. Kommt der Timerinterrupt trotzdem noch zum Zuge?
Variable volatile? Ja wenn sie nicht nur im Timer Interrupt sondern auch in einem anderen Interrupt oder Hautprogramm benutzt wird. Sobald ein Interrupt aktiv ist sind alle weiteren Interrupt Abforderungen gesperrt. Man muss in der Interrupt Routine ein EI machen damit die anderen Interrup Anforderungen den aktuellen Interrupt unterbrechen können. Die Interrupt Priorität hat damit nichts zu tun. Sie regelt die Reihenfolge bei gleichzeitigem Auftreten von mehreren Interrupt Anforderungen.
> Die Interrupt Priorität hat damit nichts zu tun. Doch , eigentlich ist sie genau das. Höherpriore Interrupts können niederpriore unterbrechen, umgekehrt aber nicht. Das unterstützt der AVR nicht, sondern nur: > Sie regelt die Reihenfolge bei gleichzeitigem Auftreten von mehreren > Interrupt Anforderungen. Siehe Posting in diesem Thread etwas weiter oben: Beitrag "Re: AVR ASM Interrupt Priorität"
>So jetzt halte ich den Taster gedrückt. Kommt der Timerinterrupt >trotzdem noch zum Zuge? Schreib doch ein Mini-Testprogramm im AVRStudio und lass es im Simulator laufen. Ich tippe übrigens auf "nein", d. h. der Timerinterrupt wird nicht mehr aufgerufen, wenn der INT0-Interrupt auf "pegelgetriggert" konfiguriert ist und deshalb bei gedrücktem Taster ständig ansteht. Dieser Betriebszustand gibt aber in keinem normalen Programm einen Sinn. Man benötigt den pegelgetriggerten INT0 zum Aufwachen aus dem Power Down und zur Realisierung eines Single-Step-Modus für Debuggingzwecke, aber ich glaube nicht, dass er für sonst noch was gut ist (heißt: etwas, das man nicht auch mit einem flankengetriggerten INT0 erledigen kann).
> (heißt: etwas, das man > nicht auch mit einem flankengetriggerten INT0 erledigen kann). Wobei Taster am flankengetriggerten Int0 kontraproduktiv sind, es sei denn, man will einen Zufallsgenerator bauen. ;-) ~
Ahh so... und was würde man dann für ein Interrupt verfahren nehmen, wenn man per Tastendruck eine Aktion machen will. Polling würde ja bei kritischen Anwendungen nicht die optimale Lösung sein. Worauf ich hinaus will ist, der Timer Interrupt ist wichtig aber der Tastendruck Interrupt auch. Aber wie könnte man das jetzt lösen, wenn zum Beispiel aus mechanischen Gründen der Schalter hängt. Dann würde ja die kritische Timer Routine nicht mehr zum zugekommen, wenn ich das jetzt richtig verstanden habe!?
Max wrote: > Ahh so... und was würde man dann für ein Interrupt verfahren nehmen, > wenn man per Tastendruck eine Aktion machen will. Polling würde ja bei > kritischen Anwendungen nicht die optimale Lösung sein. Ich nehme an, es ist für dich sehr wichtig, dass der Tastendruck nach 10µs und nicht erst nach 1000µs zur entsprechenden Reaktion führt. Denn andernfalls ist entprelltes Polling im oft sowieso schon vorhandenen regelmässigen Timer-Interrupt höchst einfach und problemlos: http://www.mikrocontroller.net/articles/Entprellung#Interrupt-Verfahren_.28nach_Peter_Dannegger.29
>Wobei Taster am flankengetriggerten Int0 kontraproduktiv sind, es sei >denn, man will einen Zufallsgenerator bauen. ;-) OK, das steht dann auf einem anderen Blatt. Ein denkbarer Anwendungsfall: Jemand will herausfinden, wie oft ein Taster prellt. Dann könnte er ihn an einen flankengetriggerten INT0 hängen und in der ISR nur eine Variable inkrementieren, die sofort auf einen Port geschrieben wird. >Polling würde ja bei >kritischen Anwendungen nicht die optimale Lösung sein. Nein, umgekehrt: Über Interrupt ist nicht die optimale Lösung. Jeder Taster prellt. Wenn er beim Niederdrücken z. B. fünf mal prellt, dann gibts zwei Möglichkeiten: 1. Der INT0-Handler wird auch fünfmal aufgerufen, weil er so reaktionsschnell ist (das ist ja gerade seine Besonderheit). Dies dürfte kaum jemals erwünscht sein. Also muss man 2. irgendwie eine künstliche Verzögerung realisieren, die verhindert, dass der Interrupt sofort nach dem ersten Pegelwechsel erneut stattfinden kann. Eine Delayschleife ist dafür tabu, weil der µC in einer zeitkritischen Anwendung nicht ein paar Millisekunden lang blockiert sein darf, also muss man es mit einem Timer machen. Toll: Dann sind zwei wertvolle Controllerresourcen (ext. Int. + Timer) mit der Abfrage eines dämlichen Tasters belegt. Manche hält das nicht davon ab, es tatsächlich so zu machen; der Rest erkennt die Vorteile der Pollingmethode: Kein externer Interrupt nötig; die Resource Timer kann gleichzeitig noch vielen anderen Zwecken dienen; CPU-Last vernachlässigbar (wen nicht: Taktfrequenz des µC raufsetzen); so viele Taster handelbar, wie man will. Die durch die Tastenabfrage erzeugte CPU-Last kann man leicht rechnerisch abschätzen und kommt unter realistischen Bedingungen (z. B. FOSC = 8 MHz, Abfrageintervall = 10 ms, 20 Takte für Tastenhandler) auf Werte weit unter 1 %.
Ah stimmt dran habe ich noch nicht gedacht. Auch wenn ich jetzt nicht Timer und INT0 für einen "dämlichen" Taster verschwenden würde! Da hätte ich noch eine Offtopic Frage! ;-) Nehmen wir an zwei Leute arbeiten an einem Projekt. Jeder schreibt seinen Teil. Beide nutzen den Timer Overflow Interrupt. Gibt es in einem Programm immer nur einen ISR zu dem jeweiligen Interrupt?! Ich würde denke ja, aber wie organisiert man dann so ein etwas größeres Programm?! Legt man sowas dann vorher durch die Vorplanung fest?
@ Max (Gast) >arbeiten an einem Projekt. Jeder schreibt seinen Teil. Beide nutzen den >Timer Overflow Interrupt. Gibt es in einem Programm immer nur einen ISR >zu dem jeweiligen Interrupt?! Ja. Dort kann man aber mehrere Funktionen aufrufen. > Ich würde denke ja, aber wie organisiert >man dann so ein etwas größeres Programm?! Legt man sowas dann vorher >durch die Vorplanung fest? Wäre sinnvoll. MFG Falk
@ Max (Gast)
>Ist es dann auch sinnvoll alle ISR in eine seperate Datei zu legen?
Kann man manchen, muss man aber nicht. Geschmackssache.
MFG
Falk
Modularisierung. Ein Timer-Modul bestehend aus .h und .c mit Initialisierung und der dazu gehörenden ISR. Wahlweise werden darin die Timer-Handler anderer Module direkt aufgerufen - das ist die einfache Fassung für überschaubare Projekte. Oder man geht einen Schritt weiter und bietet im Timer-Modul eine Funktion, mit der sich beliebige Timer-Handler hinzufügen lassen - dann wird ein flexibel (wieder-) verwendbarer Timer Scheduler draus.
>>Ist es dann auch sinnvoll alle ISR in eine seperate Datei zu legen? > > Kann man manchen, muss man aber nicht. Geschmackssache. Wenn damit gemeint ist, dass jede ISR in ein eigenes Quellcode-File nur für diese ISR soll: Das ergibt nur in besonderen Fällen Sinn, etwa wenn der Code anders compilert werden muss (z.B. ARM/Thumb). Denn dadurch steigt der Aufwand und man kann in C keine Modul-lokalen Variablen mehr verwenden (static). Ansonsten gehört zusammengehöriger Code zusammen und weitgehend getrennter Code getrennt. Also ein Code-Modul für UART mitsamt seinen Interrupts und getrennt davon eines für I2C.
Ah ich finde das Forum super! ;-) Nicht so ein Kompetenzverlust wie in anderen Foren! :-)
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.