Forum: Mikrocontroller und Digitale Elektronik AVR - Erkennen ob Interrupts verloren gehen


von Artur (Gast)


Lesenswert?

Hallo zusammen,

ich verwende bei meinem ATmega328 mehrere externe und interne 
Interruptquellen (timer, SPI, pinchange). Gibt es eine Möglichkeit zu 
erkennen, ob manche Interruptanforderungen verloren gehen, weil 
vielleicht die CPU nicht schnell genug alle Interruptanforderungen 
abarbeiten kann?

Natürlich könnte man eine theoretische worst-case Analyse aufgrund der 
Ausführungszeiten und vorraussichtlichen Häufigkeit der Interrupts 
machen, aber vielleicht geht es ja auch einfacher?

von Dennis H. (c-logic) Benutzerseite


Lesenswert?


von Artur (Gast)


Lesenswert?

Dennis Heynlein schrieb:
> Beitrag "Interrupts beim ATmega"

Hallo Dennis, ich finde in obigem Beitrag leider nur allgemeines zum 
Thema Interrupts. Ich habe auch den Interrupt Abschnitt im AVR-GCC 
Tutorial gelsen. Dort steht leider auch nichts dazu, wie man sein 
Programm auf mögliche Interruptverluste überprüfen kann.

Hat noch jemand eine Idee?

von Martin (Gast)


Lesenswert?

Kommt ein interrupt während eines interrupts, wird dieser nach der 
vorherigen interrupt-routine ausgeführt. Es geht also kein INT verloren

von test (Gast)


Lesenswert?

Martin schrieb:
> Kommt ein interrupt während eines interrupts, wird dieser nach der
> vorherigen interrupt-routine ausgeführt. Es geht also kein INT verloren

Außer der "Interrupt im Interrupt" kommt noch ein zweites mal, dann geht 
die erste Anforderung verloren. Wenn das eintritt hat man aber schon 
irgendwo anders ein Problem in seinem ganzen Konzept.

von Artur (Gast)


Lesenswert?

Martin schrieb:
> Kommt ein interrupt während eines interrupts, wird dieser nach der
> vorherigen interrupt-routine ausgeführt. Es geht also kein INT verloren

Hallo Martin, das ist mir bekannt. Mir geht es um den Fall, dass die CPU 
bereits einen Interrupt bearbeitet und dann ein weiterer Interrupt 
auftritt und kurze Zeit später noch einer gleichen Typs. Damit ginge 
dann der erste wartende Interrupt verloren. Mir geht es darum im 
Dauertest abzusichern dass es praktisch nicht vorkommt. Eine theoretisch 
worst-case-Betrachtung ersetzt es natürlich nicht, würde mir aber 
zusätzliche Sicherheit geben.

von Artur (Gast)


Lesenswert?

test schrieb:
> Außer der "Interrupt im Interrupt" kommt noch ein zweites mal, dann geht
> die erste Anforderung verloren. Wenn das eintritt hat man aber schon
> irgendwo anders ein Problem in seinem ganzen Konzept.

Ich habe wie beschrieben viele unterschiedliche Interruptquellen bei 
denen nicht genau bekannt ist, wie häufig sie auslösen. Da das ganze 
nicht wirklich kritisch ist würde es mir reichen, wenn nur selten mal 
ein Interrupt verloren geht. Das würde ich gerne praktisch absichern.
Mir ist klar, dass der Königsweg darin besteht alle Intteruptroutinen so 
kurz wie möglich zu gestalten und mit Flags zu arbeiten.

Mir geht es darum zu erkennen, ob / oder wie häufig praktisch Interrupts 
verworfen werden mußten wegen CPU Überlastung durch zu viele 
Interruptanforderungen pro Zeit.

von Falk B. (falk)


Lesenswert?


von Karl H. (kbuchegg)


Lesenswert?

Tja.
Egal was du machst, gibt es immer eine Grenze, ab der der µC nicht mehr 
mitkommt.

Dein Problem steckt aber hier
> Ich habe wie beschrieben viele unterschiedliche
> Interruptquellen bei denen nicht genau bekannt ist,
> wie häufig sie auslösen.
solange du da nichts drüber weißt, ist alles andere sinnlose Überlegung.

> Mir geht es darum zu erkennen, ob / oder wie häufig
> praktisch Interrupts verworfen werden mußten
Im schlimmsten Fall brauchst du dazu Hardware-Unterstützung.

Im einfachsten Fall kommt das ISR-Jobflag System zum Zug, bei dem du in 
der ISR vereinbaren kannst: Tritt der Interrupt auf, und ist das Jobflag 
schon (noch immer) gesetzt, dann wird es kritisch.

: Bearbeitet durch User
von Artur (Gast)


Lesenswert?

Falk Brunner schrieb:
> http://www.mikrocontroller.net/articles/Multitaski...

Hallo Falk, das ist ein sehr interessanter Link. Dort wird aber erklärt, 
wie man die Dauer des Hauptprogrammes über Interrupts im 
Millisekundentakt mittels Interrupt absichert und nicht ob sich 
Interrupts auftürmen.

von F. F. (foldi)


Lesenswert?

Ein voller Eimer Wasser läuft über und das Wasser läuft dann weg.

Da der µC ohnehin immer ein paar Takte braucht, wird dir, wenn die 
Interruptquelle schneller ist als der µC, sicher ein gleicher Interrupt 
verloren gehen.

von Oliver (Gast)


Lesenswert?

Artur schrieb:
> Mir geht es um den Fall, dass die CPU
> bereits einen Interrupt bearbeitet und dann ein weiterer Interrupt
> auftritt und kurze Zeit später noch einer gleichen Typs. Damit ginge
> dann der erste wartende Interrupt verloren.

Es gibt im Prozessor keine automatische Möglichkeit, diesen Fall zu 
erkennen.

> Mir geht es darum im
> Dauertest abzusichern dass es praktisch nicht vorkommt. Eine theoretisch
> worst-case-Betrachtung ersetzt es natürlich nicht, würde mir aber
> zusätzliche Sicherheit geben.

Du musst sicherstellen, daß deine ISRs kürzer sind, als die kürzeste 
vorkommende Interrupt-Wiederholzeit. Kennst du letztere nicht, kannst du 
nichts garantieren.

Zu der Analyse gehört aber such die Überlegung, was genau passiert, wenn 
du mal eine Interruptanforderung nicht bedienen kannst.

Oliver

von Peter D. (peda)


Lesenswert?

Artur schrieb:
> Ich habe wie beschrieben viele unterschiedliche Interruptquellen bei
> denen nicht genau bekannt ist, wie häufig sie auslösen.

Bei einigen Interrupts ist es bekannt, z.B. Timer, UART.
Bei anderen ist es egal, z.B. I2C, ADC, EEPROM, Master-SPI.

Erzähl dochmal genauer, welcher Interrupt bei Dir kritisch sein könnte.

von Artur (Gast)


Lesenswert?

Karl Heinz schrieb:
> Im einfachsten Fall kommt das ISR-Jobflag System zum Zug, bei dem du in
> der ISR vereinbaren kannst: Tritt der Interrupt auf, und ist das Jobflag
> schon (noch immer) gesetzt, dann wird es kritisch.

Hallo Karl Heiz, wäre super wenn das so ginge. Meinst du mit Jobflag das 
Interrupt Flag?

So wie ich das Datenblatt verstanden habe wird doch das Interruptflag, 
z.B. bei Pegelwechsel an einem Pin, auf 1 gesetzt (hier im EIFR – 
External Interrupt Flag Register), dann sofort der Interrupt 
angesprungen, dabei automatisch die 1 wieder gelöscht und dann der Code 
des Interrupts ausgeführt.

Währenddessen kann ein weiterer Pegelwechsel gleich nochmal das Flag von 
0 auf 1 setzten. Das Flag wird solange nicht 0, bis der Interrupt 
bearbeitet wird.

Wenn vor der Bearbeitung dieses wartenden Interrupts noch ein 
Pegelwechsel auftritt, wird das Interruptflag nochmals auf 1 gesetzt. Da 
es aber bereits auf 1 steht geht die Information verloren, dass jetzt 
eigentlich zweimal der Interruptcode ausgeführt werden müsste.

Der Interruptverlust bleibt doch leider unbemerkt, oder?

von Falk B. (falk)


Lesenswert?

@ Artur (Gast)

>> http://www.mikrocontroller.net/articles/Multitaski...

>Hallo Falk, das ist ein sehr interessanter Link. Dort wird aber erklärt,
>wie man die Dauer des Hauptprogrammes über Interrupts im
>Millisekundentakt mittels Interrupt absichert und nicht ob sich
>Interrupts auftürmen.

Bitte nochmals lesen und NACHDENKEN!

von Falk B. (falk)


Lesenswert?

@ Artur (Gast)

>Wenn vor der Bearbeitung dieses wartenden Interrupts noch ein
>Pegelwechsel auftritt, wird das Interruptflag nochmals auf 1 gesetzt. Da
>es aber bereits auf 1 steht geht die Information verloren, dass jetzt
>eigentlich zweimal der Interruptcode ausgeführt werden müsste.

>Der Interruptverlust bleibt doch leider unbemerkt, oder?

Ja. Das kann der AVR leider nicht erkennen, das könnte man nur in 
Hardware machen.

von Peter D. (peda)


Lesenswert?

Artur schrieb:
> Wenn vor der Bearbeitung dieses wartenden Interrupts noch ein
> Pegelwechsel auftritt, wird das Interruptflag nochmals auf 1 gesetzt. Da
> es aber bereits auf 1 steht geht die Information verloren, dass jetzt
> eigentlich zweimal der Interruptcode ausgeführt werden müsste.

Die eigentliche Frage ist, muß er das wirklich?
Oder ist es nur ein Prellen oder ein Störimpuls.

Das kann man allgemein nicht beantworten. Dazu muß man schon konkret 
wissen, was den Interrupt bewirkt und wie er ausgewertet werden soll.

Man muß sich also erstmal Gedanken machen, welche maximale 
Nutzsignal-Interruptrate erwarte ich von der Quelle.

von Artur (Gast)


Lesenswert?

Peter Dannegger schrieb:

>>> http://www.mikrocontroller.net/articles/Multitaski...
>>Hallo Falk, das ist ein sehr interessanter Link. Dort wird aber erklärt,
>>wie man die Dauer des Hauptprogrammes über Interrupts im
>>Millisekundentakt mittels Interrupt absichert und nicht ob sich
>>Interrupts auftürmen.
> Bitte nochmals lesen und NACHDENKEN!

Hallo Falk, ich bin nochmal durchgegangen und ich weiß wirklich nicht wo 
du da das Ei des Kolumbus versteckt siehst. In der Datei ACF?

In diesem Abschnitt?

Diese Überprüfung kann an zwei Stellen durchgeführt werden.

*    Am Ende der Hauptschleife nach Abarbeitung aller Ausgaben. Wenn 
hier die Variable flag_1ms schon wieder aktiv ist, dauerte die 
Abarbeitung länger als 1ms. Wenn man ein sehr strenges Timing 
sicherstellen möchte, ist das ein Fehler, der erkannt und signalisiert 
werden kann.

*    In der ISR. Wenn hier die Variable immer noch aktiv ist, wurde sie 
von der Hauptschleife noch nicht erkannt und zurück gesetzt. Das ist 
definitiv ein Fehler, denn jetzt würde ohne Fehlererkennung ein 
Timerdurchlauf von der Hauptschleife verschluckt werden. Diese Prüfung 
ist etwas nachgiebiger, weil zwischenzeitlich ein Durchlauf der 
Hauptschleife mehr als 1ms, jedoch nicht länger als 2ms dauern darf. 
Siehe auch den Abschnitt Interrupt#Zeitverhalten_eines_Timerinterrupts. 
Sinnvollerweise nutzt man nur eine der beiden Prüfungen, nicht beide 
zusammen.

von Karl H. (kbuchegg)


Lesenswert?

Artur schrieb:
> Karl Heinz schrieb:
>> Im einfachsten Fall kommt das ISR-Jobflag System zum Zug, bei dem du in
>> der ISR vereinbaren kannst: Tritt der Interrupt auf, und ist das Jobflag
>> schon (noch immer) gesetzt, dann wird es kritisch.
>
> Hallo Karl Heiz, wäre super wenn das so ginge. Meinst du mit Jobflag das
> Interrupt Flag?

Nein.
Ich meine die Technik des Jobflags
1
uint8_t Job;
2
3
ISR( ... )
4
{
5
  Job = 1;
6
}
7
8
int main
9
{
10
11
  ....
12
  while( 1 )
13
  {
14
15
     if( Job )
16
       ...

von Oliver (Gast)


Lesenswert?

Vielleicht mal etwas deutlicherer Klartext:

Solange du nicht weißt, in welchen Zeitabständen deine 
Interruptanforderungen kommen, und was es bedeutet, wenn du mal eine 
verpasst, brauchst du nirgends weiterzulesen. Dann hast du schlicht 
keine Chance, das Problem zu lösen. Geht nicht. Fertig.

Wenn du aber die kürzeste Zeit zwischen den Interruptanforderungen 
kennst, kannst du versuchen, deine ISR's noch kürzer zu gestalten. Das 
geht nicht ohne Zyklen zählen, oder ähnliche Anaylsen. Wenn du innerhalb 
der vorgegeben Zeit in der ISR alles abarbeiten kannst, prima.

Wenn nicht, so kannst du versuchen, ein eigenes Flag-System zu bauen, 
das z.B. die Interruptanforderung selber und die relevanten Daten dazu 
in eine queue schreibt. Die eigentlich Abarbeitung übernimmt dann das 
Hauptprogramm. Wenn deine ISR damit kurz genug wird, verlirst du keine 
Interrupts, aber die Abarbeitung bzw. Reaktion darauf kann verspätet 
erfolgen (eben erst dann, wenn das Hauptprogramm Zeit findet, den 
Request abzuarbeiten). Das funktioniert natürlich nur, wenn im Mittel 
das Haupprogramm schnell genug ist, alle Request abzuarbeite, ansonsten 
läuft deine Queue irgendwann über.

Wenn du es nicht schaffst, das Flag/Queue-System innerhalb der zur 
Verfügung stehehden ISR-Zeit abzuarbeiten, dann bist du wieder am 
Ausgangspunkt: Zu langsam...

Oliver

von Artur (Gast)


Lesenswert?

Karl Heinz schrieb:

> Ich meine die Technik des Jobflags
>
> uint8_t Job;
>
> ISR( ... )
> {
>   Job = 1;
> }
>
> int main
> {
>
>   ....
>   while( 1 )
>   {
>
>      if( Job )
>        ...

Wenn ich das richtig verstanden habe hilft diese Technik nur 
sicherzustellen, dass der Teil unter "if( Job )" nicht mehr Zeit 
benötigt als der Interrupt als Takt vorgibt.

Ich möchte aber sicherstellen, dass meine 3 unterschiedlichen Timer die 
ich verwende, mehrere Pinchange Interrupts und die SPI Kommunikation 
sehr zügig funktioniert und daher im Interrupt abgearbeitet werden soll. 
Die Main-Loop ist sehr voll mit Berechnungen, die eine sehr zeitnahe 
Ausführung auf Flag-Basis nicht ratsam machen.

von Artur (Gast)


Lesenswert?

Hallo Oliver,

vielen Dank für deine umfangreiche Antwort. Da sind viele gute Ideen 
dabei. Ich sehe, es gibt aber anscheinend keinen einfachen Mechanismus 
der mir sagen könnte ob das Interruptsystem überläuft.

Es sei denn Falk kann mich noch darauf stoßen.

von robin (Gast)


Lesenswert?

Um zu verhindern, dass dir keine interrupts verloren gehen, musst du die 
ISR so klein wie möglich halten. Bedeutet, serielle kommunikation in 
einen puffer zwischen speichern und diesen in der main-Schleife 
auswerter (solange der puffer voll ist).

Timer sind kritisch, da diese nicht später im Hauptprogramm ausgeführt 
werden dürfen, aber evtl kannst du im Hauptprogramm etwas die Daten 
vorbereiten und sie dann anschliesend nur im der ISR ausgeben.

Pin change interrupts kann man auch in einen puffer schreiben und später 
im Hauptprogramm auswerten.

Ein Rinspeicher beschreiben ist in unter 20 Takten möglich, wenn deine 
Auswertung eines interrupts länger als 20 takte benötigt, die daten in 
einen puffer schreiben und in der Hauptschleife auswerten.

Ganz verhindern kann man das "verschlucken" von interrupts nicht, aber 
in dem man die ISR so kurz wie möglich gestaltet kann man einiges 
erreichen.

Probleme können aber Taster machen, die prellen. Diese müsste man 
entweder in Hardware entprellen oder bei auftreten eines interrupts eine 
systemzeit mit abspeichern damit man ein prellen ausschliesen kann.

von Falk B. (falk)


Lesenswert?

@ Artur (Gast)

>Wenn ich das richtig verstanden habe hilft diese Technik nur
>sicherzustellen, dass der Teil unter "if( Job )" nicht mehr Zeit
>benötigt als der Interrupt als Takt vorgibt.

Ja.

>Ich möchte aber sicherstellen, dass meine 3 unterschiedlichen Timer die
>ich verwende, mehrere Pinchange Interrupts und die SPI Kommunikation
>sehr zügig funktioniert und daher im Interrupt abgearbeitet werden soll.

Kann man machen.

>Die Main-Loop ist sehr voll mit Berechnungen, die eine sehr zeitnahe
>Ausführung auf Flag-Basis nicht ratsam machen.

Alles eine Frage der Programmierung. Wenn man es will, kann man lange 
Berechnungen auf mehrere Schritte aufteilen und mit mehreren Aufrufen 
erledigen. Siehe Multitasking.

Aber was hast du denn konkret zu tun? So eine allgemeine Beschreibeung 
nützt wenig. Nenn mal ein paar konkrete Zahlen.

von Falk B. (falk)


Lesenswert?

@ Artur (Gast)

>dabei. Ich sehe, es gibt aber anscheinend keinen einfachen Mechanismus
>der mir sagen könnte ob das Interruptsystem überläuft.

Auf unterstet Ebene, nein. Schrieb ich bereits.

Beitrag "Re: AVR - Erkennen ob Interrupts verloren gehen"

Aber man kann es mal so sehen. Interrupts können nun durch andere, 
gerade laufende Interrupts blockiert und damit verschluckt werden, weil 
der AVR von hause aus keine Prioritäten für die Interrupts hat. Hält man 
aber alle ISRs kurz, kann das nicht passieren, auch nicht im 
schlimmsten, definierten Fall (den man ja berechnen/simulieren kann). 
Klar, wenn man maximal mit 10kHz rechnet, duch was auch immer ein Pin 
aber mit 100kHz toggelt, dann war's das. Aber sowas ist vermeidbar.

von cybmorg (Gast)


Lesenswert?

Wenn du feststellen willst, ob du Interrupts verlierst, musst du das 
Ueberlaufmanagement einfach selbst machen. Am Anfang der 
Interruptroutine einen Zaehler hochsetzen. Ist er groesser als 1, laeuft 
die Interruptroutine schon und du brichst ab. Ist er 1, gibst du die 
Interrupts wieder frei und machst die eigentliche Interruptbearbeitung. 
Am Ende der Bearbeitung sperrst du die Interrupts wieder und 
dekrementierst den Zaehler wieder. Alles, was groesser als Null ist, 
sind verlorene Interrupts. Die kannst du zum Beispiel auf eine andere 
Variable aufaddieren und in der Hauptschleife ausgeben. Nicht vergessen, 
den Zaehler wieder auf Null zu setzen, sonst war das die letzte 
Interruptausfuehrung. Alternativ kann man das Aufaddieren auch am Anfang 
der Interruptroutine machen, dann entgehen einem Deadlocks in der 
Interruptverarbeitung nicht.

von Artur (Gast)


Lesenswert?

cybmorg schrieb:
> Wenn du feststellen willst, ob du Interrupts verlierst, musst du
> das
> Ueberlaufmanagement einfach selbst machen. Am Anfang der
> Interruptroutine einen Zaehler hochsetzen. Ist er groesser als 1, laeuft
> die Interruptroutine schon und du brichst ab. Ist er 1, gibst du die
> Interrupts wieder frei und machst die eigentliche Interruptbearbeitung.
> Am Ende der Bearbeitung sperrst du die Interrupts wieder und
> dekrementierst den Zaehler wieder. Alles, was groesser als Null ist,
> sind verlorene Interrupts. Die kannst du zum Beispiel auf eine andere
> Variable aufaddieren und in der Hauptschleife ausgeben. Nicht vergessen,
> den Zaehler wieder auf Null zu setzen, sonst war das die letzte
> Interruptausfuehrung. Alternativ kann man das Aufaddieren auch am Anfang
> der Interruptroutine machen, dann entgehen einem Deadlocks in der
> Interruptverarbeitung nicht.

Hallo cyvmorg,
das hört sich nach einer guten Lösung an. Sie ist nicht einfach, sie 
erzeugt overhead, ab sie scheint machbar. Hast du sowas schon praktisch 
getestet?

von Thomas E. (thomase)


Lesenswert?

Artur schrieb:
> cybmorg schrieb:
>> Wenn du feststellen willst, ob du Interrupts verlierst, musst du
>> das
>> Ueberlaufmanagement einfach selbst machen. Am Anfang der
>> Interruptroutine einen Zaehler hochsetzen. Ist er groesser als 1, laeuft
>> die Interruptroutine schon und du brichst ab. Ist er 1, gibst du die
>> Interrupts wieder frei und machst die eigentliche Interruptbearbeitung.
>> Am Ende der Bearbeitung sperrst du die Interrupts wieder und
>> dekrementierst den Zaehler wieder. Alles, was groesser als Null ist,
>> sind verlorene Interrupts. Die kannst du zum Beispiel auf eine andere
>> Variable aufaddieren und in der Hauptschleife ausgeben. Nicht vergessen,
>> den Zaehler wieder auf Null zu setzen, sonst war das die letzte
>> Interruptausfuehrung. Alternativ kann man das Aufaddieren auch am Anfang
>> der Interruptroutine machen, dann entgehen einem Deadlocks in der
>> Interruptverarbeitung nicht.
>
> Hallo cyvmorg,
> das hört sich nach einer guten Lösung an. Sie ist nicht einfach, sie
> erzeugt overhead, ab sie scheint machbar. Hast du sowas schon praktisch
> getestet?

Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts 
gesperrt. D.h. die ISR wird kein zweites Mal erreicht.

mfg.

von Karl H. (kbuchegg)


Lesenswert?

Thomas Eckmann schrieb:

> Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts
> gesperrt.

Na ja.
Man kann sie freigeben.
Hier im Forum wird zwar meistens davon abgeraten, solange man aber weiß 
was man tut, kann man das natürlich machen.

von Artur (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts
> gesperrt. D.h. die ISR wird kein zweites Mal erreicht.
Die kann man sofort nach Eintritt in die ISR wieder einschalten mit 
sei().

Oder den Interrupt gleich richtig ausschalten, wie es hier geschrieben 
steht:
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial#Interrupts_mit_avr-gcc


#include <avr/interrupt.h>

ISR(XXX,ISR_NOBLOCK) /* veraltet: INTERRUPT(SIG_OVERFLOW0) */
{
    /* Interrupt-Code */
}

von Artur (Gast)


Lesenswert?

Ich meine natürlich Interrupt anschalten.

von Thomas E. (thomase)


Lesenswert?

Karl Heinz schrieb:
> Thomas Eckmann schrieb:
>
>> Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts
>> gesperrt.
>
> Na ja.
> Man kann sie freigeben.
> Hier im Forum wird zwar meistens davon abgeraten, solange man aber weiß
> was man tut, kann man das natürlich machen.

Leider wissen die meisten das aber nicht.

mfg.

von cybmorg (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Das funktioniert nicht. Währrend eine ISR läuft, sind die Interrupts
> gesperrt. D.h. die ISR wird kein zweites Mal erreicht.

Im Text habe ich explizit erklaert, wann die Interrupts freizugeben und 
zu sperren sind. Wie man das ueberlesen kann, ist mir unverstaendlich.

von cybmorg (Gast)


Lesenswert?

Artur schrieb:
> Hallo cyvmorg,
> das hört sich nach einer guten Lösung an. Sie ist nicht einfach, sie
> erzeugt overhead, ab sie scheint machbar. Hast du sowas schon praktisch
> getestet?

Das ist eigentlich recht einfach, ich arbeite oft mit mehreren 
Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung 
verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten. 
Der Ueberlaufzaehler ist eine einfache Erweiterung davon. Overhead 
erzeugt die Loesung natuerlich schon - aber wenn du so nah am Limit 
deines Kontrollers bist, dass es dafuer nicht mehr reicht, hast du 
wahrscheinlich noch andere Probleme.

von Thomas E. (thomase)


Lesenswert?

cybmorg schrieb:

> Im Text habe ich explizit erklaert, wann die Interrupts freizugeben und
> zu sperren sind. Wie man das ueberlesen kann, ist mir unverstaendlich.

>> Am Ende der Bearbeitung sperrst du die Interrupts wieder

Wie das funktionieren soll, ist mir unverständlich.

mfg.

von Thomas E. (thomase)


Lesenswert?

cybmorg schrieb:
> Das ist eigentlich recht einfach, ich arbeite oft mit mehreren
> Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung
> verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten.
Wer will das wissen?

Ein Atmega 328 hat keine verschiedenen Prioritätsebenen.

Im Ausgangspost hat der TO explizit erklaert, daß er einen Atmega 328 
benutzt. Wie man das ueberlesen kann, ist mir unverstaendlich.

mfg.

von cybmorg (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Ein Atmega 328 hat keine verschiedenen Prioritätsebenen.

Natuerlich hat er das nicht. Sonst muesste ich das ja nicht haendisch 
implementieren.

> Im Ausgangspost hat der TO explizit erklaert, daß er einen Atmega 328
> benutzt. Wie man das ueberlesen kann, ist mir unverstaendlich.

Das liebe ich so hier am Forum: Wenn man in's Klo gegriffen hat, ist 
Zugeben und Schnabel halten die letzte Alternative - lieber aus vollen 
Rohren feuern, vielleicht merkt es keiner!

> Wie das funktionieren soll, ist mir unverständlich.

Meinst du den ganzen Ablauf, oder nur das Sperren am Ende der 
Bearbeitung? Letzteres macht ein einfaches cli(). Oder ist unklar, 
warum? Wenn ich den Interruptzaehler anfasse, muss das gegen 
nebenlaeufige Zugriffe gesichert passieren, also werden die Interrupts 
vorher wieder gesperrt. Die Freigabe, dass ueberhaupt wieder Interrupts 
bearbeitet werden, geschieht danach "automatisch", wie ueblich.

von Sebastian W. (wangnick)


Lesenswert?

cybmorg schrieb:
> Das ist eigentlich recht einfach, ich arbeite oft mit mehreren
> Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung
> verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten.
> Der Ueberlaufzaehler ist eine einfache Erweiterung davon.

Hallo cybmorg,

schicke Sache. Hast du da mal etwas (Pseudo-)code zur Veranschaulichung? 
Mich würde insbesonders der Code am Ende jeder ISR interessieren, der 
dann explizit (?) die aufgelaufenen Interrupts niedrigerer Priorität 
abarbeitet ...

LG, Sebastian

von Thomas E. (thomase)


Lesenswert?

cybmorg schrieb:

> Wenn ich den Interruptzaehler anfasse, muss das gegen
> nebenlaeufige Zugriffe gesichert passieren, also werden die Interrupts
> vorher wieder gesperrt. Die Freigabe, dass ueberhaupt wieder Interrupts
> bearbeitet werden, geschieht danach "automatisch", wie ueblich.

Und wenn in der Zeit zweimal der gleiche Interrupt auftritt, hast du mit 
dem Gehampel gar nichts gewonnen. Völliger Humbug das Ganze.

mfg.

: Bearbeitet durch User
von Artur (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Und wenn in der Zeit zweimal der gleiche Interrupt auftritt, hast du mit
> dem Gehampel gar nichts gewonnen. Völliger Humbug das Ganze.

Wenn gerade ein Interrupt bearbeitet wird, könnte ein schnell folgender 
Interrupt, der ja nur kurz den Zähler erhöht und sich dann selbst 
beendet, im ersten Interrupt direkt angehängt werden. Schneller käme ja 
ein mit Flag zwischengepeicherter Interrupt auch nicht zum Zug.

von Falk B. (falk)


Lesenswert?

Mein Gott, hier wird schon wieder ewig über vermeintliche Lösungen 
diskutiert, ohne des reale Problem WIRKLICH zu kennen!

Beitrag "Re: AVR - Erkennen ob Interrupts verloren gehen"

von Thomas E. (thomase)


Lesenswert?

Artur schrieb:

> Wenn gerade ein Interrupt bearbeitet wird, könnte ein schnell folgender
> Interrupt, der ja nur kurz den Zähler erhöht und sich dann selbst
> beendet, im ersten Interrupt direkt angehängt werden. Schneller käme ja
> ein mit Flag zwischengepeicherter Interrupt auch nicht zum Zug.

Den Interrupt gibt es aber nicht umsonst. Der kostet jede Menge Zeit, 
die ja angeblich nicht vorhanden ist. Sonst könnte man sich das ja alles 
grundsätzlich sparen. Das Zählergehampel mit Wiederfreigabe kann aber 
auch nicht zu 100% garantieren, daß kein Interrupt verloren geht. 
Maximal ein Interrupt kann im Flagregister gespeichert werden. Mehr gibt 
die AVR-Hardware einfach nicht her.
Tritt allerdings während einer ISR derselbe Interrupt nochmals auf, kann 
man diesen auch durch Abfrage des Interrupt-Flags vor Verlassen der ISR 
bearbeiten. Wenn es denn unbedingt sein muß.

Man kann aber auch vernünftig programmieren lernen und sich diesen Mist 
komplett ersparen.

mfg.

von cybmorg (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> Das Zählergehampel mit Wiederfreigabe kann aber
> auch nicht zu 100% garantieren, daß kein Interrupt verloren geht.

Es gibt Ingenieure, die Probleme loesen und Ingenieure, die endlos 
darueber referieren koennen, was an Loesungsansaetzen anderer schlecht 
ist und wieso das Problem sowieso nicht loesbar ist. Rate mal, welche 
von Beiden keiner braucht.

von Thomas E. (thomase)


Lesenswert?

cybmorg schrieb:
> Thomas Eckmann schrieb:
>> Das Zählergehampel mit Wiederfreigabe kann aber
>> auch nicht zu 100% garantieren, daß kein Interrupt verloren geht.
>
> Es gibt Ingenieure, die Probleme loesen und Ingenieure, die endlos
> darueber referieren koennen, was an Loesungsansaetzen anderer schlecht
> ist und wieso das Problem sowieso nicht loesbar ist. Rate mal, welche
> von Beiden keiner braucht.

Mehr als so ein blödes Gelaber fällt dir jetzt nicht ein?

In der Digitaltechnik gibt es zwei Möglichkeiten. Entweder es 
funktioniert zu 100% oder es funktioniert nicht. Dazwischen ist gar 
nichts.

mfg.

von cybmorg (Gast)


Lesenswert?

Thomas Eckmann schrieb:
> In der Digitaltechnik gibt es zwei Möglichkeiten. Entweder es
> funktioniert zu 100% oder es funktioniert nicht. Dazwischen ist gar
> nichts.

Da du von nichts, was du baust/programmierst die Funktion zu 100% 
garantieren kannst, reduziert sich bei deiner Sichtweise jeglicher 
Output deiner Taetigkeit auf: Gar nichts. Wie du das deinem Arbeitgeber 
vermittelst, dass er dich fuer gar nichts bezahlen soll, wuerde mich 
interessieren.

von Thomas E. (thomase)


Lesenswert?

cybmorg schrieb:
> Thomas Eckmann schrieb:
>> In der Digitaltechnik gibt es zwei Möglichkeiten. Entweder es
>> funktioniert zu 100% oder es funktioniert nicht. Dazwischen ist gar
>> nichts.
>
> Da du von nichts, was du baust/programmierst die Funktion zu 100%
> garantieren kannst, reduziert sich bei deiner Sichtweise jeglicher
> Output deiner Taetigkeit auf: Gar nichts. Wie du das deinem Arbeitgeber
> vermittelst, dass er dich fuer gar nichts bezahlen soll, wuerde mich
> interessieren.

Das muss ich sogar garantieren, du Witzfigur.

mfg.

von Timm T. (Gast)


Lesenswert?

cybmorg schrieb:
> Das ist eigentlich recht einfach, ich arbeite oft mit mehreren
> Interruptebenen und dazu muss ich die manuelle Ueberlaufsteuerung
> verwenden, um die Prioritaeten der Interruptebenen zu gewaehrleisten.

Wozu brauchst Du im AVR mehrere Interruptebenen? Ein Interrupt ist so 
kurz wie möglich zu halten, und das heisst, wirklich wenige Takte. 
Großartige Software-Division oder Speicher umkopieren oder PID-Regler 
berechnen macht man einfach nicht im Interrupt.

Zum Beispiel Uart: Byte einlesen, in Ringpuffer schreiben, Ringbuffer 
Pointer inc, Flag setzen, dass Daten vorhanden, raus. Braucht vielleicht 
20 Takte. Die Auswertung, was dann mit den Daten passiert, machst Du im 
Hauptprogramm.

von Artur (Gast)


Lesenswert?

> cybmorg schrieb:
> Mehr als so ein blödes Gelaber fällt dir jetzt nicht ein?

> Thomas Eckmann schrieb:
> Das muss ich sogar garantieren, du Witzfigur.

Kleiner Kampf? Das ist ein Spiel mit kleinen ferngelenkten Modellpanzern 
über's Internet. Ist umsonst. Ich wär' dabei... 
Beitrag "Panzer über Internet fernsteuern für Jedermann"

von Falk B. (falk)


Lesenswert?

@ Timm Thaler (timm-thaler)

>Wozu brauchst Du im AVR mehrere Interruptebenen?

Andere Controller haben die und können sie zweckdienlich nutzen. Der AVR 
hat keine, man kann und muss damit leben.

> Ein Interrupt ist so
>kurz wie möglich zu halten,

Ja.

> und das heisst, wirklich wenige Takte.

Nein. So kurz wie NÖTIG! Das kann je nach Anwendung auch mal ne 
Millisekunde oder mehr sein. Manchmal auch nur 10us.

>Großartige Software-Division oder Speicher umkopieren oder PID-Regler
>berechnen macht man einfach nicht im Interrupt.

Siehe oben.

>Zum Beispiel Uart: Byte einlesen, in Ringpuffer schreiben, Ringbuffer
>Pointer inc, Flag setzen, dass Daten vorhanden, raus. Braucht vielleicht
>20 Takte.

In Hardcore Assembler bestenfalls, in C geht unter 50 Takten kaum was. 
Aber selbst damit lässt sich ganz gut leben.

Aber solange der OP nicht mal mit seinen realen Aufgaben und 
Anforderungen rausrückt, ist das alles sinnlos. Fakt ist, der AVR ist 
schon ein fixes Kerlchen, der auch ohne Interruptlevel verdammt viel 
verdammt schnell machen kann. Ohne Interrupts zu verschlucken.

von Timm T. (Gast)


Lesenswert?

Falk Brunner schrieb:
> Das kann je nach Anwendung auch mal ne
> Millisekunde oder mehr sein.

Ich hab ja schon viel mit AVRs verbrochen, für das ich mich heute 
schäme. Aber Interrupts, die ne Millisekunde, also um die 10.000 Takte 
dauern, sind mir noch nicht untergekommen. Nicht dass ich nicht glaube, 
dass es sowas gibt, aber ich kann mir nich vorstellen, wo man sowas 
braucht.

Hast Du ein paar Beispiele? Das interessiert mich ernsthaft, man lernt 
ja nie aus.

Falk Brunner schrieb:
> In Hardcore Assembler bestenfalls, in C geht unter 50 Takten kaum was.

Wenn ich C programmieren wöllte, nähme ich nen PC. ;-) Im AVR wird 
natürlich ASM programmiert.

von Sebastian W. (wangnick)


Lesenswert?

Artur schrieb:
>> cybmorg schrieb:
>> Mehr als so ein blödes Gelaber fällt dir jetzt nicht ein?
>
>> Thomas Eckmann schrieb:
>> Das muss ich sogar garantieren, du Witzfigur.

Das ist jetzt aber eine falsche Quellenangabe. Beide Zitate sind von 
Thomas. Zur Vollständigkeit fehlt aber noch:

Thomas Eckmann schrieb:
> Man kann aber auch vernünftig programmieren lernen und sich diesen Mist
> komplett ersparen.

cybmorg hat hier einen interessanten Beitrag geleistet, der für 
bestimmte Situationen für mich sicherlich hilfreich sein wird. Thanks 
for that!

Ob diese Lösung für den OP geeignet ist sei dahingestellt. Bei 
entsprechendem Vorwissen kann der OP das sicher auch selbst entscheiden.

Auf Risiken, zum Beispiel die Möglichkeit von Starvation, die nötige 
Synchronisation des Zugriffs auf gemeinsame Resourcen auch in der ISR, 
könnte man hinweisen.

Ich sehe aber keinen triftigen Grund angesichts eines fachlichen 
Beitrags hier persönlich beleidigend zu werden.

LG, Sebastian

von Artur (Gast)


Lesenswert?

An alle ein herzliches Dankeschön!

Hallo Falk, ich möchte das Programm zumindest vorerst nicht an die 
Öffentlichkeit geben, entschuldige bitte. Es läuft ja auch schon recht 
stabil, lediglich vereinzelt gibt es Abstürze, die vielleicht ein 
Interruptüberlauf sein könnten, oder was ganz anderes. Heute habe ich 
wieder einen Bug gefunden, ein vergessenes Atomic. Wenns richtig gut 
läuft wars das schon.

Besonderen Dank an cybmorg, für die unkonventionelle Idee dem AVR 
Fähigkeiten abzutrotzen, die eigentlich nicht vorgesehen sind. Sowas 
finde ich großartig. Meine Fragen sind beantwortet. Vielen Dank für eure 
Hilfsbereitschaft! Ich werde mich revanchieren. Lasst euch nicht 
abhalten weiterzudiskutieren.

Schönen Gruß
Artur

von Falk B. (falk)


Lesenswert?

@ Timm Thaler (timm-thaler)

>Hast Du ein paar Beispiele? Das interessiert mich ernsthaft, man lernt
>ja nie aus.

Ich hab hier eine Steuerung in einem kommerziellen Gerät, dort läuft ein 
kooperatives Multitasking. Ein Timer mit 10ms gibt den Grundtakt vor. In 
diesem Timer steckt die wesentliche Verarbeitung, d.h. Datenerfassung 
über einen externen ADC, PI-Regler, Überwachung der Parameter, Daten für 
den Netzwerktransport vorbereiten, wobei hier nochmal ein Teiler in 
Software drinsteckt, d.h. nicht alle Funktionen laufen mit 10ms 
Periodendauer, die meisten deutlich langsamer! Dieser Timerdurchlauf 
dauert je nach Konstellation bis zu 4ms. Was bei 10ms Periodendauer kein 
Problem ist.
Man muss aber auch sagen, dass dieser Controller kein ganz normales C 
nutzt, es ist ein etwas eigenes Framework, wo es nur ereignisgesteuerte 
Funktionen gibt und eben diese Timer. Eine main-Funktion gibt es nicht!

>Wenn ich C programmieren wöllte, nähme ich nen PC. ;-) Im AVR wird
>natürlich ASM programmiert.

Jaja, als Hobby ganz nett, im produktiven Einsatz aber meist nicht 
sinnvoll. Bestenfalls die ISR könnte man als reinen Assembler machen, 
wenn es denn WIRKLICH nötig ist. Ist es aber gar nicht so oft wie man 
denkt.

von Timm T. (Gast)


Lesenswert?

Falk Brunner schrieb:
> kooperatives Multitasking. Ein Timer mit 10ms gibt den Grundtakt vor. In
> diesem Timer steckt die wesentliche Verarbeitung, d.h. Datenerfassung
> über einen externen ADC, PI-Regler, Überwachung der Parameter, Daten für
> den Netzwerktransport vorbereiten...

Also nichts, was man mit einem Timer auf 10ms mit 15 Takten, einer 
Mainloop im Timertakt mit zeitgesteuerten Calls der einzelnen 
Subroutinen und ein bißchen Buffer für die Netzwerkdaten auch machen 
könnte.

> Jaja, als Hobby ganz nett, im produktiven Einsatz aber meist nicht
> sinnvoll.

Dieses Hobby bringt mir in einem aktuellen Projekt mit 15 AVRs für 
verschiedenste Steueraufgaben etwa 20kEur. Ich weiss, Peanuts, aber so 
ein Hobby würde sich mancher wünschen, denke ich.

Eine jitterfreie Software-PWM für 8 Kanäle in C? Bis da die Daten aus 
dem SRAM geladen sind, ist meine PWM-Routine mit direktem 
Registerzugriff schon durch.

von Falk B. (falk)


Lesenswert?

@ Timm Thaler (timm-thaler)

>Also nichts, was man mit einem Timer auf 10ms mit 15 Takten, einer
>Mainloop im Timertakt mit zeitgesteuerten Calls der einzelnen
>Subroutinen und ein bißchen Buffer für die Netzwerkdaten auch machen
>könnte.

Du bist ein Pfennigfuchser, ähhh Taktzähler. ;-)

>> Jaja, als Hobby ganz nett, im produktiven Einsatz aber meist nicht
>> sinnvoll.

>Dieses Hobby bringt mir in einem aktuellen Projekt mit 15 AVRs für
>verschiedenste Steueraufgaben etwa 20kEur.

In C wäre das wahrscheinlich ebenso, ggf. sogar einfacher machbar. Aber 
ich will niemanden bekehren. Die ewige Diskussion hatten wir schon zur 
Genüge.

>Ich weiss, Peanuts, aber so
>ein Hobby würde sich mancher wünschen, denke ich.

20kEur Umsatz oder Gewinn?

>Eine jitterfreie Software-PWM für 8 Kanäle in C? Bis da die Daten aus
>dem SRAM geladen sind, ist meine PWM-Routine mit direktem
>Registerzugriff schon durch.

Jaja, alles ganz nett und ne sportliche Herausforderung, aber Profis 
nehmen einfach einen passenden PWM-IC, von dem es heute mehr als genug 
gibt und fertig. Professionelle Industrielösungen reizen Teilkomponenten 
selten aus, dafür setzen sie auf bestehende, getestete Komponenten. Ist 
In Summe deutlich effektiver. Und wie gesagt, es gibt schon noche in 
paar kleine Nischen für ASM. Und dass man auch in C eine recht gute 
Soft-PWM hinkriegt, ist nichts neues. (Jaja, es gibt geringen Jitter 
und man braucht mehr Takte als in ASM, spielt aber in Summe keine 
Rolle).

von Timm T. (Gast)


Lesenswert?

Falk Brunner schrieb:
> Professionelle Industrielösungen reizen Teilkomponenten
> selten aus, dafür setzen sie auf bestehende, getestete Komponenten.

Ja, diese Industrielösungen kenne ich auch: Schaltkreisgräber mit völlig 
überdimensionierten µC, weil da wahrscheinlich Java programmiert wird. 
Die Peripherie mit irgendwelchen Spezial-IC gemacht, die es in 5 Jahren 
nicht mehr gibt.

Falk Brunner schrieb:
> aber Profis
> nehmen einfach einen passenden PWM-IC

Ein PWM-IC, der 8 PWM jeweils um 1/8 Periode versetzt ausgibt, um nicht 
alle Verbraucher gleichzeitig einzuschalten? Wäre mir neu...

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.