PIC - Interrupt Priority

OP #1648903
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
#1648920
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
Gast #1648927
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.
#1648931
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
Gast #1648937
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?
OP #1648944
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
#1649074
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
#1649334
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.
#1649499
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

Antwort schreiben

Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt. Bitte hier nur auf die ursprüngliche Frage antworten, für neue Fragen einen neuen Beitrag erstellen.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.