Forum: Mikrocontroller und Digitale Elektronik Hohe Frequenz bei AVR-Interrupts


von Ben _. (burning_silicon)


Lesenswert?

Ich habe nochmal zwei Fragen zu Interrupts beim AVR bei denen ich mich 
absichern möchte bevor ich es in der Praxis erprobe...

1.
Verträgt ein ATMega644 Timer-generierte Interrupts mit 20kHz? Die 
Interruptroutine soll nur prüfen ob sie aktiv ist, wenn ja einen Wert 
aus einer Tabelle im Flash laden und diesen an einem Port ausgeben. 
Viele Takte braucht das nicht und bei 20Mhz hätte ich 1000 Takte bis zum 
nächsten Interrupt Zeit. Den Controller würde ich dafür mit den maximal 
möglichen 20Mhz oder wenn nötig mit dem nächstkleineren Baudratenquarz 
(18,432Mhz) betreiben.

2.
Wie kann ich verhindern, daß diese Interrupt-Routine z.B. durch weitere 
Interrupts unterbrochen wird? Muß ich während der Abarbeitung der 
Interrupt-Routine Interrupts global deaktivieren und danach wieder 
aktivieren? Mein Problem ist, daß diese "20kHz-Routine" einigermaßen 
zeitkritisch ist. Ich muß irgendwie sicherstellen, daß diese Routine 
beim Auslösen durch den Timer definitiv abgearbeitet wird bevor der 
Controller (wieder) was anderes macht.
   Problematisch könnte sein wenn sofort nach dem Timer-Interrupt ein 
anderer Interrupt die Routine unterbricht bevor die Interrupts global 
deaktiviert sind. Kann man das irgendwie verhindern oder bleibt da ein 
Restrisiko?
   Vergisst der AVR Interrupts, die während der "Sperre" durch die 
Deaktivierung der Interrupts auftreten oder werden die nach dem 
Wiederzulassen ausgeführt?

Wenns einer weiß dann schon mal Danke im Voraus!

von Purzel H. (hacky)


Lesenswert?

Eine Interrupt Routine wird nicht unterbrochen. 20kHz sollten sehr gut 
machbar sein, da 1000 Takte dazwischen sind.

von Wilhelm F. (Gast)


Lesenswert?

Interrupts sind eigentlich ein wesentliches Merkmal von µC. Man kann die 
Interruptbelastung gerne über 90% der Gesamtlaufzeit hoch fahren, wenn 
man das möchte, und wenn das Hauptprogramm sonst nicht viel zu tun hat. 
Es ist aber immer darauf zu achten, daß man im Interrupt nur das 
allernötigste tut, um ihn schnellstens wieder zu beenden.

Wie die Interruptstruktur deines µC ist, das mußt du in der 
Dokumentation dazu suchen.

von Neumann (Gast)


Lesenswert?

Vorallem dabei auch die Interrupt-Prioritäten beachten...

von Hannes (Gast)


Lesenswert?

Ein AVR kennt keine Interrupt-Prioritäten.

von Ben _. (burning_silicon)


Lesenswert?

Eben. So komplex wie der x86 ist der bei weitem nicht.

Weiß denn jemand ob der beim Auslösen eines Interrupts das 
Interrupt-Flag löscht und beim Interrupt Return wieder setzt?

von Ulrich (Gast)


Lesenswert?

Die 8 Bit AVRs haben keine Prioritäten im eigentlichen Sinn. Das Problem 
ist also weniger das der Timer Interrupt von einem anderen unterbrochen 
wird, sondern das ein anderer Interrupt noch läuft, wenn der Timer 
Interrupt auftritt. Eine kleine Verzögerung von bis zu etwa 5-10 Zyklen 
läßt sind dabei nicht vermeiden, auch wenn man in den anderen 
Interruptroutinen früh Interrupts wieder frei gibt.

20 kHz oder 1000 Zyklen sind keine Problem, das ist noch nicht einmal 
besonders häufg. Eine kurze Interruptroutine beim AVR liegt so in der 
Größenordnung 20 Zyklen in ASM.  Bei einer Hochsprache kommen meist noch 
ein paar extra Zyklen dazu, je nach Compiler.

Bei den meisten Intrrupts wird das auftreten eines Interrupts in einem 
Flag gespeichert. Der Interrupts wird entsprechend ggf. Nachgeholt und 
geht nicht verloren. Nur wenn in der Zeit in der Interrupts gesperrt 
sind der eine Interrupt 2 mal auftritt, wird der Interrupt nur 1 mal 
nachgeholt. Beim nachholen der Interrupts gilt die Reihenfolge der 
Interruptsvektoren, nicht die in der die Events aufgetreten sind.

von Ulrich (Gast)


Lesenswert?

Beim Interruptaufruf wird das Globale Interuptflag im Status Register 
gelöscht (entpricht CLI). Beim Rücksprung aus dem Interrupt wird das 
Globale Interuptflag wieder hergestellt (entspricht SEI). Man kann per 
SEI in der ISR auch erlauben dass die ISR unterbrochen wird.

Bei den meisten Interruptquellen wird zusätzlich bei Interruptaufruf das 
Flag im SFR, das den Interrupt signalisiert automatisch gelöscht.

von Klaus (Gast)


Lesenswert?

> Ein AVR kennt keine Interrupt-Prioritäten.

Wohl, bitte Doku lesen.

Eine laufende Interrupt-Routine wird beim AVR nicht durch weitere 
Interrupts unterbrochen (es sei denn, man reaktiviert die Interrupts 
innerhalb der Interrupt-Routine). Der AVR merkt sich, dass während der 
Interrupt-Routine weitere Interrupts aufgetreten sind und holt diese 
dann nach, wenn die Interrupt-Routine abgeschlosen ist. Wobei sich der 
AVR nur merkt, dass ein bestimmter Interrupt aufgetreten ist, und nicht 
wie oft. Wenn mehrere unterschiedliche Interrupts auf der Warteliste 
stehen, werden sie entsprechend in der Reihenfolge ihrer Prioritäten 
abgearbeitet.

irgendwo habe ich nocht ein Gerät liegen, bei dem ein AT2313 mit 8 Mhz 
intern Timer-generierte Interrupt mit über 30 kHz bedient. Nebenher 
kommunziert der AVR noch per UART mit der Aussenwelt, wodurch zusätzlich 
noch weitere Interrupts mit bis zu etwa 23 kHz dazukommen.

- Klaus

von Wilhelm F. (Gast)


Lesenswert?

Klaus schrieb:

> irgendwo habe ich nocht ein Gerät liegen, bei dem ein AT2313 mit 8 Mhz
> intern Timer-generierte Interrupt mit über 30 kHz bedient. Nebenher
> kommunziert der AVR noch per UART mit der Aussenwelt, wodurch zusätzlich
> noch weitere Interrupts mit bis zu etwa 23 kHz dazukommen.

Alles kein Problem, wenn es richtig gestaltet ist. Ein Standard-8051 
konnte sowas vor 30 Jahren auch schon. Beim ARM7, LPC2000, erreichten 
wir schon Interruptfrequenzen von einigen 100.000 pro Sekunde. Wenn man 
in den Interrupts einen Pin bewegt, kann man die Aktivitäten auch sehr 
gut am Oszi darstellen, um die tatsächliche Interruptbelastung ein wenig 
zu beurteilen.

Der 8051 war so gestaltet, daß zwischen Interrupts immer mindestens ein 
Befehl des Hauptprogrammes abgearbeitet wird. Wohl, damit das nicht ganz 
zu kurz kommt. Beim älteren 8085 war das noch nicht so, wenn ich mich 
recht erinnere. Da hatten sie also schon was dazu gelernt.

Um zu sehen, was im Interrupt und mit dem Programm passiert, arbeitete 
ich früher schon mal mit Pseudo-Single-Step per Software mit einem per 
Software entprellten Taster am externen Interrupt-Pin, ohne Debugger, 
das geht alles auch. Um den Interrupt quasi festzuhalten. Zustände von 
Flags konnte man da mit LEDs an einem Port ausgeben.

von Ben _. (burning_silicon)


Lesenswert?

> Beim Interruptaufruf wird das Globale Interuptflag im Status Register
> gelöscht (entpricht CLI). Beim Rücksprung aus dem Interrupt wird das
> Globale Interuptflag wieder hergestellt (entspricht SEI). Man kann per
> SEI in der ISR auch erlauben dass die ISR unterbrochen wird.
Danke! Das sollte meine Sorgen wegen unterbrochenen Interrupt-Routinen 
vermeiden, schön daß die Controller das machen.

Die 20kHz hab ich nicht als Problem gesehen, ich wollte nur sichergehen 
daß ich nicht von irgendwelchem Mist überzeugt bin und am Ende damit 
Schiffbruch erleide.

Für komplexe Aufgaben nehm ich keine Interrupts, da würde ich in der ISR 
nur ein Flag setzen und die eigentliche Aufgabe in der Hauptschleife 
ausführen.

von Ulrich (Gast)


Lesenswert?

Eine ISR die nur ein Flag setzt kann man sich auch fast sparen, denn zum 
auslösen der ISR setzt die Hardware in den meisten Fällen auch schon ein 
Bit. Man kann das Bit auch direkt nutzen, ohne eine ISR.

Die AVRs führen normal zwischen 2 Interrupts auch wenigstens einen 
Befehl des Hauptprogramms aus. Man kann das unterdrücken, wenn man die 
ISR nicht mit RETI, sondern mit  SEI + RET beendet: mit SEI ist dann 
sozusagen die ISR zu Ende, und RET ist der eine Befehl der dann 
ausgeführt wird.

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.