Forum: Mikrocontroller und Digitale Elektronik Interrupt-Priorität


von Hans I. (obiwahn)


Lesenswert?

Hallo.
Ich bin mir nicht sicher,ob ich das englische Datenblatt (AT90S2313) 
richtig interpretiert habe. Es geht mir um Interrupt-Programmierung.
Ich benutze in meinem Programm die Ext.Interrupts 0+1 und den 
Timer0-Überlauf-IRQ. Wenn ich das Datenblatt richtig verstanden habe, 
könnte zB. je nach Priorität ein IRQ uU. eine andere laufende 
IRQ-Routine unterbrechen. Das ist aber nicht erwünscht ! Kann ich das 
irgendwie verhindern ?

von Ch D. (chrisu) Benutzerseite


Lesenswert?

hi,
du kannst einfach während des Interrupts Interrupts Global "verbieten".

am anfang des Ints: __asm("cli");//Interupts verbieten
am ende des Ints :  __asm("sei");//Interupts wieder erlauben.

mfg chrisu

von Sven (Gast)


Lesenswert?

Du kannst es Dir auch schenken. Die einfachen AVRs haben keine 
Priorisierung der Interrupts. Wird ein Interrupt abgearbeitet, sind bis 
zum reti alle anderen gesperrt.

von Sven (Gast)


Lesenswert?

Achso, und es wird nach jedem reti erst ein Befehl im Hauptprogramm 
abgearbeitet, bevor wieder ein Interrupt aufgerufen werden kann.

von Hans I. (obiwahn)


Lesenswert?

Hm. Wenn Swen recht hat, wäre das also kein Problem.
Wenn ich aber mal einen AVR hätte, der die Interrupts nach Priorität 
abarbeitet und ich Chrisus lösung nehme, sehe ich ein anderes Problem.

Es könnte dann ja passieren , das ein zweiter , anstehender IRQ 
ausgelöst wird, genau zwischen dem SEI und dem RETI der laufenden 
IRQ-Routine 1.
Der Programmablauf würde dann ja folgendermaßen aussehen :


cli     ;IRQ-Routine 1
div. Befehle
sei     ;IRQ-Routine 1
        ;Auslösen der IRQ-Routine 2
cli
div. Befehle
sei     ;IRQ-Routine 2
reti    ;IRQ-Routine 2

ein befehl des Hauptprogramms

reti    ;IRQ-Routine 1

weiter im Hauptprogramm

Oder mach ich da einen Denkfehler ?

von Stefan E. (sternst)


Lesenswert?

Hans Imglück schrieb:
> Oder mach ich da einen Denkfehler ?

Nein, weshalb das von Ch D. Vorgeschlagene nicht nur unnötig, sondern 
sogar potenziell gefährlich ist.

Bei allen AVRs sind Interrupts allgemein automatisch gesperrt, so lange 
eine ISR abgearbeitet wird.

von spess53 (Gast)


Lesenswert?

Hi

>Es könnte dann ja passieren , das ein zweiter , anstehender IRQ
>ausgelöst wird, genau zwischen dem SEI und dem RETI der laufenden
>IRQ-Routine 1.
>Der Programmablauf würde dann ja folgendermaßen aussehen :...

Abgesehen davon, das das bei AVRs nicht geht (bei anderen schon), wäre 
es bei ordentlich programmierten Interruptroutinen kein Problem.

MfG Spess

von Stefan E. (sternst)


Lesenswert?

spess53 schrieb:

> Abgesehen davon, das das bei AVRs nicht geht (bei anderen schon)

Natürlich geht das. Das sei im Vorschlag von chriso öffnet die 
Möglichkeit für verschachtelte Interrupts.

von spess53 (Gast)


Lesenswert?

Hi

>Natürlich geht das. Das sei im Vorschlag von chriso öffnet die
>Möglichkeit für verschachtelte Interrupts.

Nein. Er versucht das unnötigerweise zu verhindern.

>am anfang des Ints: __asm("cli");//Interupts verbieten
>am ende des Ints :  __asm("sei");//Interupts wieder erlauben.

MfG Spess

von Stefan E. (sternst)


Lesenswert?

spess53 schrieb:
> Hi
>
>>Natürlich geht das. Das sei im Vorschlag von chriso öffnet die
>>Möglichkeit für verschachtelte Interrupts.
>
> Nein. Er versucht das unnötigerweise zu verhindern.

Du hast den Zusammenhang offenbar überhaupt nicht mitbekommen.

Ch D.:
Unsinniger Vorschlag mit den cli/sei in der ISR.

Hans Imglück:
Wenn man das benutzt, kann dann nicht das passieren:
(Beschreibung von verschachtelten Interrupts wegen dem sei am Ende der 
ISR)

Dein Kommentar zu dieser Befürchtung:
geht bei AVRs gar nicht

von Oliver (Gast)


Lesenswert?

Hans Imglück schrieb:
> Hm. Wenn Swen recht hat, wäre das also kein Problem.
> Wenn ich aber mal einen AVR hätte, der die Interrupts nach Priorität
> abarbeitet und ich Chrisus lösung nehme, sehe ich ein anderes Problem.
...
>ein befehl des Hauptprogramms

Das ist natürlich so nicht richtig. Abgearbeitet wird ein Befehl des 
durch den Interrupt unterbrochenen Programmteil. Das kann natürlich auch 
eine andere (oder so gar die gleiche) Interruptroutine sein.

Oliver

von Sven (Gast)


Lesenswert?

Sicher, dass ein SEI in der ISR greift und das nicht anderweitig 
geblockt wird?

von Stefan E. (sternst)


Lesenswert?

Sven schrieb:
> Sicher, dass ein SEI in der ISR greift und das nicht anderweitig
> geblockt wird?

Ja. Man kann definitiv mit einem SEI die Interrupts innerhalb einer ISR 
freigeben.

von Thomas F. (tfreal10)


Lesenswert?

Stefan Ernst schrieb:
> Sven schrieb:
>> Sicher, dass ein SEI in der ISR greift und das nicht anderweitig
>> geblockt wird?
>
> Ja. Man kann definitiv mit einem SEI die Interrupts innerhalb einer ISR
> freigeben.

Wenn das so ist muss ich dann am Ende des interrupts wieder cli machen? 
oder würde ich mit einem cli am Ende die Interrupts komplett abschalten?

Also ich möchte z.B. bei einem Interrupt an einem Pin andere Interrupts 
zulassen bei einem Timer Interrupt aber nicht. So dass praktisch das 
Timer Interrupt eine höhere Priorität hat.

von Stefan E. (sternst)


Lesenswert?

Thomas Frosch schrieb:

> Wenn das so ist muss ich dann am Ende des interrupts wieder cli machen?

Nein.

> oder würde ich mit einem cli am Ende die Interrupts komplett abschalten?

Nein. Ein cli am Ende der ISR hat praktisch keinen Effekt. Die 
Interrupts wären nur für eine kurze Zeit gesperrt, denn das reti danach 
gibt sie gleich wieder frei.

> Also ich möchte z.B. bei einem Interrupt an einem Pin andere Interrupts
> zulassen bei einem Timer Interrupt aber nicht. So dass praktisch das
> Timer Interrupt eine höhere Priorität hat.

Gerade bei Interrupts an einem Pin ist ein sei() in der ISR allerdings 
eine riskante Sache. Wenn das Signal an dem Pin nämlich prellt (z.B. 
Taster), oder einfach nur häufiger kommt als erwartet, hast du ruck-zuck 
sich selbst unterbrechende Interrupts.

von Andy H. (vinculum) Benutzerseite


Lesenswert?

genau, und der stack läuft über und dann ist schicht
deshalb finger weg von sei in einer isr!!!

von Gad Z. (gad)


Lesenswert?

Das Thema Interrupts und Priorität scheint ja ein nie mehr endendes 
Problem zu sein.

Habe schon so viel im Internet gelesen darüber und leider auch viel 
Unsinn.
Habe gerade selber das "Problem", dass ich eine Priorität brauche, weil 
ich einige kurze aber häufig auftretende Interrupts habe und dann wieder 
lange aber seltener auftretende.

Hatte auch überlegt, die langen Interrupts durch ein Flag zu ersetzen 
und dann im Main die eigentliche Arbeit zu machen.
Das geht aber nur, solange die Main klein genug ist um das in der 
nötigen Zeit zu schaffen. Schließlich kommt ja in die Main alles 
"unwichtige" rein, was halt irgendwann mal bearbeitet werden soll. Das 
kann dann schon recht viel werden.

Daher habe ich mich entschlossen, einen Interrupt-Handler zu schreiben, 
der Prioritäten verwaltet.
Dazu springe ich in der Vectortabelle nicht direkt auf das 
Unterprogramm, sondern auf das Label für die Priorität. Dort wird dann 
ein Prioritätenregister gesetzt.
Anschließend wird der Interrupthandler aufgerufen und arbeitet nach 
Priorität alle Interrupts ab, bei denen das Flag sitzt.
Natürlich werden alle vom Interrupt-Handler benutzen Register im Stack 
gesichert.

Das ganze funktioniert tadellos. Selbst wenn ich einen bereits laufenden 
Interrupt erneut auslöse, wird dieser erst beendet und anschließend 
gleich nochmal bearbeitet.

Einziger Nachteil ist, man braucht etwas extra Rechenzeit für den 
Interrupt-Handler.

von Klaus (Gast)


Lesenswert?

Ch D. schrieb:
> am anfang des Ints: __asm("cli");//Interupts verbieten
> am ende des Ints :  __asm("sei");//Interupts wieder erlauben.

NEIN, NEIN, NEIN!!!

Erstens ist es überflüssig, das der AVR die Interrupts von ganz alleine 
sperrt, wenn ein IRQ ausgelöst wird.

Zweitens erzeugst du gerade genau durch das sei am ende der ISR genau 
das, was du eigentlich verhindern wolltest!  Normalerweise werden die 
Interrupts erst wieder beim Rücksprung (also beim reti) wieder 
freigegeben. Wenn du nun sein sei ans Ende der ISR schreibst, werden sie 
vorher wieder freigegeben und anstehende interrupt werden bearbeitet, 
bevor der aktuelle verlassen und damit z. B. der Stack aufgeräumt wurde.

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.