Ein immer wieder auftretendes Problem bei den ATtinys ist das gleichzeitige Abhandeln mehrerer Aktionen. Ich habe mir die Mühe gemacht ein kleines cooperatives Multitasking Systemchen in ASM zu stricken, weil ich für den beengten Speicher der ATtinys noch nichts derartiges gefunden habe. Die Eckpunkte: Speicherverbrauch: 1 byte für Timer 4 byte für Taskhandling + 4 byte pro reserviertem Task CPU-Belastung ca 70 Taktzyklen für Taskwechsel ca 70 Taktzyklen für TaskTick-handling 70 CPU-cycles klingt auf den ersten Blick viel sind aber in Wirklichkeit grade mal 3% der CPU Last, ergo 97% frei für Userprogramme. Anwendung: Das Hauptprogramm initialisiert alle IO und ruft den MosInit auf. Anschließend werden mit AddTask die einzelnen Tasks eingetragen und das Multitasking mit einem rjmp mosStartScheduler gestartet. Jeder Task erledigt die notwendigen Teile, und gibt anschließend mit rcall MosNextTask die CPU an den nächsten Task ab. Alternativ kann sich ein Task mit rcall MosSleep (Sleep Wert in MosTicks in R26/R27) eine gewisse Zeit lang warten. Ein MosTick beträgt standardmäßig 2048 Taktcyklen, also bei 8MHz sind das 256µS. Ein MosSleep(4) wartet also 1ms. Ein MosSleep(0xfffe) wartet also knapp 17 Sekunden Mit MosSleep(0xffff) kann man den Task anhalten bis er von einem anderen Task mit MosNotify wieder 'aufgeweckt' wird. Die MosTicks werden mit dem Timer0 Overflow int (prescaler=8=>256*8) erzeugt, näheres siehe Beschreibung in den Sourcen. Eine Tastenentprellung würde also zB folgendermaßen aussehen (Pseudocode): lies Taste wenn Taste gedrückt MosSleep(8) Taste noch immer gedrückt? dann kein Tastenprellen etc... rjmp zurück auf lies Taste Und zwischen den beiden Abfragen können alle anderen Tasks machen was sie wollen... Das task-switching funktioniert übrigens indem ich mir die beim Call vom Aufrufer abgelegte Adresse vom Stack hole und in der Taskliste zwischenspeichere. Dann wird zum nächsten Task geschalten und die vormals abgelegte Adresse des neuen Tasks auf den Stack gepusht und ein ret ausgeführt. Da ich den AVR erst seit einigen Wochen verwende, gibt es sicher einige Dinge die man noch verbessern kann. Ich hoffe also auf eure Hilfe und Verbesserungsvorschläge. LieGrü, strub
Der Link ist ein - für mich - unlesbares Format. Geht das auch anders (txt / asm...), dann kann ich vielleicht auch verstehen, worum es geht?
ich war mal so frei. ZIP sollt egehen - hoffe ich. Mein RAR-Packer konnte das tar.gz auspacken
oh sorry, da ich unter Linux und Solaris arbeite habe ich nicht daran gedacht. Geschrieben habe ich das ganze übrigens mit gavrasm http://www.avr-asm-tutorial.net/gavrasm/index_de.html und simuliert mit dem AVRsimu http://www.sourceforge.net/projects/avrsimu
Hallo. Mir ist nicht so ganz klar, wozu Task Scheduler bei AVRs gut sind. (Wozu sie bei riesigen Betriebssystemen gut sind, verstehe ich schon.) Ist doch ein sehr starres Prinzip. Wenn ich meine Software um Interrupts herum aufbaue, kriegt jeder "Task" sofort das Zepter in die Hand, wenn er das braucht und gerade kein anderer Int mit höherer Priorität ansteht. Den Overhead spare ich mir, und nach spätestens 10 us ist der entsprechende Task dran. mfg gerd
na, und wenn du mehr regelmäßige aufgaben als timer hast?
@Gerd "Mir ist nicht so ganz klar, wozu Task Scheduler bei AVRs gut sind." Man kann damit Wartezeiten vermeiden, besonders, wenn viel Sachen gleichzeitig zu machen sind. Der Scheduler ist aber nur eine Task in der Mainloop, d.h. Sachen, die ihn nicht brauchen, laufen direkt in der Mainloop, wie sonst auch. Man könnte ihn auch in einen Timerinterrupt setzen, muß dann aber darauf achten, daß alle ihm übergebenen Funktionen als Interrupt laufen (nichtatomare Parameterzugriffe unter Interruptsperre usw.). Allerdings programmiere ich sowas lieber in C: http://www.mikrocontroller.net/forum/read-4-49709.html#new Peter
P.S.: Zum Tastenentprellen würde ich ihn nicht mißbrauchen, das geht wesentlich effektiver so (gleich 8 Tasten auf einmal): http://www.mikrocontroller.net/forum/read-4-310276.html#new Peter
Hallo Peter! Bin zufällig wieder über meinen eigenen Beitrag gestolpert. Der Vorteil meines kleinen schedulers liegt im minimalen Ressourceverbrauch. Der Code ist grade mal ein paar dutzend Byte groß und sogar mit einem tiny13 mit minimalem SRAM kommt man locker über die Runden. Wenn man das ganze in C sauber lösen wollte, dann würde man alleine für das swappen der registers für jeden task 32 byte brauchen. LieGrü, strub
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.