Forum: Mikrocontroller und Digitale Elektronik Dritte Hierarchiestufe?


von Rumkugel (Gast)


Lesenswert?

Hi,

normalerweise hat man mit Interrupts ja zwei Hierarchiestufen:
1. Interrupts
2. Alles was im Main-Loop steht

Ich habe nun ein Programm, das genau so bereits funktioniert (Interrupts 
setzen Flags, diese werden dann in ziemlich langen Funktionen innerhalb 
des Main-Loops ausgewertet).

Jetzt möchte ich die verbliebene Kapazität aber noch für ein paar 
zusätzliche Dinge gebrauchen, die die bisherige Funktion aber nicht 
beeinflussen sollen, also praktisch eine dritte Stufe unter den 
bisherigen Funktionen aus der Main-Loop einrichten.

Hab ich mich klar genug ausgedrückt?
Gibts dazu irgendwelche Ideen?

Grüße!

von MaWin (Gast)


Lesenswert?

UNTER der Main-Loop kannst du vergessen (das wäre dann deine Main-Loop) 
aber oberhalb kannst du natürlich noch eine Ebene einziehen.

main-loop: Wenn sonst nichts zu tun ist
1. Interrupt-Hierarchie: Unwichtigeres
2. Interrupt-hierarchie: Schnell zu bearbeitende Ereignisse

Deine bisherige Main-Loop läuft einfach rum, nehmm ich an,
du musst also entscheiden, WANN sie rumlaufen soll,
und sie vermutlich auf einen Timer setzen.

Eventuell synchronisuert sie sich schon aktiv an eine Zeit
oder ein sonstiges Ereignis. Dann musst du dieses Ereignis
eben zu einem Interrupt machen (oder einen schneleren
Interrupt nachgucken lassen, ob das Ereignis eingetreten ist,
und dann zur Ausführung flaggen).

von Karl H. (kbuchegg)


Lesenswert?

> Hab ich mich klar genug ausgedrückt?

Ich vermute mal, du meinst so etwas wie 'Idle-Processing'.
Also Dinge, die ablaufen, wenn es sonst nichts zu tun gibt.

erster Ansatz:
1
int main()
2
{
3
  ...
4
5
  while( 1 ) {
6
7
    isIdle = true;   // Annahme: es gibt nichts wichtiges zu tun
8
9
    if (Jobflag)
10
    {
11
       mach irgendetwas ganz wichtiges
12
13
       isIdle = false;   // die Annahme war falsch
14
    }
15
16
    if (UpdateLCD)   // noch ein Jobflag
17
    {
18
       update das LCD
19
20
       isIdle = false;   // auch hier: die Annahme war falsch
21
    }
22
23
    ....
24
25
26
    if (isIdle)         // wenn es in diesem Durchgang nichts wichtiges
27
                        // zu tun gab, dann mach jetzt die unwichtigen
28
                        // Sachen unter der Annahme, dass ein wenig
29
                        // Zeit bleibt
30
    {
31
                        // Allerdings wichtig: Immer nur kurze Dinge
32
                        // erledigen, damit die Abfrage der Jobflags
33
                        // möglichst schnell wieder startet
34
       ....
35
     }
36
  }

Ganz auf 0 bringst du die Beeinflussung nicht. Aber das hast du ja auch 
so, dass die Abarbeitung eines Jobflags die Abarbeitung eines anderen 
Jobflags ein wenig verzögert.

von Falk B. (falk)


Lesenswert?

Siehe Multitasking

von Rumkugel (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Ich vermute mal, du meinst so etwas wie 'Idle-Processing'.
> Also Dinge, die ablaufen, wenn es sonst nichts zu tun gibt.

Eigentlich meine ich genau das. Bei dem angegebenen Code würde ich aber 
Probleme bekommen, wenn die Aufgaben niedriger Prioriät sehr viel Zeit 
in Anspruch nehmen. Dann kann meine Hauptaufgabe im nächsten Durchlauf 
nicht rechtzeitig ausgeführt werden.

Eine Lösung könnte es sein, die bisherigen Aufgaben aus dem Main-Loop in 
einen Interrupt zu verschieben. Hier bekomme ich dann aber Probleme, 
weil diese Aufgaben ziemlich lang sind (ca 0.5ms) und die übrigen 
Interrupts nicht ausgelöst werden können.

von MaWin (Gast)


Lesenswert?

> und die übrigen Interrupts nicht ausgelöst werden können.

Natürlich können andere Interrupts ausgelöst werden, selbst beim uralten 
PIC geht das in 2 Stufen, in dem du sie eben zu Beginn deiner 
Interrupt-Funktion wieder freigibst.

von Peter D. (peda)


Lesenswert?

Ich vermute mal, Du meinst standard AVRs ohne Prioritäten.

Die Main ist immer das langsamste.

Mittelschnelle Tasks kannst Du aber in nem Timerinterrupt aufrufen.
Der muß dann erst sich selbst disablen, Interrupts global enablen und 
nach den Tasks dann wieder umgekehrt.
Damit können ihn andere Interrupts unterbrechen, er sich selber aber 
nicht.


Peter

von Karl H. (kbuchegg)


Lesenswert?

Rumkugel schrieb:
> Karl heinz Buchegger schrieb:
>> Ich vermute mal, du meinst so etwas wie 'Idle-Processing'.
>> Also Dinge, die ablaufen, wenn es sonst nichts zu tun gibt.
>
> Eigentlich meine ich genau das. Bei dem angegebenen Code würde ich aber
> Probleme bekommen, wenn die Aufgaben niedriger Prioriät sehr viel Zeit
> in Anspruch nehmen.

Genau deshalb habe ich auch geschrieben: Die dürfen nur sehr kurz sein
Eventuell könnte man sich auch dadurch retten, dass die Nebenaufgabe an 
strategischen Stellen abgebrochen wird, wenn eines der Jobflags auf true 
geht. Die Nebenaufgabe überprüft quasi laufend, ob es nicht etwas 
wichtigeres zu tun gibt und bricht ab, wenn dem so ist. Vielleicht kann 
man auch die Nebenaufgabe in eine Art Statemachine verpacken, die ihre 
Aufgabe in mehreren States abarbeitet und so automatisch immer wieder 
zur Hauptschleife zurückkommt.

von Rumkugel (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Ich vermute mal, Du meinst standard AVRs ohne Prioritäten.

Ich habe die Frage mal ganz bewusst allgemein gestellt, in der vagen 
Hoffnung für mein Problem auf eine ganz neue Idee zu kommen.

Konkret läuft das auf einem ARM9 (STR91) und ich habe bereits versucht 
die mittlere Stufe als unterbrechbaren Interrupt zu schreiben, 
allerdings steige ich bei der Implementierung nicht ganz durch und es 
funktioniert natürlich nicht vernünftig.

Es ist natürlich auch kein absolut triviales Ziel mehr, aber es wäre 
halt gut wenn ich es trotzdem hinbekommen würde.

von Peter D. (peda)


Lesenswert?

Rumkugel schrieb:
> Konkret läuft das auf einem ARM9 (STR91) und ich habe bereits versucht
> die mittlere Stufe als unterbrechbaren Interrupt zu schreiben,
> allerdings steige ich bei der Implementierung nicht ganz durch und es
> funktioniert natürlich nicht vernünftig.


Wenn Du eine CPU mit Prioritäten hast, ist das ganz einfach. Du hast 
soviel Stufen, wie Du Prioritäten hast.

Du nimmst also nen Timerinterrupt und weist ihm die niedrigste Priorität 
zu, dann können ihn alle anderen Interrupts unterbrechen. Er selber kann 
aber nur das Main unterbrechen.
Und in diesem Interrupt machst Du alle Tasks der mittleren 
Hirarchiestufe.

Wie man beim ARM Prioritäten festlegt, weiß ich nicht. Beim 8051 setzt 
man einfach nur 1 oder 2 Bits in den Prioritätenregistern, fertig ist 
die Laube. Die Interrupthardware kümmert sich dann um alles andere.


Peter

von Rumkugel (Gast)


Lesenswert?

Peter Dannegger schrieb:
> Wenn Du eine CPU mit Prioritäten hast, ist das ganz einfach. Du hast
> soviel Stufen, wie Du Prioritäten hast.

Prioriäten habe ich zugewiesen. Das Problem ist nur, dass diese 
Prioritäten nur gebraucht werden, wenn mehrere Interrupts anstehen. Die 
Interrupts unterbrechen sich standardmäßig nicht gegenseitig. Damit sie 
das tun muss man offenbar etwas tricksen und das bekomme ich nicht ganz 
hin.

Peter Dannegger schrieb:
> Du nimmst also nen Timerinterrupt und weist ihm die niedrigste Priorität
> zu, dann können ihn alle anderen Interrupts unterbrechen. Er selber kann
> aber nur das Main unterbrechen.
> Und in diesem Interrupt machst Du alle Tasks der mittleren
> Hirarchiestufe.

So ähnlich hatte ich es eigentlich geplant. Doch leider funktioniert das 
nicht ganz so einfach, soweit ich das verstanden habe

Gruß

von MaWin (Gast)


Lesenswert?

>  ch habe bereits versucht die mittlere
> Stufe als unterbrechbaren Interrupt zu schreiben

1 3 2 ?

> Es ist natürlich auch kein absolut triviales Ziel mehr

Stimmt schon, richtiges Anordnen von Zahlen macht man erst nach dem 
Kindergarten.

von Falk B. (falk)


Lesenswert?

@  Rumkugel (Gast)

>So ähnlich hatte ich es eigentlich geplant. Doch leider funktioniert das
>nicht ganz so einfach, soweit ich das verstanden habe

Warum liest du nicht den Artikel Multitasking ?

MfG
Falk

von Peter D. (peda)


Lesenswert?

Rumkugel schrieb:
> Doch leider funktioniert das
> nicht ganz so einfach, soweit ich das verstanden habe

Das ist auch ein Hinderungsgrund, warum ich keine große Lust habe, auf 
ARMse umzusteigen.
Sie mögen zwar irgendwelche dirty Tricks erlauben, aber für 99,9% der 
Anwendungsfälle ist das ganze monstermäßige Interruptgedöns viel zu 
kompliziert.

Interrupthandler müssen wohl auch selber immer bestimmte Bits in einer 
ganz bestimmten Reihenfolge anfassen, damits nicht kracht.

8-Bitter löschen dagegen Interruptflags automatisch beim Einsprung und 
höher priorisierte Interrupts bleiben automatisch enabled.
Der Interrupthandler muß rein garnichts mit den Interrupt-Registern 
rummachen, alles läuft ganz von alleine rund.


Peter

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.