Hallo Leute! Ich habe das IRQ-System des ARM-Prozessors noch nicht ganz verstanden. Aus diesem Grund bitte ich euch, ob wir darüber einwenig diskutieren können. Wenn meine Ausführung nicht der Richtigkeit entsprechen sollten, bitte ich darum mich zu korrigieren. Soweit ich gehört habe, sind der IRQ-Controller und der Prozessor-Core zueinander nicht synchron. Aus diesem Grund kann es passieren, dass unerwünschte IRQs entstehen (Spurious). Diese muss man in einer leeren IRQ-Routine abfangen, wobei man das Register VICVectAddr beim Verlassen beschreiben muss. Z.B: void spurious_handler() __irq { VICVectAddr=0x00; } Soweit ich das verstanden habe tritt ein Spurious-IRQ dann auf, wenn ein IRQ zu kurz (z.B. Level IRQ an einem Eingang) anliegt. Der IRQ-Controller meldet an den Core, dass ein IRQ anliegt. Der Core versucht nun die Adresse des Vektors zu laden. Ist der IRQ zu diesem Zeitpunkt bereits wieder verschwunden, dann kann auch keine Adresse geladen werden und der Prozessor springt die Spurious-Routine an. Dann gibt es anscheinend noch ein Problem, wenn man die IRQs sperren möchte. Um die IRQs zu sperren kann man sich mit folgendem Befehl helfen: VICIntEnClr = 0xFFFFFFFF; // disable all interrupts Danach kann man sie wieder einschalten. Doch bei einem Ausschalten kann es passieren, dass ebenfalls Spurious-IRQs auftreten. Warum ist das so? Was passiert eigentlich, wenn mit dem obigen Befehl alle IRQs ausgeschaltet wurden und ein IRQ auftritt? Wird die Vektoradresse erst wieder geladen wenn die IRQs wieder eingeschaltet sind? Wenn sich der Prozessor in einer IRQ-Routine befindet und ein weiterer IRQ auftritt, wann wird dann die Vektoradresse des nächsten IRQs geladen, nach dem Austritt aus der aktuellen Routine? Es würde mich freuen, wenn wir darüber einwenig diskutieren können. Ich habe noch ein paar Fragen, aber die möchte ich erst im Laufe der Diskussion einfließen lassen. Danke, einen schönen Abend wünsche ich noch. Tschüss Martin
Martin wrote: > Soweit ich das verstanden habe tritt ein Spurious-IRQ dann auf, wenn ein > IRQ zu kurz (z.B. Level IRQ an einem Eingang) anliegt. Korrekt. > Dann gibt es anscheinend noch ein Problem, wenn man die IRQs sperren > Danach kann man sie wieder einschalten. Doch bei einem Ausschalten kann > es passieren, dass ebenfalls Spurious-IRQs auftreten. > Warum ist das so? Aus exakt dem gleichen Grund wie oben. Der VIC meldet dem Core den Interrupt. Einige Takte später führt das zum Lesen des Vektors. Wenn exakt dazwischen das VICIntEnClr = 0xFFFFFFFF; liegt, dann reagiert der VIC zwangsläufig etwas ratlos auf die Frage nach dem Vektor. > Wird die Vektoradresse erst > wieder geladen wenn die IRQs wieder eingeschaltet sind? Der Vektor wird erst final bestimmt, wenn der Prozessor ihn explizit läd. Das passiert ja nicht automatisch, sondern ist Teil des Interrupt-Codes, oft in Form eines Befehls direkt an der Stelle des Vektors. > Wenn sich der Prozessor in einer IRQ-Routine befindet und ein weiterer > IRQ auftritt, wann wird dann die Vektoradresse des nächsten IRQs > geladen, nach dem Austritt aus der aktuellen Routine? Wenn während der Abarbeitung des ersten Interrupts der IRQ abgeschaltet war, dann geht der Weg erst wieder zurück ins unterbrochene Programm, bevor der nächste Interrupt ausgelöst wird. Gibt die Interrupt-Routine die Interrupts vorher frei, kann sie ab diesem Zeitpunkt durch höher priorisierte Interrupts unterbrochen werden.
Hallo Andreas! Danke für deine ausführliche Antworten. >Wenn während der Abarbeitung des ersten Interrupts der IRQ abgeschaltet >war, dann geht der Weg erst wieder zurück ins unterbrochene Programm, >bevor der nächste Interrupt ausgelöst wird. Nehmen wir mal an die IRQ-Routine wird abgearbeitet und sie benötigt relativ lange. Wenn jetzt in dieser Zeit ein weiterer IRQ ausgelöst wird und dieser wieder verschwindet, bevor der Prozessor die Möglichkeit hat in das Hauptprogramm zurückzukehren, wird dann zwangsläufig ein Spurious-IRQ ausgelöst? Tschüss Martin
Martin wrote:
> wird dann zwangsläufig ein Spurious-IRQ ausgelöst?
Nein. Würde sich der VIC alle IRQ Anforderungen merken, gäbe es den
spurious interrupt nicht. Denn dann wäre klar, woher der Auslöser kam.
Tatsächlich speichert der VIC die Anfragen nicht, sondern bildet rein
kombinatorisch aus allen freigegebenen IRQ-Inputs eine Gesamtsumme, die
als IRQ an den Prozessor weitergereicht wird. Der wiederum speichert
ebensowenig, sondern prüft bei jedem Befehl, ob er normal weiter machen
soll oder unterbrechen. Aber das tut er nur wenn er darf, also wird die
IRQ Anfrage erstmal ignoriert. Und wenn sie verschwindet bevor die IRQs
wieder eingeschaltet werden, dann passiert garnichts.
Das ganze lässt sich ungefähr am Unterschied zwischen "level triggered"
und "edge triggered" erklären. Flankengetriggerte Interrupts speichern
die Anfrage, war die Flanke mal da, dann bleibt der Request gespeichert
bis er bearbeitet und gelöscht wurde. Pegelgetriggerte Interrupts
speichern nicht, sondern müssen solange anliegen bis sich jemand drum
kümmert, sonst gehen sie verloren. LPC21xx Interrupts sind seitens des
Prozessors und seitens des Interrupt Controllers pegelgetriggert.
Hallo Andreas! OK, ich glaube ich verstehe soweit. Ich versuche das Ganze nochmal zusammenzufassen: Wenn der Prozessor gerade das Hauptprogramm abarbeitet und plötzlich ein IRQ ansteht und bevor der Vektor geladen werden kann, der IRQ wieder verschwindet oder mit VICIntEnClr = 0xFFFFFFFF; der IRQ abgeschaltet wird, dann wird ein Spurious-IRQ ausgelöst, weil der Vektor unbekannt ist. Befindet sich der Prozessor in einer IRQ-Routine und steht dort plötzlich ein weiterer IRQ an, dann wird dieser so lange ignoriert bis nach der IRQ-Routine der Prozessor wieder im Hauptprogramm ist und die Sperr-Bits im PSR-Register wieder frei sind. Jetzt erst erkennt der Prozessor den nächsten IRQ und lädt darauf den Vektor. Wäre dieser zweitanstehende IRQ wieder verschwunden, bevor der Prozessor aus der ersten IRQ-Routine gesprungen ist, dann hätte dieser von dem zweiten IRQ nichts mitgekriegt. Wenn ich jetzt den Prozessor z.B. im Privileg-Mode laufen lasse und ich die IRQ-disable-Flags im PSR-Register selbst ein und abschalte, um IRQs im Hauptprogramm zu sperren, können im Prinzip keine Spurious-IRQs entstehen, weil der Prozessor durch das Ausschalten der IRQ-Disable-Flags nicht mitkriegt, dass IRQs überhaupt anliegen. Sehe ich das richtig? Auf jeden Fall danke ich dir schon jetzt für deine Antwort und für deine bisherigen Antworten. Damit hast du mir weitergeholfen. Tschüss Schönes Wochenende Martin
Spurious Interrupts sind kaum zur Gänze vermeidbar, weil die Ursache auch anders als durch Interrupt-Enables verschwinden kann. NXP gibt in der sonst nicht so ganz gelungenen AN10414 als Beispiel die UART an, deren Timeout-Interrupt durch grad rechtzeitig eintrudelndes Byte wieder verschwinden kann. Mit dem dort auch genannten Lösungsansatz bin ich allerdings über Kreuz. Aber dazu hat es im Internet (Yahoo Group zu LPC2000) schon reichlich Zündstoff gegeben. Ist aber m.E. nicht wirklich ein Problem. Man sollte halt den Default-Vector mit Leben füllen, wie von dir oben gezeigt, und damit hat es sich. Neugierige Leute inkrementieren dort einen Zähler und gucken ab und zu nach.
Hallo, ich möchte hier nochmal anknüpfen, weil mir die VIC Struktur immer noch etwas rätselhaft ist. Der Chip hat diverse Peripherieeinheiten von denen fast alle IRQ fähig sind. Beim PIC gibt es nur einen IRQ Vektor, wo dann nacheinander abgefragt wird, wer es denn nun war. Aber nun der ARM7: 1. Muss man für jede Peripherie EINE Routine anlegen und kann dann in der Routine auslesen, welcher IRQ nun wirklich kam? Also eine für UART, eine für die Timer, die wieder Capture & Compare/Match Fähigkeit haben usw. 2. Wie kann man IRQs schachteln? Also, dass sie einander unterbrechen dürfen? 3. Was macht VICVectAddr=0x00 denn genau? 4. Was sind die "Slots"? Bei mir sind, egal ob PIC oder ARM7 Programme meist so aufgebaut, dass ich einen Timer-IRQ habe, der zB alle 0,1s kommt und wo allerlei Sachen gemacht werden, wie zB Software-Zähler-Uhren, AD Werte auslesen in Register, Tasten abfragen etc. Dieser IRQ muss natürlich unterbrochen werden könnenn, wenn zB über mein Funkmodul etwas reinkommt, bevor dessen Fifo überläuft. Gruss, Christian
Christian J. wrote: > 1. Muss man für jede Peripherie EINE Routine anlegen und kann dann in > der Routine auslesen, welcher IRQ nun wirklich kam? Also eine für UART, > eine für die Timer, die wieder Capture & Compare/Match Fähigkeit haben > usw. Wenn die betreffende Peripherie mit Interrupts arbeitet ja. Das wird übrigens von den meisten Leuten als Vorteil empfunden. Denn in den Routinen sollte man zwar nochmal kontrollieren, ob der Interrupt wirklich ausgelöst wurde, aber man muss nicht alle zig IRQs durchprobieren, weil ja klar ist um welchen es geht. Wobei je nach Controller manche Periphierie auch mehrere IRQs belegen kann (insgesamt 9 Stück beim CAN-Modul vom LPC2194). Wenn dich das so sehr stört, kannst du aber nach wie vor einen einzigen Interrupt-Handler benutzen und dort in schönster(?) PIC-Tradition alles durchprobieren. Denn die Vektorierung mach der ARM nicht selber, sie entsteht erst durch den Code an Adresse 0x18. Oft ist das ein indirekter Sprungbefehl der den Vektor aus dem Interrupt-Controller in den PC läd. > 2. Wie kann man IRQs schachteln? Also, dass sie einander unterbrechen > dürfen? Siehe NXP Application Note AN10381. Ist abhängig vom verwendeten Interrupt-Controller. > 3. Was macht VICVectAddr=0x00 denn genau? Zu dem Zeitpunkt, zu der Vektor ausgelesen wird, wird die Interrupt-Logik so eingestellt, dass alle niederiger priorisierten Interrupts vorübergehend gesperrt sind. Das ist Voraussetzung für Nesting. Dieser Befehl entsperrt sie wieder. > 4. Was sind die "Slots"? Keine Ahnung was du meinst.
Hallo Zusammen! ich bin gerade auf Eure Diskussion gestoßen, da der VIC mich im Moment in Verbindung NXP-Prozessoren auch beschäftigt. Auch ich möchte mit 'Nesting' von Interrupts demnächst arbeiten. Dabei habe ich eine Frage, die zu Eurer Diskussion passt: Systembeschreibung: ARM7-System von NXP mit VIC arbeitet mit 3 IRQ's unterschiedlicher Priorität. Die 3 IRQ's sind unterbrechbar. Zeitliche Abfolge der Interrupts: 1. Interrupt: Der mittelpriore Interrupt tritt auf: Reaktion: Der mittelpriore Interrupt wird bearbeitet 2. Interrupt: Der höchtpriore Interrupt tritt auf, während mittelpriorer Interrupt bearbeitet wird: Reaktion: Mitterpriorer Interrupt wird unterbrochen und der höchstpriore Interrupt wird bearbeitet. 3. Interrupt: Der niederpriorste Interrupt steht an, während der höchstpriore Bearbeitet wird: Reaktion: Die höchstpriore ISR wird nicht unterbrochen und wird zu Ende geführt. Nach dem Verlassen der höchsprioren ISR wird dem VIC durch Beschreiben von VicVectAddr das Ende der ISR mitgeteilt. Jetzt meine Frage: Wird jetzt mit der mittelprioren ISR weitergemacht oder kommt der niederpriore Interrupt durch bzw. hat sich der VIC gemerkt, dass der mittelpriore Interrupt noch nicht zu Ende bearbeitet wurde? Gruß, Stefan
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.