www.mikrocontroller.net

Forum: Mikrocontroller und Elektronik Diskussion Interrupts beim ARM7 LPC2138

Autor: Martin (Gast)
Datum: 03.04.2008 18:00

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
Autor: Andreas Kaiser (a-k)
Datum: 03.04.2008 20:46

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.
Autor: Martin (Gast)
Datum: 04.04.2008 08:55

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
Autor: Andreas Kaiser (a-k)
Datum: 04.04.2008 09:04

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.
Autor: Martin (Gast)
Datum: 04.04.2008 17:24

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
Autor: Andreas Kaiser (a-k)
Datum: 04.04.2008 23:49

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.
Autor: Christian J. (Gast)
Datum: 10.04.2008 23:16

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
Autor: Andreas Kaiser (a-k)
Datum: 10.04.2008 23:38

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.
Autor: Stefan K. (Gast)
Datum: 15.05.2008 21:48

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

Antwort schreiben

Die Angabe einer Email-Adresse ist freiwillig. Wenn Sie automatisch per Email über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Suchfunktion und Betreffsuche benutzen - vielleicht gibt es schon einen ähnlichen Beitrag
  • Aussagekräftigen Betreff wählen
  • Im Betreff angeben um welchen Controllertyp es geht (AVR, PIC, ...)
  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang
  • JPEG-Dateien (.jpg) nur für Fotos und Scans verwenden
  • Schaltpläne, Screenshots usw. als PNG oder GIF anhängen

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [pre]vorformatierter Text (z.B. Code in anderen Sprachen)[/pre]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel






webmaster@mikrocontroller.netImpressumWerbung auf Mikrocontroller.net