Interrupts und blockierende Prozesse

Gast #4131141
Lesenswert?
• ▲
▼
Hey,

ich bin ein relativer Neuanfänger, und habe ein Problem mit einer 
Spezifikation. Der Grundaufbau ist folgendermaßen:

Ein Mikrocontroller und ein Sensor: Der Sensor sendet mit 10 kHz ein 
signed 32 bit Signal, und diese Signale sollen über einen blockierten 
Interrupt interpretiert werden. So weit so gut.

Jedoch steht ein zweiter blockierender Prozess im Hintergrund (z.B. 
print() serielle Ausgabe über UART - bedeutet keine Eintrittsinvarianz), 
dieser Prozess ist wesentlich langsamer als der Interrupt des Signales.

Wie kann ich die Signale des Sensors verarbeiten ohne sie während der 
Zeit des blockierenden Prozesses zu verlieren?

Technische Daten:
Sensor: Alle 100µs
Blockierender Prozess: Jede Sekunde

Momentane Idee ist: Ein Timer und Interrupt für den Sensor, und die 
Daten verarbeiten, allerdings denke ich mir dass die (blockierende) 
Ausgabe über die UART-Schnittstelle die Interrupts des Sensors 
blockierend wird, wodurch ich Daten verlieren würde.

Um jegliche Hilfe wäre ich äußerst dankbar.
Persönliche Seite #4131142
Lesenswert?
• ▲
▼
Chris Schäufer schrieb:
> diese Signale sollen über einen blockierten
> Interrupt interpretiert werden. So weit so gut.

Warum? Wer sagt das? Das macht doch keinen Sinn!

Chris Schäufer schrieb:
> Jedoch steht ein zweiter blockierender Prozess im Hintergrund …

Warum? Das macht doch auch keinen Sinn!

Setze Flags in den ISRs und mache alles in der Main-Loop.
Gast #4131154
Lesenswert?
• ▲
▼
Danke für deine Antwort Torsten C.,

das ist nunmal die Spezifikation an der ich nichts ändern kann, und wie 
gesagt bin ich ein Anfänger welcher sich versucht darin einzuarbeiten.

Wenn ich den blockierenden Prozess in die "Main-Loop" einsetze wird das 
Programm dann trotzdem in der Lage sein die Daten des Sensors zu 
verarbeiten? Obwohl der blockierenden Prozess wesentlich länger braucht 
als der Interrupt des Sensors?

Entschuldige es mir falls ich nicht deiner Terminologie entsprechend 
geantwortet habe
#4131163
Lesenswert?
• ▲
▼
Chris Schäufer schrieb:

>
> Wenn ich den blockierenden Prozess in die "Main-Loop" einsetze wird das
> Programm dann trotzdem in der Lage sein die Daten des Sensors zu
> verarbeiten? Obwohl der blockierenden Prozess wesentlich länger braucht
> als der Interrupt des Sensors?
>
Definiere mal "blockierender Prozess" und beantworte Dir selbst folgende 
Frage:
Wie kann der MC irgendetwas anderes machen wenn er von einem Prozess im 
IRQ blockiert wird?
Anders sieht es aus, wenn der blockierende Prozess die Mainloop aus (da 
unterscheidet sich Dein erster von Deinem 2.Beitrag). Dort kann ein IRQ 
natürlich den Prozess unterbrechen.
Man kan auch einen IRQ durch eine anderen unterbrechen. Dann wird es 
aber komplizierter und ich würde diese Vorgehensweise bei Deinem 
Kenntnisstand nicht empfehlen.
Grunsätzlich schreibt man Programme (insbesondere IRQ) bei einem 
Mikroprozessor so, daß sie eben nicht blockieren. (Stichwort: State 
machine)
Wenn also bei Deinem Programm irgendwelche Delays vorkommen, hast Du 
grundsätzlich schon etwas falsch gemacht.

Gruß
Andreas
Gast #4131191
Lesenswert?
• ▲
▼
Also erst mal eine Klarstellung: Dein "blockierender Prozess"
bedeutet wohl, dass der Prozessor/µC während der Erfassungs-
Routine (Sensor), oder der Ausgabe-Routine nicht unterbrochen
werden darf. Die "Eintrittsinvarianz" klingt schön gebildet,
erläutert dein Problem aber auch nicht so richtig:

Die print()-Ausgabe über UART kann jedenfalls ohne weiteres
unterbrochen werden, wenn man eine Hardware-UART zur Vefügung
hat (z.B. AT-Mega). Dabei schaut der µC, wenn er gerade mal
Zeit hat nach, ob der Sendepuffer frei ist und setzt ggfs. das
nächste Byte ab - um den Rest kümmert sich die µC-Hardware.

Ohne Hardware-UART hast du wohl den falschen µC gewählt,
wenn du nicht auf einige Sensorwerte verzichten willst,
darfst, oder kannst.

In vielen Fällen reichen aber auch ein bis 10 Sensorwerte pro
Sekunde - die mit ihrem 100 µs Takt auch schnell genug
übermittelt sind, um in der restlichen Zeit noch VIELE
Sachen zu erledigen.

Mach dir doch erst mal ein paar konzeptionelle Gedanken!
#4131568
Lesenswert?
• ▲
▼
Kurt schrieb:
> Also erst mal eine Klarstellung: Dein "blockierender Prozess"
> bedeutet wohl, dass der Prozessor/µC während der Erfassungs-
> Routine (Sensor), oder der Ausgabe-Routine nicht unterbrochen
> werden darf.

Wobei ich selbst das in Frage stellen würde. Wenn da alle 100 µs ein Bit 
abgefragt werden muss, kann man auch einen Timer stellen, dessen 
Interrupt das tut. Damit wäre der Prozessor nicht 3,2 ms lang zu 100%, 
sondern nur zu vielleicht 5% ausgelastet. 100 µs entsprechen 
schliesslich selbst bei gemütlichen 10 MHz CPU-Takt immer noch 1000 
Instruktionen.

Und dann sind da u.U. noch Chancen, den Hardware-SPI das Signal lesen zu 
lassen. Dann hat die CPU fast gar nichts mehr zu tun.
Gast #4131578
Lesenswert?
• ▲
▼
Bastler schrieb:
> Das würde man dann aber als "kreativ" bezeichnen, oder ;-)

Für nicht genutzt Hardware gibt es beim µC kein Geld zurück. Dann kann 
sie auch etwas sinnvolles tun und dem Prozessor für kreativere Dinge als 
regelmäßiges Abtasten den Rücken frei halten.
#4131645
Lesenswert?
• ▲
▼
Chris Schäufer schrieb:
> und diese Signale sollen über einen blockierten
> Interrupt interpretiert werden.

Warum soll ein Interrupt etwas blockieren?
Er macht sein Ding und kehrt sofort wieder zum Main zurück.
Müssen darin zeitverzögerte Sachen gemacht werden, startet er dazu einen 
Timerinterrupt und der macht dann den Rest.

Chris Schäufer schrieb:
> (blockierende)
> Ausgabe über die UART-Schnittstelle

UART im Pollingmode blockiert keine Interrupts, der Interrupt merkt die 
UART garnicht.
UART im Interruptmode blockiert auch nichts. Der schreibt nur das 
nächste Byte in das Datenregister und das braucht nur wenige CPU-Takte.
Gast #4131696
Lesenswert?
• ▲
▼
@Praktiker: offenbar war meine Ironie mißverständlich. Ich bin sehr 
dafür Probleme mit den Mittel zu lösen, die die Hardware bietet. 
Interrupts sind da mit das Wichtigste. Wie heute schonmal in anderem 
Thread geschrieben: PeDa-Entprellung auf Tiny24 in C++ formuliert, 
braucht Rechenzeit im Promillebereich. Der Rest ist Schlafen und warten 
auf Timer0. "kreativ" bezog sich mehr darauf, daß dies eigentlich nichts 
Neues sein sollte. Dinge, die für Ältere wie mich normal sind und 
Greenhorns "exciten". Und deren Aufregung ob dem vermeintlich Neuem wird 
dann als Kreativität mißverstanden ;-)
Gast #4131728
Lesenswert?
• ▲
▼
Bastler schrieb:
> dafür Probleme mit den Mittel zu lösen, die die Hardware bietet.
> Interrupts sind da mit das Wichtigste. Wie heute schonmal in anderem

Ich würde die Timer an erster Stelle nennen.

> Thread geschrieben: PeDa-Entprellung auf Tiny24 in C++ formuliert,
> braucht Rechenzeit im Promillebereich. Der Rest ist Schlafen und warten
> auf Timer0. ...

Warten auf Timer0? Den Text solltest du auch nochmal überarbeiten, wenn 
du das nicht so meinst, wie es rüberkommt.

> Dinge, die für Ältere wie mich normal sind und
> Greenhorns "exciten". Und deren Aufregung ob dem vermeintlich Neuem wird
> dann als Kreativität mißverstanden ;-)

Kann dich denn noch was "exciten"?
Gast #4131893
Lesenswert?
• ▲
▼
Chris Schäufer schrieb:
> ich bin ein relativer Neuanfänger, und habe ein Problem mit einer
> Spezifikation. Der Grundaufbau ist folgendermaßen:
>
> Ein Mikrocontroller und ein Sensor: Der Sensor sendet mit 10 kHz ein
> signed 32 bit Signal, und diese Signale sollen über einen blockierten
> Interrupt interpretiert werden. So weit so gut.

Erstmal eines: Was ist "einen blockierten Interrupt" ?

Ist der Intettupt nun blockiert oder nicht?

Dann zu einem sinnvollen Verfahren:
1. Regel: Du kannst nicht mehr Traffic hereinholen, als du an von diesem 
Traffic verursachtem Output herausbringen kannst. Mißachtest du das, 
kommt es grundsätzlich zum Überlauf.

2. Arbeite mit Puffern. Also hole deine Input-Werte in einer ISR herein 
und stopfe sie in einen Input-Ringpuffer. Verarbeite die Werte aus dem 
Ringpuffer in der Grundschleife oder einer Funktion, die du aus der 
Grundschleife heraus aufrufst. Stopfe die dort anfallenden Erebnisse in 
einen zweiten Ringpuffer. Gib die in dem zweiten Ringpuffer anstehenden 
Ergebnisse per Interrupt an den Ausgabe-Kanal aus.

3. Benutze zu solchen Zwecken NIE NIE NIEMALS sowas wie printf und 
Konsorten, sofern du den dadurch entstehenden Datenstrom nicht selbst in 
den genannten zweiten Ringpuffer leiten und per Interrupt ausgeben 
kannst.

W.S.
#4131981
Lesenswert?
• ▲
▼
> 3. Benutze zu solchen Zwecken NIE NIE NIEMALS sowas wie printf und
> Konsorten, sofern du den dadurch entstehenden Datenstrom nicht selbst in
> den genannten zweiten Ringpuffer leiten und per Interrupt ausgeben
> kannst.

Blöde Frage: Warum nicht? Sind die vom Timing so unvorhersehbar?
#4132029
Lesenswert?
• ▲
▼
@ S. R. (svenska)

>> 3. Benutze zu solchen Zwecken NIE NIE NIEMALS sowas wie printf und
>> Konsorten,

Unsinnige Verallgemeinerung. Man kann das durchaus verwenden, wenn der 
Interrupt sich nicht zu schnell wiederholt.

> sofern du den dadurch entstehenden Datenstrom nicht selbst in
> den genannten zweiten Ringpuffer leiten und per Interrupt ausgeben
> kannst.

>Blöde Frage: Warum nicht?

Man kann.

> Sind die vom Timing so unvorhersehbar?

Nein, das ist eher revht gut vorheragbar, kann aber bisweilen lang sein. 
Ein printf() in einem 10kHz Timer-Interrupt ist eher deplatziert, in 
einem 5 Hz Interrupt kein Problem.
Gast #4132048
Lesenswert?
• ▲
▼
Falk Brunner schrieb:
> Ein printf() in einem 10kHz Timer-Interrupt ist eher deplatziert, in
> einem 5 Hz Interrupt kein Problem.

Das ist haarsträubender Unsinn, es geht darum wie LANGE eine ISR 
blockiert und nicht wie OFT. So etwas Irreführendes dürfte hier niemals 
veröffentlicht werden, das ist unverantwortlich!

In ISRs darf es keine Warteschleifen geben, die mehr als vorhersehbar 
wenige µs brauchen. Z.B. serielles Senden: die ISR sendet ein Byte, wenn 
das UART frei ist, und wenn nicht kehrt sie sofort zurück - warten in 
der ISR darauf, dass eine Peripherie frei wird, ist ein unentschuldbarer 
Kunstfehler.

Man kann daher so etwas wie printf in einer ISR nur verwenden, wenn man 
das Timing in der Hand hat, weil man die zeichenweise Ausgabe selbst 
durch ISRs ersetzt hat (und das Zeitverhalten überblickt!), oder wenn es 
mit absoluter Garantie keine Verzögerungen gibt, z.B. wenn man ins 
Memory schreibt statt auf einen Drucker o.ä.

Georg
Gast #4132126
Lesenswert?
• ▲
▼
S. R. schrieb:

> ...oder wenn es in der Anwendung keine Bedeutung hat.
>
> Und das ist in erstaunlich vielen Fällen der Fall.

Nur dann, wenn der µC für die zu erfüllende Aufgabe massiv 
überdimensioniert ist und damit unnötig viel Strom verbraucht und 
unnötig viel Abwärme produziert.

Das ist, als wenn man jeden Tag mit einem 40Tonnen-Truck zur Arbeit 
fährt. Klar, dann braucht man sich auch niemals Sorgen darum zu machen, 
ob man die Lunchbox und die Einkäufe auf der Heimfahrt im Fahrzeug 
unterkriegt...

Aber trotzdem machen das erstaunlich wenige Leute. Die können vermutlich 
alle rechnen...
#4132244
Lesenswert?
• ▲
▼
@ Georg (Gast)

>Das ist haarsträubender Unsinn, es geht darum wie LANGE eine ISR
>blockiert und nicht wie OFT. So etwas Irreführendes dürfte hier niemals
>veröffentlicht werden, das ist unverantwortlich!

Ohje. Beschwerd dich doch beim internationalen Gerichtshof in Den Haag.
Natülich darf die langsame 5 Hz Timer ISR mit riesigen print(f) Ausgaben 
nicht ANDERE ISR, welche deutlich öfter aktiv werden, nicht soweit 
ausbremsen, dass dort ISRs verschluckt werden. OK, mein Fehler dass ich 
das nicht so explizit geschrieben habe.

Dass man zwar meistens gut damit fährt, printf(9 & Co in ISRs eher nicht 
zu vermeiden heißt eben nicht, dass es absolut unmöglich bzw. verboten 
ist.
Man muss wie immer wissen was man tut.

>In ISRs darf es keine Warteschleifen geben, die mehr als vorhersehbar
>wenige µs brauchen.

Blödsinn! Das ist ein SONDERFALL! Allgemein gilt das überhaupt nicht.
Eine ISR darf sich im Einzelfall auch mal 100ms Zeit gönnnen.

> Z.B. serielles Senden: die ISR sendet ein Byte, wenn
>das UART frei ist, und wenn nicht kehrt sie sofort zurück - warten in
>der ISR darauf, dass eine Peripherie frei wird, ist ein unentschuldbarer
>Kunstfehler.

Davon redet gar keiner.

>Man kann daher so etwas wie printf in einer ISR nur verwenden, wenn man
>das Timing in der Hand hat, weil man die zeichenweise Ausgabe selbst
>durch ISRs ersetzt hat (und das Zeitverhalten überblickt!),

Das muss man bei ISRs immer.
Gast #4132533
Lesenswert?
• ▲
▼
Also die Aufgabenstellung tönt sehr abenteuerlich. Vielleicht solltest 
du zuerst ein paar Tutorials zum Thema Mikrokontroller durcharbeiten.

So wie ich das verstanden erhältst du 32Bit Daten, alle 100us soll ein 
neues Bit eingelesen werden. Dafür brauchst du eigentlich nur ein Timer 
Interrupt, im Interrupt selbst wird nur der Status des Sensors gelesen 
und danach in einem Zwischenspeicher abgelegt. Die Daten kannst du dann 
in der main() Routine verarbeiten. Der Timer Interrupt wird deine 
restliche Software nicht tangieren.
Im Interrupt sollte keine grosse Datenverarbeitung statt finden, 
irgendwelche delays haben dort ebenfalls nichts zu suchen.

Gruss
#4133210
Lesenswert?
• ▲
▼
Falk Brunner schrieb:
>>In ISRs darf es keine Warteschleifen geben, die mehr als vorhersehbar
>>wenige µs brauchen.
>
> Blödsinn! Das ist ein SONDERFALL! Allgemein gilt das überhaupt nicht.
> Eine ISR darf sich im Einzelfall auch mal 100ms Zeit gönnnen.

Es gibt natürlich Fälle, in denen auch Murks funktioniert. Ändert aber 
nichts daran, daß es Murks ist. Wäre es vernünftig implementiert, würde 
sich die Fragestellung des TE gar nicht erst ergeben. Ihm kann man das 
nicht vorwerfen, da er nach eigenem Bekunden Anfänger ist.
Nun kann man das irgendwie so zurechtfrickeln, daß es trotzdem 
funktioniert, oder man kann es gleich richtig machen, also die ISRs so 
gestalten, daß sie (laufzeitmäßig) möglichst kurz sind und nur das 
selbst machen, was absolut nötig ist.
Jedesmal, wenn jemand eine Warteschleife in eine ISR einbaut, stirbt 
irgendwo ein kleines Hasenbaby.
Gast #4133239
Lesenswert?
• ▲
▼
Oh, da hab ich bisher wohl etwas falsch gemacht:
Ich habe mir ehrlich gesagt überhaupt nichts dabei gedacht, als ich 
printf() so implementiert hat, dass es in einen Ringpuffer schreibt, 
welcher dann per UART-Interrupt ausgegeben wird.

Mist, jetzt muss ich das alles wieder rausmachen und es per Polling und 
Warteschleifen machen :-(
#4133283
Lesenswert?
• ▲
▼
Rolf Magnus schrieb:
> Was soll daran falsch sein?

Das Main schreibt gerade was in den Puffer, zufällig will der Interrupt 
auch was schreiben und es entsteht ein Mischtext:
"MMMMMMIIIIIIIII\nMMMMMM\n".

Generelle Interruptsperre ist keine gute Idee, wenn der Puffer zu voll 
ist und der UART-Interrupt ihn nicht leeren kann.

Man müßte für den Interrupt einen extra Puffer anlegen, der dann vom 
Main mit eingereiht wird.
#4133295
Lesenswert?
• ▲
▼
Peter Dannegger schrieb:
> Rolf Magnus schrieb:
>> Was soll daran falsch sein?
>
> Das Main schreibt gerade was in den Puffer, zufällig will der Interrupt
> auch was schreiben und es entsteht ein Mischtext:
> "MMMMMMIIIIIIIII\nMMMMMM\n".

Davon stand in Broncos Posting aber nichts. Das was er beschrieben hat, 
nämlich für die Ausgabe von printf() einen Rinpuffer und den 
TX-Interrupt zu benutzen, ist erstmal völlig in Ordnung. Ich sehe auch 
nicht, warum sich das in irgendeiner Form mit dem von mir geschriebenen 
beißen sollte.
Das was du beschreibst, also printf() selbst wiederum aus einer ISR 
heraus aufzurufen, ist aber nochmal was anderes. Das ist dann eben der 
Murks, von dem ich geschrieben hab. Da spielt es aber auch keine große 
Rolle, ob das Backend nun Polling oder Interrupts für die Ausgabe nutzt.

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.