sehr rudimentäres kooperatives multitasking

Microcontroller, Steuerungen, Protokolle und und und.

Moderators: thomasf, random

Post Reply
User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

sehr rudimentäres kooperatives multitasking

Post by random » Tue 15 May, 2007 11:32 pm

Hi Leutz,

auch wenn das noch ein klein wenig entfernt ist vom richtigen multitasking, so kommt es doch den kooperativen multitasking sehr nahe und bringt einiges an interessanten Funktionen mit sich.

Worum geht es? Ich dachte mir, ich lerne mal etwas über Funktionspointer und habe in ner ruhigen Stunde mal ein kleines, sowas wie Multitasking OS zusammengebaut.

Um das eigendliche Context-Switching muss ich mir noch Gedanken machen, dazu muss man etwas tiefer in asm rein und u.a. die CPU-Register sichern.


Was kann das ?

nun ja, man schaue sich folgendes an :-)

Code: Select all


#include <stdio.h>
#include <conio.h>
#include "main.h"
#include "scheduler.h"


int func1(int);
int func2(int);
int func3(int);


int func1(int a)
{
	static counter1=0;

	printf("\nTask 1: %i", a);
	deleteTask(func1);

	return(0);
}


int func2(int a)
{

	printf("\nTask 2: %i", a);
	//deleteTask(func2);

	return(0);
}



int func3(int a)
{

	printf("\nTask 3: %i", a);
	//deleteTask(func3);

	return(0);
}




int main()
{
	int i=0;


	schedulerInit();

	// insert new tasks
	insertTask(func1);
	insertTask(func2);
	insertTask(func3);

	// set tasks active
	setTaskState(func1, TASK_RUNNING);
	setTaskState(func2, TASK_RUNNING);
	setTaskState(func3, TASK_RUNNING);


	printf("\nScheduler started...:");

	// run the scheduler. later this will be done by an isr with constant timing
	for(i=0; i<10; i++) 
	{
		printf("\nNo. %i", i);
		scheduler();
	}

	
	printf("\n\n");
	return(1);
}
Die Parameter, die die Tasks als Übergabe bekommen, dienen hier nur zum Testen. Natürlich kommen die in einer richtigen Anwendung nicht vor.

...und das for(i=0; i<10; i++) ist natürlich auch nur dafür da, das Verhalten zu begucken, da mit ansonsten die Ausgabe der printf's davonrennt :-)

Das komplette Paket zum nur testen (ordner debug mit der .exe) und dem MS VC-Projekt gibtz hier:
http://medra.dyndns.org/thOS/scheduler/ ... ointer.rar

sowie auch die einzeldateien zum einsehen.


Ich denke, selbst diese rudimentäre Sache ermöglicht schon eine recht mächtige Programmierung, wenn man in die Tasks mit einbaut, dass sie rechenzeit abgeben.
Noch ist das nicht implementiert, ich denke noch über eine Art sleep(ms) funktion nach, sowie über eine prioritätssteuerung.

Weiterhin kommt noch die Messung der einzelnen Tasks mittels Timer hinzu.


Wer jetzt sagt, das krieg ich doch auch hin mit

while(1)
{
func1();
func2();
func3();
}
sollte sich das ganze doch vllt etwas genauer ansehen.
Sicher nicht für jesen Microcontroller interessant, aber dennoch ein interessanter Ansatz mit vielen schönen Möglichkeiten, wenn man seine Software erweitern will.

Auch interessant für die Kombination mit (m)einer Shell, wo der Benutzer direkten Zugriff auf das System hat.

Oder man könnte Bedarfsgesteuert aus einer ISR oder von wo auch immer heraus eine Task auf einfache Art aktivieren, und sie entweder ne weile (oder einfach nur ein mal) laufen lassen, und dann mit irgendeinem anderen kriterium oder irgendwo anders wieder deaktivieren. Sie wird ja - auch wenn vorher deaktiviert - immer bis zum "ende" ausgeführt.

Greetz,
/r.


PS: Nicht alle auf einmal hauen *duck* :twisted:
Grün ist blauer als Rot...
NetLase-LC Firmware.

User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

Post by random » Thu 17 May, 2007 10:31 pm

65 reads aber keinen interessierts ? :lol:

Im Moment gehts weiter mit Priorisierung, Message-Queues und waits. Ist aber noch nicht stable :-)


Greetz,
/r.
Grün ist blauer als Rot...
NetLase-LC Firmware.

User avatar
sanaia
Posts: 812
Joined: Sun 20 Jun, 2004 5:49 pm

Post by sanaia » Fri 01 Jun, 2007 10:16 pm

interessieren schon, aber wer kann da mitreden ? :roll:

Ich habe in meiner soft auch einen prozess scheduler und multitasking drin. Implementiert ist das ganze über verkettete listen, die der scheduler abarbeitet. Jedes listenelement indiziert einen von 1024 bytecode speichern, wobei jeder seinen eigenen stack besitzt. Der einzige unterschied zu 'echtem' code ist, daß diese codelets alle nach dem fall-through prinzip arbeiten, weil sie in jedem cycle von vorn gestartet werden müssen.
Die wait funktion, die auf ein externes signal wartet ist so implementiert, daß sie testet, ob die bedingung für die codefortsetzung erfüllt ist. Ist das der fall, geht es mit der nächsten anweisung weiter, ansonsten wird die adresse des wait codes als resume adresse auf dem stack gelegt und beim nächsten cycle der code nicht ab position 0, sondern ab dem wait befehl wieder abgearbeitet.

Ist somit also auch kooperatives MT, weil der wait-code die kontrolle an den scheduler zurückgibt.

Das ergebnis ist, daß ich problemlos 1024 effekte pro display stacken kann - das ganze muß man allerdings auch noch irgendwie sinnvoll adressieren können. Bei max. 8 projektoren macht das 8192 zu addressierende codelets - unmöglich mit DMX, und mit MIDI nur bei verwendung mehrerer ports möglich.
* godsh # ERROR 406: file corrupt: config.earth --- reboot universe? (Y/N) *

User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

Post by random » Sat 02 Jun, 2007 11:22 am

ei hauaha, harter tobak :lol:

Ich habs hier gepostet, um denen, die uC proggen, mal zu zeigen, dass man mit ein wenig overhead eine ganze reihe mehr möglichkeiten hat.

Meine aktuelle Version davon arbeitet auch mit verketten Listen, aber sie gefällt mir noch nicht so gut, dass ich sie hier posten kann :-)
Nächste sache sind dann messageQueues zur task-komunikation.

Wie ich eine wait(time); funktion aufsetze, mit der die task rechenzeit abgeben kann, weiss ich noch nicht.

Ist im Moment auch erst mal wieder nach hinten verschoben. Wenn ich mich demnächst an den LPC3000 (ARM926) setze (Cashes, MMU etc) wirds damit weitergehen.

---
Das schöne an der Lösung oben ist, dass überhaupt keine Verpointerung schiefgehen kann, weil man nicht - wie beim preemtiven - der task die rechenzeit wegnimmt (dann muss man nämlich deren stack sowie die Register sichern (incl. Status-Reg). Das wird schon umfangreicher ...


Alles in allem ein interessantes Thema, welches für mich noch recht neu ist. Ich taste mich mit diesen Sachen da rein, und war halt überrascht, mit wie wenig Aufwand man doch viel erreichen kann.


Greetz,
/r.


@sania: Mal ne Frage :-)
WER bist du eigendlich? Also, was arbeitest/machst du?
Scheinst hier im LF das Universalgenie im Hintergrund zu sein *grins*
Grün ist blauer als Rot...
NetLase-LC Firmware.

User avatar
sanaia
Posts: 812
Joined: Sun 20 Jun, 2004 5:49 pm

Post by sanaia » Sat 02 Jun, 2007 12:49 pm

Wie ich eine wait(time); funktion aufsetze, mit der die task rechenzeit abgeben kann, weiss ich noch nicht.
Nur so als gedankenanstoß: Bei mir bekommt jedes codelet vom scheduler, wenn es gestartet oder aufgeweckt wird, einen timestamp versehen, da die codelets genau wissen müssen,wie lange sie im 'blackout' waren. Eine sleep funktion würde ich so implementieren, das diese einen timestamp auf den stack legt und ein 'sleeping' flag setzt. Jedes mal, wenn der scheduler dieses program wieder abarbeiten will sieht er erst einmal nach, ob das sleep flag gesetzt ist. Wenn ja, vergleicht er die vergangene zeit seit dem timestamp bis jetzt. Ist sie kleiner als der sleep wert, dann bricht er ab und springt zum nächsten program in der prozessliste, ist sie jedoch größer als der sleep wert, dann wird das aktuelle programm ab dem sleep befehl weiter ausgeführt.
Bei echtem maschinencode muß man nur aufpassen was noch alles auf dem stack liegt, wenn der sleep befehl in den scheduler springt und dieser das programm auf eis legen will. Üblicherweise muss man dann den ganzen stack abspeichern und beim nächsten cycle wieder herstellen.
Alles in allem ein interessantes Thema, welches für mich noch recht neu ist. Ich taste mich mit diesen Sachen da rein, und war halt überrascht, mit wie wenig Aufwand man doch viel erreichen kann.
Ist bei mir ähnlich. Auf die lösung bin ich selber gekommen, weil es die einzige variante war, die logisch sinn machte und das problem löste.
WER bist du eigendlich?
Psst ... Image
* godsh # ERROR 406: file corrupt: config.earth --- reboot universe? (Y/N) *

User avatar
random
Posts: 2161
Joined: Fri 03 Aug, 2001 12:00 pm
Do you already have Laser-Equipment?: Dynamics, Easy-/NetLase, NetLaseLC
Some devices that emit light.
Location: München - 85540 Haar
Contact:

Post by random » Sat 02 Jun, 2007 8:47 pm

sanaia wrote:
WER bist du eigendlich?
Psst ... Image
*geheimdienst* 8) :shock:
Cooles Smiley!


Jo, danke für die Tips. Mir grauts noch ein wenig davon, die Task-Stacks und die Prozessorregister zu sichern. Wenn ich das mache, mach ichs gleich Preemtiv (also Timeslices).

Erst mal gehts so weiter, wenn ich diese Version mit Liste und MessageQueue gut am laufen habe, werd ichs mal posten (vielleicht finden sich ja noch andere Interessenten, gelesen haben's ja ne Menge! :shock:


Greetz,
/r.
Grün ist blauer als Rot...
NetLase-LC Firmware.

Post Reply

Return to “Microcontroller & Steuerungen”

Who is online

Users browsing this forum: No registered users and 8 guests