Ich beschäftige mich gerade mit Betriebssystemen in Mikrocontrollern. Das wichtigste Merkmal vom OS scheint wohl das Multitasking bzw. die Prozessverwaltung zu sein. So wie ich es verstehe, werden dabei mehrere Prozesse (Programme) "gleichzeitig" abgearbeitet. Es wird z.B. ein Timer gesetzt über dem jede Millisekunde zum nächsten Prozess geschaltet werden kann. Davor werden aber alle Variablen im Stack zwischengespeichert und der Prozessverwaltung mitgeteilt, wie mit den Daten umgegangen werden soll, sobald wider in dieses Prozess gesprungen wird. Ich denke mal, dass es bei den meisten "kleineren" Anwendungen, die z.B. mit einem Atmega realisiert werden, keinen Sinn machen würde, so einen Aufwand zu betreiben, da es nur unnötig mehr Arbeitszeit und Speicher kosten würde. Ich frage mich aber, ab wann so etwas Sinn machen würde. Vielleicht kann mir jemand dazu ein gutes Beispiel geben! Der Grund ist einfach, dass ich so ein Multitasking System gerne auf einem Atmega328p nachbilden würde, aber ich sehe hier keinen Grund dazu Multitasking zu betreiben. Einfach nachbilden und dabei unnötig mehr Rechenzeit und Speicher zu verbrauchen macht mir auch keine Freude, weil da der Sinn fehlt(z.B. I/O Eingänge prüfen und gleichzeitig etwas berechnen). Wahrscheinlich liegt das aber eher daran, dass ich noch nicht so viele Projekte mit einem uC realisiert habe. Und die 2. Frage die ich mir stelle ist folgende: Bei zeitkritischen Prozessen, wo z.B. innerhalb von 10 Taktzyklen ein Byte über die Serielle Schnittstelle übertragen werden soll, weil es sonst zu Komplikationen führen würde, da wäre es doch verheerend mitten im Prozess rauszuspringen. Wie löst man das in diesem Fall? Kann man da einfach für die 10 Taktzyklen die Interrupts kurz ausschalten? Was wäre aber, wenn genau in diesem Moment ein wichtiges Interrupt stattfinden sollte, wie z.B. beim Timer. Wie ließe sich das Problem lösen? (Bei evtl. Codebeispielen bitte möglicht in Assembler, da nur geringe C Kenntnisse vorhanden sind)
>So wie ich es verstehe, werden dabei mehrere Prozesse (Programme) >"gleichzeitig" abgearbeitet. "Gleichzeitig" geht auf einem Atmega nicht. Da liegst du schon mal voll daneben. Das ist kein Multicore. >Es wird z.B. ein Timer gesetzt über dem jede Millisekunde zum nächsten >Prozess geschaltet werden kann. Auf einem Atmega? Völliger Quatsch. >Bei evtl. Codebeispielen bitte möglicht in Assembler Sonst hast du keine Wünsche zu Weihnachten? Schau dir ein RTOS an, z.B. FreeRtos und nimm dazu einen schnellen ARM Controller mit >50MHz. So macht das Sinn.
holger schrieb: >>So wie ich es verstehe, werden dabei mehrere Prozesse (Programme) >>"gleichzeitig" abgearbeitet. > > "Gleichzeitig" geht auf einem Atmega nicht. Da liegst du schon mal voll > daneben. Das ist kein Multicore. Das weiß er doch selbst. Deswegen die Anführungszeichen. >>Es wird z.B. ein Timer gesetzt über dem jede Millisekunde zum nächsten >>Prozess geschaltet werden kann. > > Auf einem Atmega? Völliger Quatsch. Warum Quatsch? Genau so könnte man es in der Theorie bewerkstelligen. Ob es Sinn ergibt so etwas zu auf einem ATmega zu realisieren ist eine andere Frage. >>Bei evtl. Codebeispielen bitte möglicht in Assembler > > Sonst hast du keine Wünsche zu Weihnachten? Er hat darum gebeten. Wenn du nichts beizutragen hast, dann schreib nicht. Warum immer diese unfreundlichen Antworten? > Schau dir ein RTOS an, z.B. FreeRtos und nimm dazu einen > schnellen ARM Controller mit >50MHz. So macht das Sinn. RTOS ist ein Realtime OS. Das hat nur bedingt etwas mit Multitasking zu tun. RTOS wird da verwendet, wo Determinismus gefragt ist. Multitasking erfordert keine Echtzeit.
Ich fange mal mit der Antwort bei meiner Applikation und ein wenig Theorie an: Ich steuere eine Kaffeemaschine, ob eine SAECO oder wie bei mir einen 2-kreiser (www.kaffeewiki.de) ist egal. Im Kern ist das eher eine langsame, gemütliche Sache,aber die Menge an Aufgaben macht den Einsatz eines Mutitasking sinnvoll, da man einfach "überblickbarer" und "modular" programmieren kann. Ein Auszug, aus den Modulen: Messung der Temperatur an 3 Stellen auf ca 0.3 Grad genau, Regelung der Temperatur, Steuerung des Bezuges, Tests beim Einschalten (Leitungsdruck da, funktioniert die Kesselsonde), evtl Timer für eine eine Mühle steuern. Ein "preemptives Multitasking" scheidet bei einem AtMega für mich hier aus, da zu aufwendig, weil: um bei einem IRQ alle Zustände zu sichern und wieder herzustellen, mußt du du grob gerechnet 40 register / Bytes sichern und wieder herstellen, bis du dann bei deinem eigentlich Code bist, der dann den eigentlichen Job tut, vergeht noch ein wenig Zeit. 40 Byte ins RAM schreiben sind 80 Taktzyklen, plus "Kleinkram" sind 100 Taktzyklen. Bei 16 MHz sind das etwa knapp 7ys. Das ganze am Ende in umgekehrter Reihenfolge nochmal sind 15ys bei jedem IRQ, unabhängig davon ob das eine Serielle oder ein Timer oder sonst was ist. Jetzt muß du zusammenzählen, wer aller in deiner Aufgabenstellung einen IRQ auslöst. Also z.b. I2C, UART, Timer, ... und die Last dadurch abschätzen. Dann weißt du, was dir für die eigentliche Bearbeitung dessen, was hier über IRQs an Daten gekommen ist, übrig bleibt. Mit einer groben Abschätzung geht es weiter: Wenn du alle 100ys einen IRQ hast (z.B. I2C mit 100KHz sind 10Kbyte/sec) geht rund ein sechstel der Zeit nur dafür verloren, daß du darauf überhaupt reagieren kannst. Dann kommt noch der eigentliche Code für den Auslöser des IRQ dazu. Ich hab selbst kein preemptives Multitasking imlementiert, aber um eine Zeitscheibe von mind 5 - 10 ms wirst du nicht herumkommen. Zu beachten ist ferner, daß C bei komplexen Strukturzugriffen einiges an Code erzeugt. Wenn du sagst, daß du in einigen Taktzyklen ragieren mußt, so geht das - wenn du das wirklich so wörtlich meinst - über FPGA o.ä. Bei einem yP in wenigen 50ns reagieren, ist schon heftigst. Zur Theorie der Betriebssysteme gibt es grob (wir lassen mal MultiCore aus) preemptives Multitasking (mit den Unterarten "Echtzeit" und "nicht Echtzeit" wie Windows und LINUX. Und dann wie das "gute alte Windows 3.1", ein "kooperatives Multitasking". Das beruht darauf, daß ein Prozess freiwillig (mittels Return from Subroutine) die Kontrolle an das OS zurückgibt, und seinerseits dann in einer riesigen Schleife auf Ereignisse (Informationen das Betriebssystems) wartet. Ich habe diese Überlegung so weitergesponnen, daß ich eine Aufgabe in ihre einzelnen Abschnitte, Verarbeitungsschritte zerlegt habe. Das ist dann eine Sammlung von einigen Unterprogrammen, die in der passenden Reihenfolge den gewünschten Job tun. Jetzt habe ich das Ganze um die Überlegung erweitert, daß ich in sehr vielen Fällen "irgendwann" "irgendwas" mache. Das führt zur Basisstruktur Zeitverzögerung und Pointer auf eine Funktion, die nach Ablauf der Zeitverzögerung durchzuführen ist. Falls jetzt ein obiger Verarbeitungsschritt aus 5 Unterprogrammen bestünde, gäbe das ein "array of struct", das 5 Einträge groß ist. Jetzt hab ich über das Ganze einen Überbau, der mehrere solcher Aufgaben = Liste von UNterprogrammen = Prozess abarbeitet. So mal im Groben geschildert. Vorteil dieser Methode : Bei einer Zeitscheibe von 10ms, stehen dann 10ms minus IRQ Last für alle Unterprogramme in einem Durchgang zur Verfügung. D.H. EIN MAL 15ys Overhead für alle "Teilaufgaben" = aktuell durchzuführende Prozeduren aller Prozesse. Und nicht 15ys für jeden Prozess. Nachteil: Gibt ein Prozess die Kontrolle nicht ab, steht alles. Dieses Argument zählt bei einem ATMEGA u.ä. nicht, da diese Prozessoren keine Sicherheitsmechanismen kennen. Jeder Prozess kann prinzipiell in Kernel Bereiche schreiben = zerstören. Jetzt lasse ich mal Luft für Kommentare deinerseits. lg Mario
> Ich frage mich aber, ab wann so etwas Sinn machen würde. > Vielleicht kann mir jemand dazu ein gutes Beispiel geben! Es bringt dann Vorteile wenn ein Projekt so gross das mehrere Leute daran arbeiten weil es dann einfacher ist ihre Aufgaben voneinander zu trennen. Bei kleineren Sachen gibt es einen graubereich wo man sowohl herkoemmlich (Statemachine, Timer, IRQ) wie auch mit so einem Betriebsystem in etwa dasselbe erreichen kann. Da ist es dann wichtiger was der Programmierer so gewohnt ist. Bei sehr kleinen Controllern (1k Ram oder weniger) ist es dann meistens Quatsch oder gar unmoeglich. Allerdings verschieben sich die Grenzen auch durch das Problem das man loesen moechte und durch die Hardware die man zur Verfuegung hat. Letztlich ist das also eine Entscheidung wo Erfahrung sinnvoll ist. Olaf
holger schrieb: > "Gleichzeitig" geht auf einem Atmega nicht. Da liegst du schon mal voll > daneben. Das ist kein Multicore. Multitask != Multicore Eine der Stärken z.B. des Amigas war das Multitasking, mir wäre es aber neu, dass der MC68000, oder seine Nachfolger, mehrere Cores hat. Der TE hat ja nicht grundlos "" benutzt ;)
:
Bearbeitet durch User
Ein OS mit mehreren Tasks verhält sich nicht anders wie ein normales Programm mit Interrupts. Das normale Programm ist quasi die Task niedrigster Priorität. Jede Interrupt-funktion ist eine Task höherer Priorität, die aufgrund von Events gestartet wird: Timer, SIO Byte reingekommen, ADC-wandlung fertig. Dazu parallel ist die Frage, ob Tasks sich unterbrechen können, analog geschachtelte Interrupts. Der wesentliche Punkt ist aber, dass Interrupts sich immer beenden müssen und neu gestartet werden. Das gibt es zwar auch bei OS, z.b. Autosar, Basic Tasks. Verbreitet ist aber, an jeder Stelle Rechenzeit abgeben zu können mit sleep oder wait. Das erfordert dann einen Scheduler und ein wenig Aufwand, es gibt aber genügend RTOSe mit wenigen KB Rom und RAM unter 1k.
Schau Dir mal Protothreads von Adam Dunkels an. Dort kannst Du - ohne ein ausgewachsenes RTOS aufsetzen zu müssen - sehr gut nachvollziehen, wie ein kooperatives Multitasking so in etwa funktioniert. http://dunkels.com/adam/pt/ Bei kleinen Projekten setze ich Protothreads sehr oft ein. Aber man muss schon aufpassen, wann es an der Zeit ist, die Reissleine zu ziehen. Denn manche Projekte bleiben nicht wie geplant klein, sondern wachsen. Und je weiter das Projekt waechst, desto unhandlicher und verworrener wird es mit Protothreads. Aber für den Einstieg und für kleine Projekte ist es sehr empfehlenswert.
Was man bei der Entscheidung Pro/Kontra präemptives Multithreading immer beachten sollte ist die Synchronisation. Wenn mehrere Threads auf die gleichen Daten zugreifen, muss man dies mit Mutexen, Semaphoren, Condition Variables usw. absichern um Race Conditions zu vermeiden. Die Implementation derer ist nicht ganz einfach, aber die Nutzung auch nicht: Tatsächlich ist es sehr schwierig, ein wirklich 100% korrektes Multithreading-Programm damit zu erstellen. Man kann sich sehr leicht Fehler einbauen, die erst nach Monaten im Betrieb auftreten. Besonders gemein wird es bei Multicore-systemen mit Caches; das ist bei Mikrocontrollern zum Glück nicht so relevant. Wenn man statt Mutexen einfach die Interrupts komplett sperrt handelt man sich neue Probleme ein; man verliert die Echtzeit-Fähigkeit und kann ein so implementiertes Programm nur mit großem Aufwand auf echtes Multithreading portieren. Ein weiteres aber nicht alleine ausreichendes Mittel zur Synchronisation sind Atomics; diese werden z.B. von ARM unterstützt, von AVR aber nicht, weshalb Multithreading da auch weniger Sinn macht. Allgemein sind die ARMs explizit für Multithreading gemacht (sowohl Cortex-A als auch -M), die AVRs aber nicht. Auf ARM ist es also sowohl einfacher als auch effizienter...
SemiTech schrieb: > Und die 2. Frage die ich mir stelle ist folgende: > Bei zeitkritischen Prozessen, wo z.B. innerhalb von 10 Taktzyklen ein > Byte über die Serielle Schnittstelle übertragen werden soll, weil es > sonst zu Komplikationen führen würde, da wäre es doch verheerend mitten > im Prozess rauszuspringen. Wie löst man das in diesem Fall? Kann man da > einfach für die 10 Taktzyklen die Interrupts kurz ausschalten? Was wäre > aber, wenn genau in diesem Moment ein wichtiges Interrupt stattfinden > sollte, wie z.B. beim Timer. > Wie ließe sich das Problem lösen? Solchen Zugriff sollte dann ein präemptives Betriebssystem selbst erledigen, und das mittels geeigneter Schnittstellen bereitstellen. Dann kann es selbst Einfluss auf den Task-Scheduler-Timer nehmen. Um zB. auch zu verhindern, dass verschiedene Tasks gleichzeitig auf die gleichen Ressourcen zugreifen. Der AVR hat wohl aber keine Mittel, um Tasks den Zugriff etwa auf Ports zu verbieten.
Multitasking braucht man eigentlich immer, selbst bei den kleinsten Applikationen. Z.B. eine Weckuhr hat schon mindestens 5 Tasks, die gleichzeitig ausgeführt werden und sich nicht gegenseitig behindern dürfen: - Anzeige - Tasteneingabe - Uhrzeit zählen - Weckzeitvergleich - Buzzer pulsen Multitasking muß nicht hochkomplex und Ressourcen verschlingend sein. Eine einfache Möglichkeit sind mehrere Statemaschines, die jeweils nur eine Aktion ausführen, sich den nächsten State mehrken und zu Mainloop zurück kehren. Die Mainloop ruft sie der Reihe nach auf, aber da sie nur wenige µs lange Aktionen ausführen, wirkt es für den Benutzer, als würden sie parallel ausgeführt. Z.B. Protothread arbeitet nach diesem Prinzip. Die Macros sind allerdings nicht so leicht zu verstehen und können Seiteneffekte haben. https://de.wikipedia.org/wiki/Protothread Man kann solche Statemaschines aber auch direkt hinschreiben mit sichtbaren Returnpunkten.
Ein Kollege hat so eine coole Funktion geschrieben: RunDelayedFunction(FUNKTIONSNAME, 5) // führt nach 5s die Funktion auf. in der mainloop steht dann nurnoch: ExecuteDelayedFunction(); Hier wird der eigentliche Scheduler ausgeführt. die ExecuteDelayedFunction() wird auch immer dann ausgeführt wenn ich auf irgendwas warten muss (Anstatt einer while(true)(für ADC-Wandler oder sonstiges)) Gruß Anselm
Anselm schrieb: > Ein Kollege hat so eine coole Funktion geschrieben: > RunDelayedFunction(FUNKTIONSNAME, 5) // führt nach 5s die Funktion auf. Ich finde so einen Scheduler auch recht nützlich. Die auslösende Task braucht sich um nichts mehr zu kümmern. Beitrag "Wartezeiten effektiv (Scheduler)"
SemiTech schrieb: > Und die 2. Frage die ich mir stelle ist folgende: > Bei zeitkritischen Prozessen, wo z.B. innerhalb von 10 Taktzyklen ein > Byte über die Serielle Schnittstelle übertragen werden soll, weil es > sonst zu Komplikationen führen würde, da wäre es doch verheerend mitten > im Prozess rauszuspringen. > Wie löst man das in diesem Fall? > Kann man da einfach für die 10 Taktzyklen die Interrupts kurz > ausschalten? Was wäre aber, wenn genau in diesem Moment ein wichtiges > Interrupt stattfinden sollte, wie z.B. beim Timer. > Wie ließe sich das Problem lösen? > > (Bei evtl. Codebeispielen bitte möglicht in Assembler, da nur geringe C > Kenntnisse vorhanden sind) Aus diesem Grund besitzen RTOS ihre Primitiven in doppelter Ausführung. Also gibt es beispielswiese neben "RingbufferSend" noch ein "RingbufferSend_fromISR". Damit muss man trotz Threads nicht auf Hardware Interrupts verzichten und kann das Byte von der seriellen Schnittstelle zeitgerecht einlesen.
Das man ohne preemptives Multitasking weit kommen kann beweisen Windows 3.x und frühere Versionen von Android. Beide Betriebssysteme setzen auf Event Queues. Das Betriebssystem legt Ereignisse (Tastendruck, Touch, Timer, Datenpakete übermittelt) in Warteschlangen. Es führt die main Loops der Anwendungsprogramme abwechselnd aus, bis das Programm freiwillig die Kontrolle wieder abgibt. Der Haken dabei ist: Wenn ein Programm die Kontrolle eben nicht mehr abgibt, hängt der ganze Rechner. Das ist bei Servern sehr lästig, aber auch bei Desktop PC wenn z.B. ein größerer Druckauftrag deswegen hängen bleibt oder wenn man gerade gemachte Arbeiten noch nicht gespeichert hat. Preemptives Multitasking unterbricht die Programme (threads) aktiv, so das ein einzelnes Programm nicht mehr so einfach das ganze System zum Stillstand bringen kann. Jetzt frage dich: Wie wichtig ist dieses Feature auf deinem Mikrocontroller? Lässt du darauf mehrere Programme laufen, denen du nicht traust und die sich nicht gegenseitig blockieren dürfen? Wohl kaum. Es gibt aber noch einen Zweiten Vorteil: Solange die Programme so tun können, als wären sie alleine auf dieser Welt (kein Datenaustausch untereinander und keine gemeinsam genutzten Schnittstellen), ist deren Programmierung sehr vie einfacher, wenn das Betriebssystem sich um das Umschalten kümmert. Wie andere schon weiter oben schrieben, endet der Spaß jedoch wieder schnell, sobald die Programme gemeinsam auf irgend etwas zugreifen. Also ist mein Fazit: Preemptives Multitasking ist eine feine Sache, aber nicht auf Mikrocontrollern eher nicht.
Stefanus F. schrieb: > Also ist mein Fazit: Preemptives Multitasking ist eine feine Sache, aber > nicht auf Mikrocontrollern eher nicht. Im Prinzip hat man das ja immer auf Mikrocontrollern. Ich denke aber, die meisten hier, die Mikrocontroller benutzen, haben immer nur ein Programm auf dem Mikrocontroller laufen. Die Frage ist auch, was man als Programm definiert. Ich denke, je nachdem wie man es definiert, haben hier viele doch schon eine Art Multitasking auf nem AVR oder ähnliches benutzt. Wenn ich mein Netzteil mal so anschaue, das fragt Potis ab, misst Spannung und Strom, Temperatur und, ganz unabhängig davon, quatscht das Netzteil via serieller Schnittstelle mit dem Rest der Welt. Ich könnte also schon zumindest einen Teilbereich als Netzteil-Programm definieren und ein Teilbereich als Kommunikations-Programm und beide Teile laufen unabhängig voneinander und zwar nebeneinander. Das zeigt mir eigentlich nur: Wenn man mal genauer drüber nachdenkt sind die Single-Task-Programme eher die Ausnahme. Wenn man lernt und erst einsteigt in die µC-Welt sind Single-Task-Programme noch häufig, ja die Regel, aber wenn man konkrete Aufgaben hat wirds ganz schnell eng nur ein Programm auf dem µC zu haben. Ich sag mal, das ist Multitasking eigentlich die Regel und nicht die Ausnahme.
:
Bearbeitet durch User
Stefanus F. schrieb: > Wohl kaum. Schön wärs :-) Oft hat man doch alle möglichen Libraries und Treiber, welche eben nicht event-basiert arbeiten. Da stehen dann diverse Warteschleifen drin, welche auf externe Hardware warten. In dieser Zeit könnte man präemptiv in andere Threads wechseln und diese bearbeiten. Diese Libraries komplett umzubauen ist auch nicht immer realistisch.
> Schön wärs :-) Oft hat man doch alle möglichen Libraries und Treiber, > welche eben nicht event-basiert arbeiten. Da stehen dann diverse > Warteschleifen drin, welche auf externe Hardware warten. Wer sowas verwendet disqualifiziert sich doch selbst aus der auch nur halbwegs professionellen Softwareentwicklung raus und dann brauch man auch kein Multitasking. Aber mal ein Beispiel wo es ganz nett ist: Du hast eine Steuerung die dir wichtig ist. Zum Beispiel weil sie dein Seewasseraquarium regelt und dir schnell 10kEuro schaden entstehen wenn da was schief geht. Dann waere vielleicht eine Task in deinem Betriebssystem ganz nett die immer kontrolliert ob alle anderen Tasks laufen, ob deren Rechenzeit im erlaubten Bereich ist, ob Werte plausibel sind, ob der Stackpointer brauchbar aussieht. Und nur wenn alles stimmt wird der Watchdog zurueckgesetzt. Olaf
Olaf schrieb: > Wer sowas verwendet disqualifiziert sich doch selbst aus der auch nur > halbwegs professionellen Softwareentwicklung raus und dann brauch man > auch kein Multitasking. Dann nenne mir doch mal einen professionellen Weg wie man z.B. ein WLAN-Modul oder eine SD-Karte anbindet.
Niklas G. schrieb: > Dann nenne mir doch mal einen professionellen Weg wie man z.B. ein > WLAN-Modul oder eine SD-Karte anbindet. Zum Beispiel (da hast du WLAN und SD Karte zusammen): http://stefanfrings.de/net_io/index.html Das war eins der wenigen Mikrocontroller-Programme, die ich für die Industrie geschrieben habe. Das Multitasking basiert auf einer Main-Loop, welche die Unterprogramme nacheinander aufruft. Die Unterprogramme sind wiederum Zustandsautomaten. Warteschleifen kommen dort nicht vor - würden auch nicht funktionieren. In Android Anwendungen durfte man bis vor Kurzem auch keine Warteschleifen verwenden, weil sonst die gesamte GUI hing (da single-threaded). Während Android auf einem Linux Kern basiert und nur die GUI single Threaded war, war das ganze Windows 3.x single threaded. Wenn da eine GUI hing, reagierte die Maus nicht mehr und der Drucker blieb stehen. Trotzdem war Windows 3.11 Netzwerkfähig. Was ich relativ häufig sehe ist, dass für die Netzwerk-Kommunikation ein separater Mikrocontroller verwendet wird, der von der Haupt-Steuerung des Gerätes losgelöst ist. Zum Beispiel in Druckern, Messgeräten und Telefonanlagen. Das ESP-01 Modul wurde für solche Anwendungsfälle gemacht, ebenso die Produkte der Firma Wiznet.
SemiTech schrieb: > Ich beschäftige mich gerade mit Betriebssystemen in Mikrocontrollern. > Das wichtigste Merkmal vom OS scheint wohl das Multitasking bzw. die > Prozessverwaltung zu sein. > ... > Davor werden aber alle Variablen im Stack zwischengespeichert und der > Prozessverwaltung mitgeteilt,... So, du beschäftigst dich. Also hast du keinen realen Anwendungsfall vor der Nase, der gelöst werden soll. Nun, für preemptives Multitasking werden Prozesse oder Threads definiert, wobei jeder Prozess seinen eigenen Stack hat, wo im Unterbrechungsfalle die CPU-Register gespeichert werden, damit man sie bei Wiederbeleben des Prozesses wiederherstellen kann. Das Ganze funktioniert aus Sicht eines Prozesses also wie das Pausieren des Ablaufes durch einen Interrupt. Aber ein gewöhnlicher Interrupt steckt nicht dahinter, sondern es ist eine Verwaltung, die anhand diverser Dinge entscheidet, mit welchem Prozeß es denn weitergehen soll. Das ist alles kompliziert und schluckt deshalb Platz und Zeit und man kann sich in jedem Prozeß zwar blockierend wie beim Abarbeiten eines PAP benehmen, muß aber trotzdem auf den Rest der Welt Rücksicht nehmen, z.B. indem poplige Warte-Trampelschleifen einen "Sleep"-Aufruf des OS enthalten, um nicht benötigte Rechenzeit zurückzugeben. Ich halte derartige Firmware-Konstrukte für µC in den allermeisten Fällen für nicht zweckmäßig. Stattdessen ist es dort weitaus besser, mit Events und kooperativem Multitasking zu arbeiten. W.S.
Stefanus F. schrieb: > Zum Beispiel (da hast du WLAN und SD Karte zusammen): Der SD-Karten-Zugriff sieht mir doch sehr synchron-blockierend aus:
1 | MMC_SPI.DATA = byte; //Sendet ein Byte |
2 | loop_until_bit_is_set(MMC_SPI.STATUS,SPI_IF_bp); |
und
1 | for (int i=0; i<5; i++) { |
2 | if (mmc_init()==1) { |
Beim WLAN-Modul schreibst du sogar im Kommentar dass es dauern kann:
1 | // This function usually takes only some few ms, but it may take longer
|
2 | // when the WLAN module is busy.
|
3 | void executeCommand(char* command) |
W.S. schrieb: > Nun, für preemptives Multitasking werden Prozesse oder Threads > definiert, wobei jeder Prozess seinen eigenen Stack hat Jeder Thread hat einen eigenen Stack, jeder Prozess hat min. 1 Thread. Wenn man überhaupt Prozesse implementiert.
:
Bearbeitet durch User
Niklas G. schrieb: > Der SD-Karten-Zugriff sieht mir doch sehr synchron-blockierend Korrekt erkannt. Das hätte ich dort noch besser machen können. Hier wird maximal 8 SPI Takte lang blockiert. An dieser Stelle habe ich die Library einfach so verwendet, wie sie der Autor geliefert hat. Es ist aber nicht so blockierend, dass Netzwerk-Kommunikation und SD-Karten Zugriff sich gegenseitig ausschließen. Du kannst Files von der SD Karte downloaden, gleichzeitig eine andere Webseite benutzen, I/O Pins kontrollieren und die DCHP Adresse aktualisieren. > Beim WLAN-Modul schreibst du sogar im Kommentar dass es dauern kann Ich wollte Dir eigentlich nur die die Ethernet Variante als Beispiel zeigen. Die WLAN variante ist billig zusammen gefrickelt. Die WLAN Variante passt hier nicht zum Thema, denn da befindet sich der ganze IP Stack auf einem separaten Mikrocontroller. Ich weiß, ich bin selbst an der Irritiation Schuld, weil du nach WLAN gefragt hattest und ich habe mit der Ethernet Variante geantwortet. Sorry, da habe ich gepennt.
Stefanus F. schrieb: > Es ist aber nicht so blockieren, dass Netzwerk-Kommunikation und > SD-Karten Zugriff sich gegenseitig ausschließen. Manche SD-Karten-Operationen können 1-2 Sekunden dauern; deine Anforderungen an "nicht-blockierend" scheint ja sehr gutmütig zu sein. Stefanus F. schrieb: > Ich wollte Dir eigentlich nur die die Ethernet Variante als Beispiel > zeigen Ethernet ist ja auch vergleichsweise easy. Es ging mir daher schon um WLAN. Stefanus F. schrieb: > Die WLAN Variante passt hier nicht zum Thema, denn da befindet > sich der ganze IP Stack auf einem separaten Mikrocontroller. Kommt aufs Modul an. Der IP-Stack ist sowieso nicht so sehr das Problem; lwIP z.B. ist vorbildlich asynchron programmiert. Die Low-Level-Treiber hingegen gerne mal nicht so.
Niklas G. schrieb: > Manche SD-Karten-Operationen können 1-2 Sekunden dauern; deine > Anforderungen an "nicht-blockierend" scheint ja sehr gutmütig zu sein. Ja, wie gesagt habe ich es mir an dieser Stelle einfach gemacht. > lwIP z.B. ist vorbildlich asynchron programmiert. Die Low-Level-Treiber > hingegen gerne mal nicht so. Ja, ebenso das µIP vom selben Autor, auf dem meine verlinkte Firmware basiert, die ich als Beispiel nannte.
Hallo, ich wollte nur noch etwas Futter liefern: wie bereits oben beschrieben, haben die meisten RTOS pro Task einen eigenen Stack Bereich. Hier muss man sehr genau den Stack-(Heap) Bedarf kalkulieren. Sonst knallts oder der speicher reicht nicht. Lösungen sind hier kooperative RTOS mit Stichwort: SINGLE STACK RTOS auch gibt es ein Patterns namens ACTIVE OBJECT, das das Aufgabenhandling abstrahiert. hier mal noch einen Link den ich auch sehr interessant finde: http://www.state-machine.com/doc/concepts Grüße, Adib.
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.