Forum: Mikrocontroller und Digitale Elektronik PIC - Interrupt Priority


von Mirco H. (mirq)


Lesenswert?

Hallo zusammen,

ich hab hier einen PIC18F4520 und benutze den C18-Compiler.

Für die serielle Kommunikation mit dem PC möchte ich nun Interrupts 
verwenden. Das funktioniert, wenn ich IPEN auf 0 setze und dann einen 
einen Vektor mit Adresse 0x08 verwende.

Ich möchte aber jetzt unterschiedliche Prioritäten ermöglichen und setze 
IPEN auf 1; sowie auch GIEL und GIEH.

Dazu Fragen...
Wo im Datenblatt finde ich eine Angabe dazu ob meine Interrupt-Quelle 
low- oder high-priority hat?! oder muss ich das für alle selbst 
zuweisen? wenn ja, dann weiß ich ebenfalls nicht wo :/
wenn ich mein programm teste stelle ich fest, dass ich wohl für den 
USART die high-ISR benötige...

Außerdem verwirrt mich, dass es auch ohne die folgende mittlere Zeile 
tut. Wird diese nicht benötigt?
1
#pragma code high_vector = 0x08
2
//#pragma interruptlow ISR_high  // NICHT BENÖTIGT?
3
void high_interrupt(void) {..}

Ist es die gängige Art bei diesem Controller dass man innerhalb der ISR 
erst prüft von wem der Interrupt ausgelöst wurde? Gibt es also wirklich 
insgesamt nur 2 Interrupt-Routinen?


Hoffentlich könnt ihr mir ein bisschen auf die Sprünge helfen :)

Viele Grüße, Mirco

von MarioT (Gast)


Lesenswert?

Wenn ein Interrupt auftritt, dann springt die Programmausführung an eine 
bestimmte Stelle im Programmspeicher. Diese Stellen sind festgelegt und 
können nicht geändert werden:

von MarioT (Gast)


Lesenswert?


von Mirco H. (mirq)


Lesenswert?

Danke, aber das ist alles in Assembler, hat nichts mit C18 zu tun und 
ist außerdem der falsche Controller?!


Ist beispielsweise für den UART standardmäßig eine high-priority 
implementiert? Kann ich das irgendwo nachlesen?

Grüße

von Peter D. (peda)


Lesenswert?

Mirco H. schrieb:
> Ist es die gängige Art bei diesem Controller dass man innerhalb der ISR
> erst prüft von wem der Interrupt ausgelöst wurde? Gibt es also wirklich
> insgesamt nur 2 Interrupt-Routinen?

Ja, das ist (nur) beim PIC so.
Das ist ein ziemlicher Pferdefuß der PICs.
Andere MCs haben die Interruptvektoren nach Quelle verschieden, da kann 
man gleich loslegen, ohne was testen zu müssen.
Auch muß der Compiler dann nur die benötigten Register sichern.


Peter

von Gast-O-mat (Gast)


Lesenswert?

Die Priorität der einzelnen Interrupts kanns Du mit jeweils einem Bit in 
den IPR-,  INTCON2- oder INTCON3-Registern einstellen. Nur nicht für den 
INT0, der ist immer high-priority.
Und ja, es gibt nur einen Vektor für high- und einen für low-interrupts. 
Dort muß man dann per Software auseinanderdröseln, wer den Interrupt 
ausgelöst hat.

von Der M. (steinadler)


Lesenswert?

Es gibt für jeden Interrupt 3 Register:

PIR - hier sind die Interrupt-Flags drin, wenn der Interrupt ausgelöst 
hat
IPR - hier legst du die Priority fest (0 = high und 1 = low, oder 
umgekehrt, weiß ich nicht aus dem Kopf)
PIE - damit kannst du die die gewünschten Interrupts 
aktivieren/deaktivieren

Low-Priority-Interrupts können von High-Priority-Interrupts unterbrochen 
werden.
High-Priority-Interrupts können NICHT unterbrochen werden.

Verwendung von Prioritäten musst du aber erst mit RCON.IPEN = 1 
festlegen.

Der Einsprungsvektor für High-Interrupts ist 0x0008h und der für 
Low-Interrupts ist 0x0018h

von MarioT (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Mirco H. schrieb:
>> Ist es die gängige Art bei diesem Controller dass man innerhalb der ISR
>> erst prüft von wem der Interrupt ausgelöst wurde? Gibt es also wirklich
>> insgesamt nur 2 Interrupt-Routinen?
>
> Ja, das ist (nur) beim PIC so.

Ich habe wieder was gelernt.
Was es nicht alles gibt?

von Mirco H. (mirq)


Lesenswert?

Ahh, danke. Das klappt jetzt alles mit high und low :)
Und auch wenn es wohl eine Umstellung bedeutet kann man sich sicher an 
die nur zwei ISR gewöhnen..

Könnt ihr mir auch noch sagen wieso die Zeile:
1
#pragma interruptlow ISR_low
scheinbar völlig unnötig ist? Funktioniert auch wenn sie an der gleichen 
stelle ein 'interrupt' statt 'interruptlow' hat oder sogar auch wenn sie 
auskommentiert ist..
Im C18-compiler-Handbuch und in allen Bsp. im Internet ist die Zeile 
immer vorhanden... Wird sie wo anders noch benötigt?

Grüße

von Der M. (steinadler)


Lesenswert?

Diese Zeile bewirkt ein automatisches Context-Saving. Also da kümmert 
sich dann der Compiler drum.

bei "#pragma interrupt" kommen die Inhalte aus WREG, BSR und STATUS in 
sogennante Shadow-Register.
"pragma interruptlow" hingegen, legt die Inhalte auf den Softwarestack.

von Mirco H. (mirq)


Lesenswert?

Ist dann eins von beiden möglicherweise als Standard festgelegt, so dass 
ich die Zeile nicht unbedingt schreiben muss? Funktionieren tut es bei 
mir nämlich auch ohne. Danke für die verständliche Formulierung!

Grüße

von Meister E. (edson)


Lesenswert?

Peter Dannegger schrieb:
> Ja, das ist (nur) beim PIC so.
> Das ist ein ziemlicher Pferdefuß der PICs.
> Andere MCs haben die Interruptvektoren nach Quelle verschieden, da kann
> man gleich loslegen, ohne was testen zu müssen.

Kleine Korrektur: Das ist bei allen 8-Bit PIC so. Die anderen Familien 
sind da moderner ausgerüstet.

Ein wirklich schlimmer Pferdefuss ist es meiner Meinung nach nicht, weil 
auch mit vielen separaten Interruptvektoren die ISR nicht gleichzeitig 
abgearbeitet werden können. Die Latenz beim Eintritt in eine spezifische 
ISR ist da natürlich etwas geringer, ob man von diesem Vorteil was hat 
ist aber sehr von der konkreten Anwendung abhängig.

Grüße,
Edson

von Der M. (steinadler)


Lesenswert?

Mirco H. schrieb:
> Ist dann eins von beiden möglicherweise als Standard festgelegt, so dass
> ich die Zeile nicht unbedingt schreiben muss? Funktionieren tut es bei
> mir nämlich auch ohne. Danke für die verständliche Formulierung!
>
> Grüße

Ist mir nicht bekannt. Vergleich doch mal den assemblierten Code der 
beiden Varianten.
Sicher kann es auch ohne Context-Saving funktionieren. Aber irgendwann 
kommt der Punkt, wo du einen Fehler suchst, und dir nicht erklären 
kannst, wo der her kommt. Zum Beispiel Vorzeichen-/Rechenfehler.

Interrupt nach der Berechnung:
0. Register 1 und 2 rücksetzen
1. Berechnung mit Register 1 und 2, Schritt 1
2. Berechnung mit Register 1 und 3, Schritt 2
3. Interrupt verändert Register 1

das geht so.

aber bei Interrupt während der Berechnung:
0. Register 1 und 2 rücksetzen
1. Berechnung mit Register 1 und 2, Schritt 1
3. Interrupt verändert Register 1
2. Berechnung mit Register 1 und 3, Schritt 2

kommt Mist raus, weil das Register 1 vom Interrupt verändert wird.

Tritt der Interrupt WÄHREND einer Berechnung auf, kann der dir den 
aktuellen Registerinhalt zerschießen.

von Peter D. (peda)


Lesenswert?

Der Micha schrieb:
> bei "#pragma interrupt" kommen die Inhalte aus WREG, BSR und STATUS in
> sogennante Shadow-Register.
> "pragma interruptlow" hingegen, legt die Inhalte auf den Softwarestack.

Das heißt im Klartext, "pragma interruptlow" ist für Interrupts, die 
selber unterbrechbar sein müssen, also "low priority".
Stack ist sicherer, aber wohl langsamer als Register.


Peter

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
Noch kein Account? Hier anmelden.