Archiv verlassen und diese Seite im Standarddesign anzeigen : Usart interrupt Atmega8 prioritat
Arexx-Henk
16.04.2006, 21:06
Hallo,
Es handelt sich um Atmega8.
innerhalb main() wird ein Warteschleife Funktion angerufen.
Die Funktion ist etwas wie:
for(i=0;i<1000;i++){
for(j=0;j<1000;j++){
}
}
Wenn wahrend die Warteschleife ein usart von aussen angesteurt wird, wird kein usart interrupt aktiviert. Wenn die Warteschleiffe beendet ist da erscheint in die usart-interrupt funktion ein usart overrun error.
Die usart interrupt funktion funktioniert sonst normal.
Ich dachte die usart wird auch ein Warteschleiff unterbrechen, oder irre ich mich hier?
Gruss
Henk
SprinterSB
16.04.2006, 21:12
Ja klaro. Einer IRQ ist es egal, wie dein Programm aussieht. IRQs müssen natürlich global aktiviert sein ein der betreffende IRQ muss zugelassen sein.
Arexx-Henk
17.04.2006, 19:33
Jetzt hab ich die ursache gefunden.
Die Warteschleiffe wird ausgefuhrt innerhalb eine interrupt function.
Im Atmega pdf steht dass warend die ausfuhrung eines interrupt die globalen interrupt immer 'disabled' ist!
Ich habe immer (offensichtlich fals) gedacht dass ein interrupt mit eine hoheren prioritat ein anderes interrupt mit niedrigen prioritat interuppieren konnte....
Jetzt denke ich dass, wenn wahrend die ausfuhrung von interrupt A sich zwei andere interrupts B und C sich melden, nachdem interrupt A fertig ist die interrupt B oder C, derjenige der die hochste prioritat besitzt, zuerst ausgefuhrt wird.
Hat mich schon wieder manche Stunde gekostet das heraus zu finden...
Gruss
Henk
SprinterSB
17.04.2006, 23:08
Jau, genauso ist das mit A, B, und C ;-)
Falls eine ISR durch eine andere IRQ unterbrochen werden sollte, kann man einfach an den Anfang der ISR ein sei() schreiben.
Noch einfacher deklariert man die ISR (avr-gcc 3.x) mit INTERRUPT() anstatt mit SIGNAL(), und avr-gcc mache den passenden Code. Ist auch in GCC erklärt.
Arexx-Henk
18.04.2006, 09:12
Aha,
also, jetzt ist mir ganz klar wie INTTERUPT() und SIGNAL() funktionieren und was die unterschied ist.
Schon wieder etwas gelernt!
Danke
Gruss
Henk
Die Namen sind auch missverständlich.
Bei SIGNAL sind die Interrupts während der Ausführung deaktiviert (Implizites cli() am Anfang der Interrupt Routine.
Bei INTERRUPT bleiben die Interrupts aktiviert. Eine INTERRUPT-Routine kann also von weiteren Interrupts unterbrochen werden. Da das schnell zu einem Stacküberlauf führen kann, sollten INTERRUPTS wenn möglich vermieden und ansonsten sehr vorsichtig eingesetzt werden.
BTW, in den neuen Versionen des avr-gcc ist die Benennung geändert worden. Aus SIGNAL wurde ISR (was IMHO dem Sinn viel näher kommt).
Arexx-Henk
18.04.2006, 09:42
Ich mochte noch dazu bemerken:
SIGNAL:
ist die normale weise wie die Atmega8 hardwaremassig funktioniert.
INTERRUPT
ist (fur Atmega) die weise da braucht die programmierer (oder compiler) die sei() instruction selber zu zu fugen innerhald eine ISR.
Ich hatte ein grosseres project gemacht mit einen Philips microcontroller der hardwaremassig wie 'INTERUPT' functionierte und nicht wie 'SIGNAL'.
Deswegen war ich mit dem Atmega auf dem falschen Spur gefahren.
Gruss
Henk
SprinterSB
18.04.2006, 10:40
INTERRUPT ist vor allem dann zweckmässig, wenn manche ISRs eine kleine Interrupt-Respond-Time haben müssen und andere ISRs vergleichsweise komplex sind und lange dauern.
Dann macht man die lange ISR unterbrechbar und die kurzen, schnell abzuarbeitenden als normale SIGNAL().
Abstürzen tut da nix. Ein fehlerhaftes Programm nur mit SIGNAL() schmiert genauso ab ;-)
In der 4er Version scheint es kein Analogon zu INTERRUPT zu geben, da muss man selber mit den Attributen rumhudeln.
Übrigens ist
SIGNAL (...)
{
sei();
...
}
NICHT gleichbedeitend mit
INTERRUPT (...)
{
...
}
Letzteres führt zu teilweise deutlich kleineren Response-Zeiten, weil das sei schon am Anfang des ISR-Prologs eingefügt wird!
Ein cli() am Ende der ISR braucht man übrigens nicht. SREG steht ja aufm Stack.
Abstürzen tut da nix. Ein fehlerhaftes Programm nur mit SIGNAL() schmiert genauso ab
Deswegen steht da oben ja auch der Konjunktiv :D
Lange ISRs sind ja sowieso Pfui (auch wenn sie sich manchmal vielleicht nicht vermeiden lassen) - und was lang ist, ist ja relativ.
Ich finde die Änderung von SIGNAL nach ISR allerdings sehr sinnvoll. Viele Einsteiger haben SIGNAL und INTERRUPT genau anders herum verstanden.
SprinterSB
18.04.2006, 11:08
Ich find's eher nervig, wenn sich dauernd die API ändert: andere Makro-Namen, Dateinamen, Vektor-Namen...
Wer die Doku zu SIGNAL() nicht gelesen hat, tut es wohl auch nicht, wenn das Ding plötzlich ISR() heisst und der Kaiser neue Kleider anhat. ;-)
Lange ISR sollte man vermeiden -- vor allem dann, wenn darin nix weiter getan wird, als zu warten, also im Endeffekt NIX zu tun. Kategorisch oder dogmatisch braucht es aber nicht zu sein...
Man kann sein Programm zB so auslegen, daß es 3 Prioritätsstufen hat:
-- die unterste Ebene (normale Ausführungsebene)
-- mittlere Ebene: In einem INTERRUPT, der auch recht ausgewachsen sein darf
-- höchste Ebene: Typischerweise kurze Schnittstellen- und Interrupt-Bedienungen mit SIGNAL()
Den Code aus der mittleren Ebene auf die untere zu ziehen, kann sehr umständlich sein und das Programm schnell undurchschaubar machen. Zudem kommen lästige Synchronisierungen hinzu. Ausserdem verliert man dadurch Echtzeitigkeit, weil sich Code auf Ebene 1 nicht selbst unterbrachen kann. Macht man auf unterer Ebene nen unwichtigen Job und ist zB ne Zeit um, an der man was komplexes zu machen hat, wird's schnell ätzend. Man müsste dan ständig nachschauen, ab's an der Zeit ist, den Cron-Job zu erledigen, ihn gegebenenfalls ausführen und danach die Arbeit wieder aufnehmen.
Mit einer mittelprioren Zwischenschicht steht die Sache jedoch ganz gut da.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.