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!
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).
> 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
intmain()
2
{
3
...
4
5
while(1){
6
7
isIdle=true;// Annahme: es gibt nichts wichtiges zu tun
8
9
if(Jobflag)
10
{
11
machirgendetwasganzwichtiges
12
13
isIdle=false;// die Annahme war falsch
14
}
15
16
if(UpdateLCD)// noch ein Jobflag
17
{
18
updatedasLCD
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.
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.
> 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.
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
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.
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.
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
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ß
> 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.
@ 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
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