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 | 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.
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.