Hallo Nutzerinnen und Nutzer ;)
Ich habe ein eigenes OS für AVR Mikrocontroller geschrieben, dass ich
euch hiermit (inkl. Sourcecode) zur Verfügung stellen möchte.
Ich habe es Nano OS getauft.
Es beinhaltet folgende Features:
-preemptives Multitasking inkl. Prioritäten,
-binäre Semaphore (Mutex),
-Message Queues,
-ein einfaches Speichermanagement (basiert auf einem array im RAM) sowie
-Funktionen zur Task-Kontrolle (anhalten, löschen usw...)
Die einzelnen Funktionewn sind im Quelltext dokumentiert.
Das zip beinhaltet folgende Files:
/software/nano_os.c - Das main-File
/software/system/header/nano_os.h - die zentrale Konfigurationsdatei
/software/system/idle.c - den idle-task
/software/system/kernel.c - den "kernel"
/software/system/memory.c - das Speichermanagement
/software/system/message.c - die Message Queue
/software/system/scheduler.c - den Scheduler
/software/system/tasks.c - die Task-Steuerung
/software/user/user.c - die Usersoftware
/software/user/user.h - das header-file für die User-Software
Das OS ist im Rahmen einer Diplomarbeit entstanden, die hier leider
nicht veröffentlicht werden kann.
Es wurde entwickelt auf einem AtMega 168; Für andere Prozessoren muss
das File nano_os.h angepasst werden.
Die Dokumentation des APIs findet sich in den einzelnen Dateien; als
User-Software ist eine Binäruhr für einen Atmel AtMega 168 dabei, die
die Uhrzeit über PORTC und PORTD ausgibt. Der Schaltplan der Hardware im
eagle-Format liegt bei.
Mich interessiert insbesondere das Feedback. Also viel Spass mit dem OS,
in dem sicher noch viele Fehler zu finden sind ;)
Fragen werden gern angenommen.
gruß
tobi
Gefällt mir, werd ich mal ausprobieren. :)
Unter welcher Lizenz veröffentlichst du den Code? BSD wär nett, muss
aber nich. :)
Auch als Hobbyist will ich vor Überraschungen gefeit sein. Ausserdem
weiss ich ja nie wann ich das wieder mal brauche und allenfalls ganz
"legal" auf offenen/freien Code zurückgreifen kann. Oder nach
Herzenslust rumhacken und nicht gezwungen bin, meinen Code wieder offen
zu legen, wenn ich dereinst eine Kleinserie an WallClocks verticke. ;)
> Für andere Prozessoren muss> das File nano_os.h angepasst werden.
Wenn ich das richtig sehe dann doch wohl auch scheduler.c weil dort ein
paar sehr prozessorspezifische Annahmen gemacht werden und es sogar
Assemblercode gibt.
Olaf
@Tom: Das ganze veröffentliche ich unter GNU GPL. Du kannst den Code
also gern verwenden, und auch weitergeben.
Solltest du den Code des OS selbst verändern, wäre eine Meldung
(hacker-tobi@gmx.net) nicht schlecht. Die user - Software ist hiervon
ausgenommen.
Lese ich das richtig...du baust Uhren ? Genau dafür ist dieses OS
geschrieben worden ;) Ich baue hauptsächlich Multifunktions-Uhren mit
AVR-Controllern, und daher kam die Idee, einige immer wiederkehrende
Themen zusammenzufassen, und ein OS draus zu gießen.
Hauptthemen waren dabei:
-Verschiedene Aufgaben (z.B. Display-Steuerung, Auslesen von Sensoren)
mit verschiedenen Prioritäten erledigen zu können,
-einheitliche Kommunikationswege zu schaffen und
-das ganze noch auf schwere Ausnahmefehler zu überwachen.
@Olaf: Jain ;) Wenn du das System für andere Prozessoren anpassen
willst, müsstest du die Scheduler.c anpassen.
Und auch andere Teile des Codes, welche avr-gcc - spezifische Makros
verwenden, müssten angepasst werden.
Wenn man in der Atmega - Familie bleibt, dann reicht es jedoch, die
Parameter in nano_os.h anzupassen.
gruß
tobi
Hallo Mario,
nein, denn ich sichere die Register nicht! auf den Stack, sondern in die
Task-Struktur, genauer in das für diesen Zweck vorhandene Array.
Es wäre evtl. noch als Ergänzung möglich, um dem gcc etwas Arbeit zu
ersparen, das muss ich mal testen.
aber es "geht" auch so.
gruß
tobi
hacker-tobi schrieb:> nein, denn ich sichere die Register nicht! auf den Stack, sondern in die> Task-Struktur, genauer in das für diesen Zweck vorhandene Array.
Ausschnitt aus deinem Quelltext
Ich verstehe jetzt nicht genau wieso Du "nein" behauptest und es
trotzdem machst, aber ja... Mir ist übrigens klar, dass der Stackpointer
immer wieder auf die aktuelle Task gesetzt wird.
Kann es sein, dass Du dich an GOS orientiert hast. Da sind ja schon
einige Gemeinsamkeiten.
Beitrag "GOS: einfacher preemptive multitasking scheduler"
Hallo Mar IO,
stimmt, GOS ist in der Tat recht ähnlich.
Aber nein, die beiden Systeme sind unabhängig voneinander entstanden.
Ich kannte GOS gar nicht.
GOS ist ein reiner Scheduler ohne weitere Funktionalität, wenn ich das
richtig sehe.
Ich glaub, wir haben uns missverstanden. Ich meinte, dass ich die
Register in ein Array in der Task-Struktur sichere (current->stack[]).
Dass sie zusätzlich in den Stack gesichert werden, ist korrekt, aber:
Ich hab gerade mal ausgetestet, was passiert, wenn ich das Attribut
aufnehme.
Das Ergebnis ist interessant: Bei Optimierungslevel 0 verändert sich
erwartungsgemäß die Größe des Compilats leicht nach unten, und die
Taskumschaltung erfolgt schneller als ohne das Attribut.
Bei höheren Optimierungsveln bewirkt der Eintrag hingegen nichts; Es
scheint so, wie als ob gcc von selbst erkennt, dass eine separate
Sicherung der Register unnötig ist.
Ich werde das Attribut daher mit aufnehmen; Vielen dank für den Rat.
gruß
tobi
Was man vielleicht noch dazu schreiben sollte:
Ich "verbiege" in tasks.c den Stackpointer so, dass er für jeden Task
auf eine interne Datenstruktur char[64] zeigt, welche für den aktuellen
Task unter current->stack[] zu finden ist:
t->sp = (unsigned char *)(t->stack + sizeof(t->stack) - 3);
So gesehen ist es korrekt, "PUSH" und POP" sind Stack-Operationen,
arbeiten aber in diesem Fall auf die interne Datenstruktur.
gruß
tobi
Tobi,
super cool... eine kleine Empfehlung..
da du ja eigentlich weisst, wie gross dein task stack ist, überprüfe
beim scheduler, ob der task nicht seine grenzen überschritten hat. spart
viel debuging.. am besten noch bevor register auf den stack gesichert
werden, den schon dort könnte es passieren, das Daten überschrieben
werden..
lg roman
Hallo Roman,
prinzipiell eine gute Idee. Ich nehme an, du meinst ein Konstrukt a la
if (SP >= (current->sp + STACK_SIZE))
task_anhilate(¤t);
?
Ich überlege nur gerade, wann ein Task seine Grenzen überschreitet, denn
eigentlich hat er ja auf dem Stack nichts zu schaffen ;)
Mir fallen da im Moment nur verschachtelte Funktionsaufrufe und die
Rettung der GPR ein...
Na ja, wenn ich schon dabei bin, kann ich auf die Art auch einen
Stack-underrun vermeiden mit
if (SP >= (current->sp + STACK_SIZE) || SP < current->sp))
task_anhilate(¤t)
Bitte korrigiert mich, wenn ich falsch liege.
PS. task_anhilate ist jetzt natürlich nur ein Beispiel; hier könnten
auch andere Aktionen stehen.
Hallo hacker-tobi,
bin dabei mich mit Deinem OS zu beschäftigen.
Kannst Du nicht eine abgespeckte Anleitung dazu legen?
Ich denke, daß wird auch anderen helfen sich an diese
Materie heran zu wagen, und es eher zu Benutzen.
Gruß
Hallo Lernender,
die API ist im Quelltext dokumentiert.
Es gibt eine vollständige Anleitung, diese ist aber leider in der
Diplomarbeit enthalten, und die darf ich erst veröffentlichen, wenn ich
die Freigabe dazu habe.
Sollte ich keine Freigabe zur Veröffentlichung bekommen, werde ich eine
Kurzanleitung erstellen und veröffentlichen. Aber auch das spreche ich
dann zur Sicherheit erst mit der Hochschule ab.
Also habt Geduld...
//+++++++++++++++++TASK Control Structure+++++++++++++++
2
typedefvolatilestructTask
3
{
4
volatileuint8_tID;
5
volatileunsignedcharsreg;
6
volatileunsignedchar*sp;
7
volatileTaskPrioprio;
8
#ifdef TASK_USE_SIGNAL
9
volatileTaskStatestate;
10
volatileuint8_tlaps;
11
#endif
12
volatileunsignedcharstack[STACK_SIZE];
13
}Task;
Also ich verstehe jetzt nicht ganz, wieso Du beim Checken ob ein
Stacküberlauf bzw. -unterlauf Du den Stackpointer SP mit current->sp
vergleichst???
StackÜBERlauf tritt doch auf, wenn SP kleiner als current->stack ist
1
if(SP<current->stack)...
und ein StackUNTERlauf triff auf, wenn SP größer als höchste Adresse vom
Array current->stack[]
Was mir noch aufgefallen ist, wieso eigentlich SIGNAL und nicht ISR?
Wieso springst Du aus scheduler() aus dem Interrupt zurück (letzte
Zeile, asm volatile("reti");) und wird eigentlich current ausser in
scheduler() nochmals verändert? Wenn nicht, dann macht die Zeile
"current = tasks[currentTask];" keinen Sinn, denn current ==
task[currentTask]. Wenn ja, dann würde ich noch ein volatile bei der
Deklaration von current schreiben (nano_os.h).
Hallo tobi,
ja so was habe ich gemeint...
es sind nicht nur verschachtelte funktions konstrukte, die probleme
verursachen koennen, auch lokale variablen.
btw. zb. bei Linux oder Solaris, kann man die stack groesse als
parameter angeben. Ich weiss frueher hatten wir im solaris ein page
kernel thread stack dh. 8K spaeter 16k. Meistens hat es gereicht..jedoch
wenn nicht.. big baga bum.
das waere vieleicht gar nicht so schlecht, den stack nicht als array zu
definieren, sondern dynamisch allozieren und den stack size als
parameter uebergeben beim task create.
ehh.. nur so eine dumme frage.. beim interrupt, wo wird der stack
gesichert ?? auf dem current task ??
lg roman
Jetzt habe ich mal deinen Code mit dem AVR-GCC übersetzt mit OPT=3 und
irgendwie frage ich mich ob der Code auch so funktioniert. Grund ist die
Zeile 0x175e, da wird aus dem Interrupt rausgesprungen, aber der
Ursprung ist noch nicht wieder hergestellt. Dies ist erst nach Zeile
0x1770. Ich kann mich auch irren, bin mir aber nicht 100 %ig sicher
Hi
@Mario:
Stack: Da liegst du richtig. Sorry war mein Fehler. Hatte vorhin den
Quelltext auch nicht vor mir.
Habs aufgenommen. Jetzt wird das System vom Scheduler zurückgesetzt,
wenn eine Stack-Violation auftritt.
Thema Signal: Macht der Gewohnheit. Aber es macht auch keinen
Unterschied, da Signal und ISR() das selbe bewirken. Des wegen auch das
RETI.
Thema current: kann theoretisch wegbleiben, ist ja nur ein Pointer auf
tasks[currentTask]. Ich empfinde es aber so als Vereinfachung, daher
bleibt der ;)
Thema code: Der läuft - schon in mehreren Projekten. Ich werd mir dein
File die Tage mal ansehen, heut bin ich zu müde
@Bachelor:
Das weiß ich zur Zeit noch nicht. Ich poste hier wenn ich was neues
weiß.
@Roman: Wie schon an Mario adressiert, ist die Stack-Überwachung mit
aufgenommen.
Das dynamische Management überleg ich mir die Tage mal, ob ich das z.B.
mit malloc() im heap realisiere. Aber eigentlich bin ich kein freund von
malloc(). Wird auch nur für die queues verwendet. Any better idea?
@All
Ich habe einen Ordner "doku" angelegt, und dort die komplette API
dokumentiert. Ist momentan noch eine simple API-Zusammenfassung, aber
wenn ich Zeit und die Eralubnis hab, kommt da evtl. noch mehr.
@Mar IO: Anmerkung: versuchs mal mit Optimize-Level s. Bei 3 kommt bei
mir funktionsfähiger code raus, der aber erheblich größer ist, als bei
s.
Mehr find ich heut abend nicht mehr raus...deinen Code schau ich mir die
Tage an
@All
Schön, dass das kleine OS so viel Anklang findet.
Und danke für die konstruktive Kritik.
Ich freu mich auch über positive meldungen, wenn jemand ein Projekt
damit realisieren sollte und es funktioniert ;)
@Mar IO: Nochmal wegen dem current: Ich seh grad, ich hab dich
mißverstanden. Ich dachte du beziehst dich auf den Pointer "current" an
sich, aber dir gehts ja nur um die eine Zeile.
Die kann raus. Habe ich auch erledigt.
Und dann hab ich auch noch gesehen, das die push/pop im scheduler mit
durch die if-bedingungen abgesichert werden sollten. auch das habe ich
angepasst.
also hier nochmal ein aktuelles file mit angepasstem scheduler...
ich geh jetzt ins bett
gruß und gute n8
tobi
Tobi,
eine Idee ohne den malloc.. meist weiss man ja wie viele task man
braucht und auch ca. den stack verbrauch.. dh. man koennte den stack
fuer den jeweiligen task schon global deklarieren. zumal man dann diesen
so oder so als parameter uebergeben muss, kann man immernoch diesen per
malloc allozieren.
anderseits... sollte eine task irgend etwas bloedes tun, kann man, man
dem der task ein rausschmiss gekriegt hat auch noch gleich sein stack
loeschen.
Ich habe es einmal so vorgesehen (ist schon jahre her und auf einem 68k)
dass das system sich merkt welche task memory alloziert hat. Stirbt
dieser oder tut was illegales, wird sein memory wieder frei fuer's
system.
lg roman
Guten Morgen Roman,
Okay, was gehen würde, wäre ein globales array, das die Stacks aller
Tasks aufnimmt, und dessen Größe fest vorgegeben wird.
Dann brauche ich zur Laufzeit nur den Stack-Pointer für jeden Task
passend auf einen freien Bereich entsprechender Größe in diesem Array zu
setzen.
Allerdings muss ich dann das globale Array mit (Anzahl der Tasks *
durchschnittliche Stack-size) initialisieren.
Ich bin mir nicht sicher, ob das Vorteile bringt, zumal die Stack_size
ja global in nano_os.h vorgegeben werden kann.
(Mir ist bewußt, dass ich damit Speicher einsparen kann, aber ich will
mal sehen, wie viel das in der Praxis ausmacht).
Ich werde es testen.
Das Memory Management in meinem OS arbeit übrigens genau nach diesem
Prinzip, nur das dort Speicherblöcke fixer Größe verwendet werden, was
den Algorithmus vereinfacht.
Jeder Task kann hier bis zu einer Obergrenze (MAX_BLOCKS) Speicherblöcke
reservieren, und diese auch wieder freigeben. Diese werden in einem
array verwaltet, das fixnach dem Muster (MAXBLOCKS*BLOCK_SIZE) angelegt
ist.
hacker-tobi schrieb:> Thema Signal: Macht der Gewohnheit. Aber es macht auch keinen> Unterschied, da Signal und ISR() das selbe bewirken. Des wegen auch das> RETI.
Signal ist halt veraltet, nicht ganz genau das selbe wie ISR und sollte
nicht benutzt werden. Siehe Doku
http://www.nongnu.org/avr-libc/user-manual/group__avr__interrupts.html#ga67cd0dea412157775c2f2a3ffe9fb8ff
Ausserdem springst Du mit RETI zurück aus einer Funktion (SIGNAL(...)
ist die ISR). Das I-Flag wird gelöscht, obwohl Du noch in der ISR bist.
Weiß ned ob das schlimme Auswirkungen mit sich zieht, ist halt etwas zu
früh (aber nur etwas).
hacker-tobi schrieb:> @Mar IO: Anmerkung: versuchs mal mit Optimize-Level s.
Japp, habe ich soeben (den Code vom ersten Posting). Was mir da
auffällt, dass in SIGNAL(SIG_OVERFLOW0) (Code-Adresse ab 0x1b0) ziemlich
viel auf den Stack gesichert wird (Register, SREG, Rücksprungadressen)
und in scheduer() (ab 0xa6) nochmals alle Register. Hier kannst Du
sicher etwas einsparren (siehe GOS). Was da auch auffällt, in
scheduler() kommt zuerst ein RETI, dann ein RET (zu dem man natürlich
nicht kommt) und dann in SIGNAL(...) wieder ein RETI.
Ich habe mir bis jetzt nur scheduler() angeschaut und den restlichen
Code überflogen. Was mir dabei aufgefallen ist, dass Du gerne volatile
schreibst. Zu struct und volatile kannst dir mal folgenden Thread
durchlesen (der enthaltende Link ist auch recht interessant):
Beitrag "volatile und struct"
Hi MarIO,
das mit dem reti kann ich so nicht bestätigen. nimmt man das reti raus,
wird nicht mehr aus dem Interrupt zurückgesprungen.
Was die überflüssigen volatiles angeht - die hab ich entfernt.
Und noch einen Fehler in der Funktion Queue_Init entdeckt und behoben;
dort wurde die queue->number nicht korrekt initialisiert.
ISR() funktioniert nicht wirklich. Selbst mit dem GOS-Scheduler (im
original, also mit direktem Aufruf als ISR) nicht. Es werden massiv
Register überschrieben. Hier liegt wohl noch ein Fehler vor. Entweder
bei mir oder beim Compiler. Aber das werde ich heut abend nicht mehr
untersuchen.
Mit Signal funktionierts problemlos, das reicht mir momentan gerade. Ich
bin mitten dabei, mich in nen neuen Job einzuarbeiten, und mein Studium
zuende zu bringen, da ist Zeit mangelware....
Anbei die aktuelle Version.
gruß
tobi
Tobias W. schrieb:> stimmt, GOS ist in der Tat recht ähnlich.> Aber nein, die beiden Systeme sind unabhängig voneinander entstanden.> Ich kannte GOS gar nicht.> GOS ist ein reiner Scheduler ohne weitere Funktionalität, wenn ich das> richtig sehe.
Dann hat GOS wohl von dir abgeschaut?
GOS:
@Helli: Das Thema hatten wir jetzt schon... sorry ich weiß was ich
geschrieben hab und was nicht.
Und ich sage es nochmal...GOS ist ein reiner Scheduler, Nano OS bietet
ja doch etwas mehr Funktionalität, oder?
hacker-tobi schrieb:> @Helli: Das Thema hatten wir jetzt schon... sorry ich weiß was ich> geschrieben hab und was nicht.> Und ich sage es nochmal...GOS ist ein reiner Scheduler, Nano OS bietet> ja doch etwas mehr Funktionalität, oder?
Das ist nicht das Problem ... Man muss auch seine Quellen angeben, wenn
man etwas fremdes verwendet hat.
Niemand hätte irgendwas gesagt, wenn du gleich geschrieben hättest, dass
du dich von GOS inspirieren hast lassen ...
Aber eine Lüge ist eine Lüge ...
Und mal davon abgesehen...wenn du dir den Scheduler genauer ansiehst, so
sind doch einige Unterschiede da:
-Ich rufe den Scheduler via Signal() auf, nicht als ISR. Das kommt
daher, dass ich den Scheduler schon vor längerer Zeit geschrieben hab -
für ein Uhrenprojekt- und ihn für Nano OS übernommen habe.
-PUSH und POP und die Struktur sind identisch, aber der Prozessor muss
ja immer das selbe ausführen, um einen Task-Switch auszulösen, ergo ist
das wohl nicht verwunderlich. Ok, die Makrobezeichnungen sind identisch.
Daher sehen sich die Programmteile ähnlich.
Aber das wird sich auch demnächst ändern, da ich die Registeranzahl
variabel gestalten will, wegen der neuen AtTinys, die nur noch 16
Register haben.
-Der Scheduler in Nano OS hat einige Fähigkeiten, die der GOS-Scheduler
nicht hat, wie z.B. die möglichkeit, Tasks für eine definierte Zeit
schlafen zu legen.
Insgesamt verstehe ich den Einwand, das die Scheduler ähnlich sind, aber
es gibt eben doch unterschiede.
Ich hoffe damit ist dieses (aus meiner Sicht -sorry- leidige) Thema
erledigt.
@Helli: Nochmal...ich kann nichts angeben, was ich nicht kenne.
Und mich deswegen der Lüge zu bezichtigen - meinst du nicht, dass das
etwas zu weit geht? Sorry, aber du hast nicht danebengesessen, als ich
das OS geschrieben hab, oder irre ich mich? Also woher willst du wissen,
was ich geschrieben hab und was nicht?
Und wenn ich gos als Quelle benutzt hätte, würde ich es auch angeben.
Warum sollte ich es denn verheimlichen?
Aber ich kann gern die Makrobezeichnungen ändern, und den Programmtext
umstellen, wenn dich die ähnlichkeiteen stören (das meine ich ernst,
nicht als witz).
gruß
tobi
Echt merkwürdig ...
hacker-tobi schrieb:> Aber ich kann gern die Makrobezeichnungen ändern, und den Programmtext> umstellen, wenn dich die ähnlichkeiteen stören (das meine ich ernst,> nicht als witz).
Das hier ist von dir (14.09.2010):
Sind die beiden Codeschnippsel nicht irgendwie identisch? Sogar die
Variablen heißen alle gleich usw ...
Oder hast du GOS auch geschrieben?
Wenn das für eine wissenschaftliche Arbeit wäre, würde ich mir langsam
ernste Gedanken machen
Ach, es gibt auch noch eine andere Möglichkeit ... Der GOS-Entwickler
meinte, er würde seinen Scheduler in den AVRWizard einbauen ...
Hast du den vlt verwendet?
Das würde das erklären ...
Frank M. schrieb im Beitrag #1868712:
> Aber zu behaupten, Du würdest GOS gar nicht kennen, ist dummdreist.
Vlt kennt er GOS wirklich nicht ... Ich hab grad nachgeschaut, das
Multitasking-Dings ist im AVR-Wizard auch eingebaut worden ...
Aber einen Wizard zu verwenden für das, was man selbst machen soll ...
Hoffentlich hat er das wenigstens angegeben ...
Ich habs schonmal gesagt...ich gebe zu, das sich die Scheduler ähnlich
sehen. Von daher verstehe ich den Einwand definitiv.
Und was die Arbeit angeht...dort sind alle benutzen Quellen gelistet.
In diesem Fall war auch der Fachmentor direkt an der Entwicklung
beteiligt.
Ich werde die Arbeit hier veröffentlichen, sobald ich die Freigabe dazu
habe, ok?
Sorry, aber damit ist diese Diskussion von meiner Seite her beendet,
denn sie macht keinen Sinn. Du kannst das OS gern nutzen oder auch nicht
und gern andere fachspezifische Fragen stellen, aber zu diesem Thema
wird von mir nichts mehr kommen, denn so lange ich die Arbeit nicht
veröffentlichen darf, kann ich es dir leider nicht schwarz auf weiß
widerlegen.
Übrigens, der nano OS scheduler ist älter als der von gos, genauer
gesagt von 2005/2006. nur das ich ihn nicht veröffentlicht habe, weil
ich ihn -wie gesagt- in einem Uhrenprojekt eingesetzt habe, dass ich
auch verkauft hab.
Von daher - nein ich habe gos nicht geschrieben, aber weder ist gos von
mir abgekupfert, noch umgekehrt.
Ich finds ehrlich gesagt ein wenig unverschämt, was du da sagst.
Manchmal macht der Ton die Musik.
gruß
tobi
Helli schrieb:> Frank M. schrieb im Beitrag #1868712:>> Aber zu behaupten, Du würdest GOS gar nicht kennen, ist dummdreist.
Während Du antwortetest, habe ich meinen Beitrag wieder gelöscht, weil
ich danach Deinen Beitrag über den AVR-Wizard las, der auch noch als
Möglichkeit in Frage käme.
Du warst schneller, das ist halt das Problem bei asynchronen Medien ;-)
Dann formuliere ich mal um:
@hacker-tobi:
Dass Du irgendwann irgendwo abgeschrieben hast, ist offensichtlich. Die
Makros und Funktionen sind nicht nur "ähnlich", sondern komplett
identisch, sogar die Spaces in den Makro-Argumenten bei einstelligen
Zahlen. Am Abschreiben ist auch nicht unbedingt etwas Verwerfliches zu
sehen. Aber dann gib bitte Deine Quellen auch an.
Du schriebst auch:
> Und wenn ich gos als Quelle benutzt hätte, würde ich es auch angeben.> Warum sollte ich es denn verheimlichen?
Okay, dann sollte es ja kein Problem sein, Deine Quelle zu nennen.
P.S.
Es könnte auch jemand von Dir abgeschrieben haben. Aber das halte ich
eher für unwahrscheinlich.
Mal ganz abgesehen davon...wenn ich von gos abgeschrieben hätte, ohne es
anzugeben, dann wär ich wohl kaum so dumm, das hier zu veröffentlichen
;)
Ich würde vorschlagen...wir lassen diese Diskussion jetzt einfach.
Denn sie führt zu gar nichts, oder? Ich werds jetzt jedenfalls nicht
weiter kommentieren. Aber ich werde den Quelltext ändern, wenn du das
willst.
Tobias W. schrieb:> das mit dem reti kann ich so nicht bestätigen. nimmt man das reti raus,> wird nicht mehr aus dem Interrupt zurückgesprungen.
Das kann ich mir nicht vorstellen bzw., das ist so richtig, denn Du bist
ja noch im Interrupt drinnen. Der Interrupt ist erst aus, wenn
Signal(...) fertig ist. Wie prüfst Du das eigentlich nach?
Würde mich wundern, wenn ISR(...) nicht funktioniert. Das hat sicherlich
nichts mit den Compiler zu tun. Dieser wirft bei mir übrigens einige
Warnings raus. A
z.B: system/message.c: In function 'queue_read_byte':
system/message.c:156: warning: 'return' with no value, in function
returning non-void
@Frank: Da gebe ich dir in allen Punkten recht. Aber wie gesagt, ich
kann nichts angeben, was ich nicht kenne ;( Tut mir echt leid.
Ich sehe die Problematik ja auch absolut ein, aber was soll ich denn
noch sagen? Ich werde die Arbeit hier veröffentlichen, wenn ich die
Erlaubnis dazu bekomme, damit jeder das Gedankengut "hinter" nano os
nachvollziehen kann. Und wie gesagt, der nano os scheduler ist älter.
Nur wurde er vorher nie veröffentlicht.
Von daher kann weder ich von gos abgeschrieben haben (denn das wurde ja
erst 2007 veröffentlicht) noch gos von mir(da der scheduler ja gar nicht
veröffentlicht war). Und den AVR Wizard kenne ich, habe ihn aber nie
eingesetzt.
Es ist auch müßig, darüber zu diskutieren, denn das würde sich doch nur
im Kreis drehen.
Vorschlag: Gegenseitiges aufeinander rumhacken bringt doch nichts, wie
wäre es, wenn wir gemeinsam an nano os weiterarbeiten?
gruß
tobi
hacker-tobi schrieb:> Ich würde vorschlagen...wir lassen diese Diskussion jetzt einfach.> Denn sie führt zu gar nichts, oder? Ich werds jetzt jedenfalls nicht> weiter kommentieren. Aber ich werde den Quelltext ändern, wenn du das> willst.
Ich sag jetzt auch nichts mehr dazu ... Sogar die anderen Funktionen in
dem selben File sind identisch ... Dann würde ich dem Günter Greschenz
mal sagen, dass er nicht deinen Code klauen soll, den du 2005
geschrieben aber nie veröffentlich hast ... der ist offenbar so dumm,
ihn aus deiner Uhr zu stehlen, ihn in seinem AVR-Wizard einzubauen und
öffentlich zur Verfügung zu stellen ... Unten ein Link, und wenn man
dann auf task.c klickt, dann erscheint dein Code ... Ich würd mal einen
Virenscanner installieren, vlt hast du ja einen Trojaner ...
http://greschenz.dyndns.org/avrwiz/
Mehr Kommentare gibt's von mir aus nicht mehr dazu ... Du wirst schon
wissen, was du macht ...
@mario:
kann sein, ok, nicht ganz korrekt ausgedrückt. Er springt natürlich aus
dem Interrupt zurück, aber das I-Bit wird nicht mehr gesetzt, ergo
bleiben Interrupts inaktiv.
Warum, das muss ich in Ruhe ergründen.
Wegen ISR: Ich kanns mir zur Zeit auch nicht erklären. Aber wenn ich ISR
verwende, dann überschreiben sich die Tasks gegenseitig die Register.
Ich denke, da liegt noch was im argen. Aber auch mit dem gos-Scheduler
tritt dieses Phänomen auf. Dass muss ich mir in Ruhe ansehen.
Wegen der Warnung: Okay, da muss ich mal dran, ist ja keine große Sache.
Interessanterweise hat er das bei mir nicht bemängelt. Hast du sonst
noch irgendwelche warnungen?
hacker-tobi schrieb:> @Frank: Da gebe ich dir in allen Punkten recht. Aber wie gesagt, ich> kann nichts angeben, was ich nicht kenne
Ok, dann gib einfach das an, was Du kennst. Du eierst hier rum wie um
den heißen Brei. Wo ist Dein Problem?
Schauen wir uns mal die Funktion task_create() aus tasks.c an:
GOS:
Die ca. 20 Zeilen, die ich hier mit "..." gekennzeichnet habe, sind
absolut identisch - abgesehen von der kaputten Einrückung Deinerseits.
(Daran könntest Du noch arbeiten, es macht keinen Spaß, Code zu lesen,
der global an den linken Rand geklatscht ist).
Aber was ich daraus erkenne, ist, wer von wem abgeschrieben hat, denn
Deine Version ist eleganter, also erst das SREG zu sichern und nachher
wieder herzustellen. GOS dagegen macht es plump mit cli() und sei().
Ergo: Eine eindeutige Code-Verbesserung, umgekehrt wäre es blöd vom
Programmierer, den Code wieder zu verschlimmbessern.
Also: Wie heisst Deine Quelle?
Frank M. schrieb:> Aber was ich daraus erkenne, ist, wer von wem abgeschrieben hat, denn> Deine Version ist eleganter, also erst das SREG zu sichern und nachher> wieder herzustellen. GOS dagegen macht es plump mit cli() und sei().
Mir gefällt die GOSs Funktion besser. Ich wüsste keinen Grund, wieso man
das SREG sichern sollte. Dass kein sei() später folgt, gefällt mir hier
auch nicht, denn man muss wissen, dass taskCreate(...) die Interrupts
ausschaltet, aber nicht wieder ein. D.h., nach der Funktion läuft das
System nicht mehr so weiter wie davor (taskCreate(...) sollte ja auch
zur Laufzeit eine Task einfügen können). Das taskCreate atomic ist, ist
völlig OK.
Helli schrieb:> Ich sag jetzt auch nichts mehr dazu ...
Das halte ich für die falsche Einstellung.
> Sogar die anderen Funktionen in> dem selben File sind identisch ... Dann würde ich dem Günter Greschenz> mal sagen, dass er nicht deinen Code klauen soll, den du 2005> geschrieben aber nie veröffentlich hast ...
Es gibt noch eine andere Möglichkeit, nämlich
hacker-tobi == Günter Greschenz
D.h. er würde in diesem Falle versuchen, seinter Uni seine eigene 3
Jahre alte Software jetzt neu als Diplomarbeit zu verkaufen. Aber das
ist reine Spekulation. Ausserdem müsste ich hacker-tobi noch schlechtes
Software-Management vorwerfen, denn der avrwiz generiert auch heute noch
die uralte cli()...sei()-Variante. ;-)
Als letztes: Die Software von Günter Greschenz ist zwar öffentlich
runterladbar, aber nicht frei. Sie ist im GOS ("Günters OS", bezeichnend
ist auch die Ähnlichkeit in der Namenswahl des Projekts, jetzt ist es
"Nano OS") ausdrücklich mit
"(c) 2007 by günter greschenz (g AT greschenz.de)" gekennzeichnet.
mar IO schrieb:> Mir gefällt die GOSs Funktion besser. Ich wüsste keinen Grund, wieso man> das SREG sichern sollte. Dass kein sei() später folgt, gefällt mir hier> auch nicht, denn man muss wissen, dass taskCreate(...) die Interrupts> ausschaltet, aber nicht wieder ein.
Die Interrupts werden mit Herstellen des SREG wieder eingeschaltet.
Frank M. schrieb:> Die Interrupts werden mit Herstellen des SREG wieder eingeschaltet.
Stimmt, irgendwie habe ich an das gar nicht mehr gedacht und somit
völlig den Schmarrn geschrieben. Dann gefällt mir die GOS Funktion
besser, weil ich die besser lesen kann.
@Frank: Sorry, wie bereits geschrieben...diese Diskussion ist sinnlos.
Es gab für den Scheduler-Code keine Quelle. Natürlich habe ich Quellen
benutzt, aber die haben sich eher auf die Beschreibung der
Funktionaliltät bezogen und sind auch in der Arbeit erwähnt.
Dies war das Buch von Manfred Schwabl - Programmierung von
Mikrocontrollern und ein Buch zu Betriebssystemgrundlagen. Zusätzlich
einige Wikipedia-Artikel und weitere Internet-Recherchen.
Aus dem Buch von Manfre Schwabl stammen auch die Anregungen für den
Scheduler. Allerdings hat er in Assembler codiert, die C-Umsetzung ist
von mir.
Warum also sollte ich alle diese Quellen angeben, und eine (gos) nicht?
Warum sollte ich einmal Code verbessern, und dann -im Gegensatz zu gos-
statt mit ISR mit Signal arbeiten, und auch andere Kleinigkeiten, wie
z.B. die Initialisierung von current anders machen?
Und warum unterscheidet sich z.B. die komplette Tasksignalisierung
(task_signal, task_wait, task_wait_for_laps)? gos kennt z.B. auch kein
task_anhilate oder ähnliches.
Wenn ich das alles abgeschrieben hätte würde es doch identisch aussehen.
Ich gebe es auch zu, z.B. das konstrukt mit Signal() habe ich gemacht,
weil dies mein erster Scheduler ist, und ich schlicht nicht wusste, das
es auch anders (und besser) geht. Und push/pop sind nunmal
Standardfunktionen. Da können auch andere drauf kommen, die so zu
benennen. Und zum rest...der Prozessor muss nunmal zum Taskwechsel immer
das selbe tun, egal ob der Scheduler nun gos, nanoos oder sonstwie
heißt. Die Schritte sind nunmal immer...interrupts abschalten, register
sreg und SP sichern, neuen Task anwählen, register sreg sp
zurückschreiben und dann interrupts wieder aktivieren.
Und da suich die Verwaltungsinformationen ähneln, sind nunmal auch die
dafür notwendigen Verwaltungsstrukturen zwangsläufig ähnlich.
Und zum Thema rumeiern...das kann ich euch genauso vorwerfen. Ihr
versucht da krampfhaft, mir eine Quelle aus den Rippen zu leiern, die
ich nicht kenne und auch nicht benutzt habe. Ich habe keine Ahnung,
warum sich die Codes ähnlich sind, aber es interessiert mich auch nicht.
Ich werfe ja auch dem gos-schreiber kein Abschreiben vor (und glaube
auch nicht daran), obwohl mein Scheduler eher entstanden ist.
Es wurde auch schon einmal weiter oben in diesem Thread nach den
Ähnlichkeiten gefragt, und diese Frage habe ich auch beantwortet. Aber
dort wurde nur einmal nachgefagt.
Du und heli, ihr probiert es andauernd wieder, und -sorry- aber mehr als
das was ich weiß, kann ich dazu nicht sagen.
Ich werde aber meinen Code umschreiben, damit die Ähnlichkeiten weg
sind, obwohl ichs für unsinnig halte, um damit dieses Thema zu beenden.
So nun habe ich alle Quellen offengelegt, und auch sonst alles. Die
Arbeit selbst folgt, wenn ich sie veröffentlichen darf.
So, ich bin mittlerweile ziemlich entnervt. Um meine nerven zu schonen,
werden weitere Anfragen zu diesem Thema nicht mehr kommentiert.
Andere Fragen Anregungen Lob / Kritik werden natürlich weiter
bearbeitet und beantwortet.
gruß
tobi
Jetzt wirds ja völlig abstrus...klar ich bin Günther Greschenz...all
right ;) Komisch, auf meiner Diplomarbeit steht ein anderer
Name...Tobias W. Auf meinem Perso auch ;). Daher auch der nick
(hacker-TOBI)
Leute , lasst es einfach.
@Mario: Es ist so, wie frank sagt. Mit dem SREG wird auch das I-Bit
wieder gesetzt. Daher kein sei(). Okay ich stimme dir zu, das sieht man
nur, wenn man es weiß. Von daher ist gos besser zu lesen ;)
Aber ich denke, ein zuätzliches sei() der lesbarkeit wegen ist hier
sinnfrei() ;)
Hast du noch ne Idee, warum das mit ISR() nicht funktioniert hat?
Übrigens, GOS ist eigentlich auch schon älter, aber anscheinend ging da
der Code verloren...
---HISTORY--------------------------------------------------------------
--------
*) V0.000 2001 (?)
first working version for 68000 (PalmPilot)
(but i lost my old code ...)
*) ...
Was mich bei beiden Codes wundert, wieso SREG nicht auf den Stack
sichern und den gesicherten Stackpointer auf das erste gesicherte
Register (r31) zeigen zu lassen???
hacker-tobi schrieb:> Wenn ich das alles abgeschrieben hätte würde es doch identisch aussehen.
Einzelne Teile (insb. der Code in tasks.c) sind identisch. Das kann
man nicht mit "ähnlich" abtun. Die Interfaces sind identisch, die
Variablen sind identisch, der Code ist identisch.
Ich habe ja nicht gesagt, dass Du alles abgeschrieben hast. Aber große
Teile davon kommen aus einer anderen Quelle.
> Und zum Thema rumeiern...das kann ich euch genauso vorwerfen. Ihr> versucht da krampfhaft, mir eine Quelle aus den Rippen zu leiern, die> ich nicht kenne und auch nicht benutzt habe. Ich habe keine Ahnung,> warum sich die Codes ähnlich sind, aber es interessiert mich auch nicht.
Nochmal zum mitmeisseln: Die sind nicht "ähnlich", die sind in großen
Teilen identisch.
Es gibt also 2 deutschsprachige Programmierer auf der Welt, die - ohne
sich zu kennen - identischen Code schreiben. Wahnsinn, das hat die Welt
noch nicht gesehen.
> Ich werde aber meinen Code umschreiben, damit die Ähnlichkeiten weg> sind, obwohl ichs für unsinnig halte, um damit dieses Thema zu beenden.
Das heisst, Du machst aus dem identischen Code einen ähnlichen Code.
Wegbekommen wirst Du die "Ähnlichkeiten" niemals, ausser Du schreibst
den identischen Code von Scratch auf neu.
> So nun habe ich alle Quellen offengelegt, [...]
Ich habe keine Quelle gesehen?!? Oder habe ich Tomaten auf den Augen?
> So, ich bin mittlerweile ziemlich entnervt.
Das hast Du Dir selbst eingebrockt.
> Um meine nerven zu schonen,> werden weitere Anfragen zu diesem Thema nicht mehr kommentiert.
Als Gründer von einigen in Deutschland ziemlich bekannten
OpenSource-Projekten ist Dein Verhalten, was Du hier an den Tag legst,
für mich wie ein Schlag ins Gesicht. Daher ist dieses Thema
(Copyright/Kupfern/Diplomarbeit) für mich noch lange nicht beendet.
Hi Mario,
stimmt. Aber so fit bin ich (noch) nicht, das ich den code vom 68000
umschreiben könnt, selbst wenn er noch vorhanden geweswen wäre ;) Der
Scheduler für den avr hat mich genug mühe gekostet.
Thema Sichern: Das wär ne Möglichkeit. Aber so richtig sehe ich den
Vorteil jetzt nicht. Das SREG könnte ich auf den Stack schieben, aber so
oder so geht mir dafür 1 byte im Speicher drauf.
Hast du da einen bestimmten Grund?
Stackpointer: Das lässt sich machen.
Nachtrag als gutgemeinter Tipp:
Besorge Dir von Günther Greschenz schnellstmöglich die Erlaubnis, seinen
Code verwenden zu dürfen, d.h. er soll Dir eine Lizenz ausstellen.
Verletzungen von Copyrights sind kein Kavaliersdelikt. Wenn das in der
Uni rumgeht, kannst Du Deine Diplomarbeit in die Tonne werfen.
Frank M. schrieb:>> Um meine nerven zu schonen,>> werden weitere Anfragen zu diesem Thema nicht mehr kommentiert.>> Als Gründer von einigen in Deutschland ziemlich bekannten> OpenSource-Projekten ist Dein Verhalten, was Du hier an den Tag legst,> für mich wie ein Schlag ins Gesicht. Daher ist dieses Thema> (Copyright/Kupfern/Diplomarbeit) für mich noch lange nicht beendet.
Wie wär's wenn man Günther auf diesen Thread aufmerksam macht und ihn
einfach frägt, ob er den Scheduler geschrieben hat oder nicht?
Aber es stimmt - Die Source-Codes sind identisch und unabhängig
identischen Source-Code zu produzieren ist unmöglich.
Grüße,
Mampf
hacker-tobi schrieb:> Thema Sichern: Das wär ne Möglichkeit. Aber so richtig sehe ich den> Vorteil jetzt nicht. Das SREG könnte ich auf den Stack schieben, aber so> oder so geht mir dafür 1 byte im Speicher drauf.
Wie man an diesen Ausführungen sieht, hast Du Deinen angeblich "eigenen"
Scheduler nicht im Griff, d.h. Du verstehst nicht, was Du da tust. Wenn
Du SREG auf eine lokale Variable einer Funktion schreibst, wo liegt
diese Kopie dann? Wenn Du die Antwort wüsstest, dann würdest Du auch
einsehen, dass Deine obige Antwort sinnfrei ist.
Gruß,
Frank
Ich habe mich auf den kompletten code bezogen, daher von Ähnlichkeiten
gesprochen.
Ansonsten gebe ich dir recht, einzelne Zeilen sind identisch. Das API
hingegen nur in Teilen. Ich verweise da z.B. auf task_wait und
task_signal, welche andere Parameter nutzen, usw.
Und ja, ich werde den code neuschreiben. Dann ist es eindeutig, denn wie
gesagt - ich kann die Einwände völlig verstehen, und nachvollziehen.
Auch die Schlußfolgerungen sind verständlich, aber ich kann nur das
wiedergeben, was ich auch getan habe. Von daher verstehe du bitte auch,
das ich mich gegen derartige Anschuldigungen zur Wehr setze, denn aus
meiner Sicht sind sie nachvollziehbar, aber unberechtigt.
Und las bitte Äußerungen wie "das ist für mich noch lange nicht
erledigt" weg - was sollen denn solche Drohungen? Sorry, aber damit
erreichst du bei mir nichts.
Warum können wir nicht einfach konstruktiv an einer Lösung des Problems
arbeiten?
Was soll ich denn nach deiner Ansicht tun, um das Problem aus der Welt
zu räumen
(die Frage meine ich ernst, denn ich will das Thema friedlich aus der
Welt schaffen)?
gruß
tobi
Mensch Tobi,
sehe es bitte mal von der anderen Seite, einfach als gut gemeinten
Hinweis, dass es hier Probleme mit Urheberrechten geben könnte, vor
denen man dich (noch rechtzeitig) warnt und die du jetzt klären
solltest! Es muss nicht hier sein, aber in deiner Arbeit solltetst du es
tun!
Das hier jemand von jemanden anders "abgeschrieben" hat, ist wirklich zu
offensichtlich (Frank hat ein paar Dinge genannt..., für mich ist auch
die spezielle Formatierung der PUSH/POP-Anweisungen zu prägnant). Der
Zufall wäre zu groß, wenn zwei Leute genau(!) so formatieren!
Klar, wie du auch schon geschrieben hast, gleiches Thema = gleiche
Vorgehensweise, aber nicht von unterschiedlichen Leuten vollkommen
gleiche Variablennamen, Programmstrukturen, Codeformatierungen..., dass
geht einfach nicht! Da hilft es auch nicht, wenn du jetzt einfach den
Code umschreiben willst, dafür ist dieser Thread zu öffentlich!
Es ist doch legitim, wenn du fremde Codefragmente als Grundlage nimmst
und für deine Belange anpasst und erweiterst. Genau das ist doch die
geistige Arbeit die du da reingesteckt hast, an der du gemessen wirst
und die will/wird dir keiner streitig machen. Aber diese Grundlage musst
du als Quelle angeben, selbst wenn diese unter GPL steht.
Sei bitte so ehrlich, sonst kommst du spätestens bei der Einreichung
deiner Arbeit in Teufels Küche.
Wenn du nicht abgeschrieben hast, solltest du wirklich überdenken, woher
in fremden Code deine(!) ursprünglichen Fragmente herkommen können. Hast
du vielleicht doch irgendwo deine Programme und sei es auch nur ganz
kurz, öffentlich gemacht oder hast du einzelnen Leuten den Quelltext
gegeben und kannst du das irgendwie nachweisen (nicht uns, sondern immer
im Hinblick auf deine Arbeit, mit der du einen Titel erreichen willst)?
Überdenke das bitte nochmal!
hacker-tobi schrieb:> Was soll ich denn nach deiner Ansicht tun, um das Problem aus der Welt> zu räumen
Ganz einfach: Besorge Dir von Günter eine Lizenz. Dann löst sich das
Problem in Luft auf.
hacker-tobi schrieb:> SREG wird in eine globale Struktur vom Typ task gesichert, die mit> deklaration volatile versehen ist. und wo liegt die? im RAM oder?
Die liegt auf dem Stack. Du brauchst sie also nicht auf den Stack zu
schieben, da ist der Wert der lokalen Variablen bereits.
RAM: peinlich peinlich...
@hugo: Das ist ja das Thema...ich hab wirklich nichts abgeschrieben ;(
Die Argumentation ist durchweg verständlich, aber was soll ich denn tun?
Ich will doch nichts zugeben, was ich definitiv nicht getan hab.
Und genauso wie gemeinsamkeiten gibt es eben auch eklatante
Unterschiede. Wir diskutieren hier über vielleicht 40 Zeilen Code in
mehren 100 Zeilen Code insgesamt.
Ob der Code mal rausgegangen ist, das ist eine gute Frage. Der Scheduler
ist 5 in den Grundzügen Jahre alt, ausschließen will ich es nicht, aber
ich möchte hier auch niemand irgendwas unterstellen.
Die Arbeit ist erledigt und abgehakt, darum mach ich mir keine Gedanken.
Aber ich werd den Code umschreiben. Ich denke, damit ist allen geholfen,
und das Problem ist aus der Welt.
hugo schrieb:> Es ist doch legitim, wenn du fremde Codefragmente als Grundlage nimmst> und für deine Belange anpasst und erweiterst. Genau das ist doch die> geistige Arbeit die du da reingesteckt hast, an der du gemessen wirst> und die will/wird dir keiner streitig machen. Aber diese Grundlage musst> du als Quelle angeben, selbst wenn diese unter GPL steht.
Günters Arbeit ist nicht unter der GPL gekennzeichnet. Daher reicht eine
Quellenangabe nicht aus.
> Sei bitte so ehrlich, sonst kommst du spätestens bei der Einreichung> deiner Arbeit in Teufels Küche.
Eben.
> Überdenke das bitte nochmal!
Ja, dringendst.
Waum sollte eine globale Variable, welche mit VOLATILE versehen ist, auf
dem Stack liegen?
Siehe:
http://www.imb-jena.de/~gmueller/kurse/c_c++/c_volat.html
"Das Schlüsselwort volatile teilt dem Compiler mit, daß die mit name
bezeichnete Variable mit dem Datentyp typ durch Ereignisse außerhalb der
Kontrolle des Programms verändert werden kann.
Der Wert der Variablen muß deshalb vor jedem Zugriff neu aus dem
Hauptspeicher eingelesen werden, d.h. er darf nicht in einem Register
des Prozessors zwischengespeichert werden.
Der Compiler arbeitet bei mit volatile deklarierten Variablen ohne jede
Optimierung, d.h. läßt die entsprechenden Werte bei jedem Zugriff neu
aus dem Hauptspeicher laden und sorgt bei Veränderungen dafür, daß die
neuen Werte ohne Verzögerung dort sofort abgelegt werden."
ergo liegt die Variable auf einer fixen Adresse im Hauptspeicher.
Die Speichersegmentierung beim Atmel sieht dafür den bereich .data vor,
der für Variablen reserviert ist.
Was natürlich nicht ausschließt, das lokale Variablen auf dem Stack
liegen können, aber diese Variable ist eben nicht lokal.
Frank M. schrieb:> Die liegt auf dem Stack. Du brauchst sie also nicht auf den Stack zu> schieben, da ist der Wert der lokalen Variablen bereits.
Ich sehe gerade, dass es eine globale Variable sregsys ist. Das hatte
ich übersehen, da ich davon ausgegangen bin, dass sregsys natürlich
lokal ist. Besser wäre in jedem Falle eine lokale Variable, damit die
Funktionen, wo das SREG gesichert werden, auch reentrant werden. Wenn
das nicht notwendig ist, kannst Du das natürlich auch lassen.
Frank M. schrieb:> Günters Arbeit ist nicht unter der GPL gekennzeichnet. Daher reicht eine> Quellenangabe nicht aus.>
ist mir bewußt und hatte ich nur als weiteres Beispiel gemeint, dass
auch GPL-Software (bzw. OpenSource im allgemeinen) nicht zur sorglosen
"Bedienmentalität" einladen sollte, ohne die Quellen wasserdicht
anzugeben... hatte mich etwas missverständlich ausgedrückt.
Sorry, was das andere Thema angeht, da werde ich nur den Code
umschreiben. Ansonsten gibts da nicht viel zu überdenken, denn da kann
ich ein reines Gewissen haben, tut mir leid. Wenn jemand anderer Meinung
ist - ok.
Aber das ändert nichts daran, dass der Code von mir stammt. sorry.
Ich gebe aber ehrlich zu, das ich vieles zusammenschneidern musste, und
das ich froh bin, dass der Scheduler überhaupt läuft. Manches habe ich
auch per trial&error ermittelt.
gruß
tobi
Zum Abschluß: Wie kommen wir jetzt mit der leidigen Code-Thematik
übberein? Ich werde den Code umschreiben, aber was muss ich dabei
beachten?
Frank, kannst du mir da helfen?
hacker-tobi schrieb:> Sorry, was das andere Thema angeht, da werde ich nur den Code> umschreiben. Ansonsten gibts da nicht viel zu überdenken, denn da kann> ich ein reines Gewissen haben, tut mir leid. Wenn jemand anderer Meinung> ist - ok.> Aber das ändert nichts daran, dass der Code von mir stammt. sorry.>
... willst du es nicht verstehen? Wenn du nicht abgeschrieben hast (und
du bestehst ja darauf, was dein Recht ist), dann hat der andere
abgeschrieben!
Und das ist der Knackpunkt, du musst dann deine(!) Rechte geltend
machen, sonst kann es ganz leicht passieren das deine Arbeit hinfällig
wird und sich fremde Leute mit deinen Federn schmücken (und u.U.
irgendwann mal Geld damit verdienen). Im schlimmsten Fall meldet sich
der Andere und macht seine Urheberrechteansprüche geltend...
Ich würde es genau aus diesem Grund nicht so leichtfertig abtun, wie
leben (leider) nicht im Software-Sozialismus. Geistige Arbeit wird nicht
als gesellschaftliches Gemeingut angesehen, sondern wird knallhart als
Kapital verwendet.
hacker-tobi schrieb:> Zum Abschluß: Wie kommen wir jetzt mit der leidigen Code-Thematik> übberein? Ich werde den Code umschreiben, aber was muss ich dabei> beachten?
Umschreiben bringt gar nichts. Geistiges Eigentum bleibt auch bei
künstlichem Verfremden des Codes erhalten. Sonst könnte ja jeder einfach
ein paar Variablennamen/Funktionsnamen umbenennen und fertig. Man kann
auch eine Kaffeemaschine nicht als eigene Erfindung ausgeben, nur weil
man sie umgefärbt hat.
Die ganze Datenstruktur (und damit auch die benötigten Funktionen)
bekommst Du nur weg durch komplettes Neuprogrammieren - ohne Hinsehen
auf den alten Code.
Ich selbst habe schon mehrfach eigenen Code komplett neugeschrieben,
weil er durch immerwährende Erweiterungen historisch wuchs und
irgendwann unhandlich wurde. Das Bezeichnende daran ist: Was man selbst
einmal entworfen hat, codiert man beim zweiten Mal in einem Bruchteil
der Zeit: einfach, weil man die damaligen Gedankengänge im Kopf
eingebrannt hat und einen Fehler, nach dem man damals stundenlang
suchte, bestimmt kein zweites Mal macht.
Wenn es also Dein eigener Code ist, dürfte es für Dich ein leichtes
sein, die entsprechenden Codeteile neu zu programmieren, denn Du hast
Dein Programm ja im Kopf.
> Frank, kannst du mir da helfen?
Ich wüsste nicht, wie.
@hugo:Ich versteh das Grundproblem. Du hast recht, von der Seite hab ich
es noch nicht betrachtet. Ok, was den jetzigen Stand angeht, lasse ich
es auf sich beruhen.
Den neuen Code würde ich gerne als open source nach GNU GPL o.ä.
veröffentlichen. Was gibt es dabei zu beachten?
Ich gestehe ehrlich, das ich mich bis jetzt nicht besonders um Lizenzen
und ähnliches bemüht habe. Mir war es bis jetzt egal, wenn jemand den
Code verwandt hat, auch kommerziell. Ich schreibe das in meiner Freizeit
und weil ich Spass daran habe. Bei Lösungen, die ich selbst verkaufe,
habe ich den code nie veröffentlicht.
Das mag naiv klingen, aber so war bis jetzt mein Denken. Durch diese
Diskussion wurde ich eines besseren belehrt. Aus Fehlern lernt man eben.
@Frank: Ich wills nicht verfremden, ich werds neu schreiben. Und dabei
gleich einige der Anregungen von hier mit aufnehmen. Ich weiß aber
momentan noch nicht, wann ich dazu komme. Ich poste hier, wenn ichs
fertig hab.
Ich bezog das weiterhelfen darauf, wie ich den Code so gestalte, dass es
keine Probleme bezüglich der Verwechslung mit gos mehr gibt. Und da hast
du mir mit der Aussage schon geholfen. Danke.
Ich habe Günter Greschenz informiert, mit der bitte, sich mit mir in
Verbindung zu setzen.
Hallo Hr. Greschenz,
folgendes Problem:
Ich habe -wie sie- ein OS für AVR Mikrocontroller geschrieben, siehe
auch:
Beitrag "Re: NeuesOS für AVR Mikrocontroller"
Leider sind sich unsere Scheduler und die Task-Verwaltung extrem
ähnlich, was den Verdacht ausgelöst hat, dass hier einer von uns
abgeschrieben hat.
Um es vorweg zu nehmen: Ich denke nicht, dass sie bei mir kopiert haben,
aber ich habe bei ihnen auch nicht abgekupfert.
Meine Frage: Wie können wir das Problem lösen?
Ich biete ihnen an, das ich meinen Code neuschreibe, um die
Ähnlichkeiten auszuschließen, falls sie das möchten. Dann wäre das Thema
definitiv aus der Welt.
Bitte melden sie sich per mail an xxxxx bei mir. Gern auch telefonisch
unter xxxxxxxxxxx
Mit freundlichen Grüßen,
Tobias W. (hacker-tobi).
hacker-tobi schrieb:> Den neuen Code würde ich gerne als open source nach GNU GPL o.ä.> veröffentlichen. Was gibt es dabei zu beachten?
Ich mache es so:
1. Ich schreibe in den Kopf einer jeden Source-Datei folgenden
Kommentar:
hacker-tobi schrieb:> @hugo:Ich versteh das Grundproblem. Du hast recht, von der Seite hab ich> es noch nicht betrachtet. Ok, was den jetzigen Stand angeht, lasse ich> es auf sich beruhen.>
naja, deine Entscheidung, ich würde es nicht so leichtfertig betrachten.
Immerhin hat, wenn deine Aussagen wirklich zutreffen, jemand deinen
Quellcode kopiert und nichtmal unter eine Lizenz gestellt, die ein
ungehindertes Weiterverwenden durch anderer (und damit auch dir selbst)
ermöglicht.
> Den neuen Code würde ich gerne als open source nach GNU GPL o.ä.> veröffentlichen. Was gibt es dabei zu beachten?>
du deklariert dies einfach so. Es gibt gewisse Regeln, wie das gemnacht
wird. Wichtig ist, dass du jede Quelltextdatei mit einem entsprechenden
Hinweis versiehst und den vollständigen GPL-Text als Datei mitlieferst
bzw. verweist wo er zu finden ist. Wie man es genau macht, findet man
recht leicht im Internet auf den entsprechenden Seiten. (Viele
OS-Editoren nehmen einem auch die Arbeit ab und haben entsprechedende
Funktionen, mit dem man soetwas per Tastendruck erledigen lassen kann.)
> Ich gestehe ehrlich, das ich mich bis jetzt nicht besonders um Lizenzen> und ähnliches bemüht habe. Mir war es bis jetzt egal, wenn jemand den> Code verwandt hat, auch kommerziell. Ich schreibe das in meiner Freizeit> und weil ich Spass daran habe.>
sagen wir mal so, Freizeit ist ok, solange man die verbrachte Zeit auch
wirklich als Vergnügen ansieht. Ich mache es teilweise auch so und gebe
z.B. hier einfach Quelltexte (manchmal gedankenlos)) weiter und freue
mich, wenn es andere Leute gebrauchen können --> reines Hobby. Sehe den
Aufschrei, den es hier jetzt in deinem Fall gab, bitte "dir
wohlgesonnen". Immerhin willst du deinen Quelltext für eine Arbeit
verwenden, die schon einen offizielleren Charakter hat (und die
letztendlich auch Geld bedeutet)... und da hört der Spaß auf, die Welt
draussen ist erst mal grundsätzlich böse!
Tobias W. schrieb:> Ich habe Günter Greschenz informiert, mit der bitte, sich mit mir in> Verbindung zu setzen.
Alle Achtung, das hätte ich nicht von Dir gedacht!
> Ich biete ihnen an, das ich meinen Code neuschreibe, um die> Ähnlichkeiten auszuschließen, falls sie das möchten. Dann wäre das Thema> definitiv aus der Welt.
Alternativen wären:
1. Ausstellung einer Source-Lizenz an Dich
Oder
2. Anerkennung des Sources als Dein rechtliches Eigentum
Das wäre dann mit weniger Arbeit verbunden.
Gut, dann ist auch für mich diese Sache erstmal (vorerst) vom Tisch.
Frank M. schrieb:> 2. Anerkennung des Sources als Dein rechtliches Eigentum>
genau das würde ich auch fordern, wenn die Tatsachen wirklich so liegen!
(immerhin schmückt sich hier jemand mit fremden Federn...)
Grüße Uwe Berger
Ok, danke für die Hinweise.
Ich werde mich mit Günther absprechen, und dann sehen, wie wir hier
weiter vorgehen. Bis dahin lass ich erstmal alles so wie es ist. Und
ggf.schreibe ich den Scheduler und teile der Taskverwaltung eben neu.
Das wird schon...
Das was mich hier anfänglich sehr gestört hatte, war der "Ton", in dem
manche Leute hier auf mich losgegangen sind. Darum hatte ich so heftig
reagiert. Ich bin aber genauso an einer Lösung interessiert, daher auch
die Kontaktaufnahme mit Günther.
Also, wieder zurück zum Ursprung ;)
@Roman und alle anderen: Eure Änderungen sind nicht vergessen.
@Mar IO: Wegen dem ISR: Kompilieren tuts bei mir auch, aber es läuft
nicht wirklich. Es werden eben immer wieder Register überschrieben. Hier
kann ich unterstüttzung bei der Fehlersuche gut brauchen....
Tobias W. schrieb:> Das was mich hier anfänglich sehr gestört hatte, war der "Ton", in dem> manche Leute hier auf mich losgegangen sind.
Daran muss man sich einfach gewöhnen. Wenn man etwas öffentlich macht,
dann steht man auch in der Öffentlichkeit, d.h. man muss sich ihr
stellen. Ich habe das in den letzten 9 Jahren freier
Software-Entwicklung oft genug durchgemacht.
Mit der Zeit bekommt man zwar ein dickes Fell, aber eines lernt man
gewiss: Die User ernstzunehmen. Wenn da jemand ein gravierendes Problem
sieht, dann sollte man das auch ernstnehmen.
Es hat mich ungemein genervt, dass Du diese Kritikpunkte mehrfach
einfach abgetan hast mit den Worten: "Reden wir nicht mehr drüber, für
mich ist das Thema damit abgehakt". Das ist genau der falsche Weg. Man
kann ein Problem nicht einfach dadurch lösen, dass man es ignoriert.
Besser ist es, sich den Usern zu stellen. Dann wirst Du glücklich mit
ihnen - und sie mit Dir auch.
Du musst zugeben: Die Code-Übereinstimmung ist frappierend. Da Günters
Veröffentlichung wesentlich älter ist als Deine, kannst Du es uns auch
nicht übelnehmen, wenn man da zunächst in eine ganz bestimmte Richtung
denkt. Von daher ist das "Auf-Dich-Losgehen" durchaus nachvollziehbar.
;-)
@Frank: Klar, nachvollziehbar ist es.
Du hast recht, ich war auch nicht unbedingt ein Vorbild.
Von daher entschuldige ich mich, falls sich jemand ungerecht behandelt
gefühlt hat, das war hier nicht meine Absicht.
Ich bitte einfach alle (inkl. mir selbst), doch mal ihren Ton zu
überdenken. Das macht ne Menge aus...
Trotz allem hoffe ich das das kleine OS anklang findet, und gern auch
für eigene Ideen eingesetzt werden kann. Mal sehn was aus dem Scheduler
wird.
Ich versuche momentan immer noch zu verstehen, warum es mit ISR() nicht
richtig klappt...warum werden da Register überschrieben? Oder hab ich
irgendwo nen Denkfehler?
Tobias W. schrieb:> Ich bitte einfach alle (inkl. mir selbst), doch mal ihren Ton zu> überdenken.
Dann bist Du zu zart besaitet. Der Ton hier ist den Umständen
entsprechend, da gibt es wesentlich heftigere Diskussionen (die ich
sogar auch noch als "normal" ansehen würde). Wir sind (normalerweise)
alles erwachsene Menschen, die nicht mehr im Kindergarten sind. Gewöhn
Dich schon mal daran. ;-)
> Trotz allem hoffe ich das das kleine OS anklang findet, und gern auch> für eigene Ideen eingesetzt werden kann. Mal sehn was aus dem Scheduler> wird.
Ich finde das Thema spannend, deshalb habe ich hier in den letzten Tagen
öfter mal reingeschnuppert, ohne aber den Code zu lesen, sondern erstmal
zu schauen, wie sich das hier entwickelt. Momentan habe ich selbst
eigentlich auch gar keinen Bedarf - aber wer weiß: kommt eine Idee, kann
man ja auf so etwas durchaus mal zurückgreifen.
> Ich versuche momentan immer noch zu verstehen, warum es mit ISR() nicht> richtig klappt...warum werden da Register überschrieben? Oder hab ich> irgendwo nen Denkfehler?
Ich schaue es mir mal am Wochenende in Ruhe an. Wenn ich was finde,
melde ich mich dazu.
Ich habe mir den Source mal kurz angeschaut.
Aus einer ISR darfst Du nicht selbst mit RETI springen, das macht Dein
Compiler selbst. Das war auf µC.net schon oft das Thema - und wie ich
jetzt hier auch sehe, hat Dich Gast "mar IO" auch schon darauf
angesprochen.
Du rufst aus der ISR die Funktion scheduler() auf und dort machst Du
einen RETI. Damit machst Du den Stack, den sich der Compiler beim
Übersetzen der ISR und der Funktion secheduler() selbst gebaut hat,
kaputt. Besser gesagt: Du baust den Stack, der bei jedem ISR-Aufruf
aufgebaut wird, nicht wieder korrekt ab.
Vielleicht schaust Du Dir den vom Compiler erzeugten ASM-Code für die
ISR und für scheduler() mal an und prüfst den auf saubere
Stackbehandlung.
Mein Tipp: Nimm das RETI raus, der Compiler macht das schon für Dich.
Wenn Du jedoch befürchtest, dass dann das Task-Switching nicht mehr
funktioniert, weil dadurch der Kontext-Wechsel nicht mehr sauber ist,
musst Du die ISR selbst mit dem Attribut "naked" versehen (ich hoffe,
das geht auch mit ISRs, habe ich noch nie gemacht) und den Code von
scheduler() direkt in die ISR reinkopieren, damit da ja nichts mehr mit
dem Stack passiert. Dann könntest Du das RETI am Ende der ISR machen -
aber nur dann und auch nur dort. Die Funktion scheduler() entfällt dann
komplett.
Ich glaube "mar IO" hat das Problem schon richtig erkannt - näheres kann
ich mir aber auch nur erlauben zu sagen, wenn ich das Ding mal durch den
Compiler gejagt und mir den Assembler-Teil näher angeschaut habe.
Hi Frank,
du hast recht, Mario hatte das auch schon erkannt, und ich hatte es
gestern auch schonmal so umgesetzt, aber das hat eben nicht wirklich
geklappt.
Aber stimmt, das könnte sein, das ich da gestern über das reti
gestolpert bin, und das es deswegen nicht funktioniert hat.
Werd ich am WE mal testen,
danke dir.
Frank M. schrieb:> Umschreiben bringt gar nichts. Geistiges Eigentum bleibt auch bei> künstlichem Verfremden des Codes erhalten.
Geistiges Eigentum bzw. Urheberrecht setzt eine gewisse Schöpfungshöhe
voraus. Dass die in der Formatierung von Code zum pushen und popen von
ein paar Registern oder der in der Benennung von Funktionen besteht will
ich mal bezweifeln.
Andreas Schwarz schrieb:> Geistiges Eigentum bzw. Urheberrecht setzt eine gewisse Schöpfungshöhe> voraus. Dass die beim pushen und popen von ein paar Registern gegeben> ist will ich mal bezweifeln.
Das ist natürlich korrekt ;-)
Beim zweiten Hinsehen sieht man aber, dass ganze Funktionen und
Datenstrukturen identisch sind - es sind nicht 5 Zeilen, es sind
garantiert über hundert, vielleicht sogar über 200 Zeilen Code
identisch. Da fallen die Pushs/Pops gar nicht mehr ins Gewicht.
Hallo ???
Kann mir jetzt einmal jemand sagen, um was es hier eigentlich geht ??
Das herumhacken und herumzicken geht langsam auf dem sack.
Geht es jetzt um technische weiter entwicklung oder ob jemand etwas
veroeffentlicht unter GNU und dabei wo moeglich einige Code fragmente
verwendet hat, die schon unter GNU stehen ?? hmm..
Wie es schon Tobi irgendwo geschrieben hat.. geht es um grundlegende
frage von dem Ton "C" oder das was man mit den Ton Musik macht ??
Mal ganz abgesehen davon, das alle taskswitching routinen so ziemlich
gleich aussehen !! zb. Die von Linus, ist verdammt aehnlich mit der von
BSD oder SVR4 !! weil sie alle so oder so das selbe tun muessen!!
Oder Wollt Ihre alle wirklich sagen, das Ihr in euren Codes alle quellen
angeben, von wo und von wem Ihr eure Codes habt ?? Stelle ich mein Code
in ein Oeffentliches Forum, so kann ich doch nicht wirklich auch noch
verlangen von den Usern, das sie mir ein email schicken und copyright
meldungen in den code reinschreiben und und und.. und Wollt ihr
tatsaechlich zurueck gehen bis zum Donald Knuth und dem TAOCP ?!!
Neben bei gesagt.. Wo im Gos, sind semaphoren, wo sind queue's, wo ist
memory mgr. !! Wo sind die Hinweise, das im avr basic interpreter auf
mein code verwendet wird und meine ideen :)
Hoert doch auf euch wie kleine kinder zu benehmen..
lg roman
Roman65536 schrieb:> Kann mir jetzt einmal jemand sagen, um was es hier eigentlich geht ??> Das herumhacken und herumzicken geht langsam auf dem sack.
Hättest Du erstmal ruhig bis zum Ende gelesen, hättest Du gemerkt, dass
alle Wogen bereits wieder geglättet sind.
> Geht es jetzt um technische weiter entwicklung oder ob jemand etwas> veroeffentlicht unter GNU und dabei wo moeglich einige Code fragmente> verwendet hat, die schon unter GNU stehen ?? hmm..
Es geht um Codeteile (hacker-tobi spricht selbst von 100 Zeilen), die
eben nicht unter GPL stehen. Da gab es schon im UNIX-Umfeld ziemlich
große Streitwerte, die vor Gericht landeten, weil es da gerade mal um 4
(?) Zeilen ging...
Außerdem: Es gibt Leute, die verdienen mit Ihrem Code ihr täglich Brot,
wie ich zum Beispiel - auch wenn ich ein Verfechter der GPL bin.
Programmieren ist harte Arbeit und das Klauen von Code ist kein
Kavaliersdelikt.
> Mal ganz abgesehen davon, das alle taskswitching routinen so ziemlich> gleich aussehen !! zb. Die von Linus, ist verdammt aehnlich mit der von> BSD oder SVR4 !! weil sie alle so oder so das selbe tun muessen!!
Ah, Du hast die Taskwitching-Routinen von SVR4 gesehen? In welchem
Umfeld, wenn ich fragen darf?
Natürlich ist es klar, dass gleiche Problemstellungen zu ähnlichem Code
führen. Hier geht es aber um absolut identischen Code.
> Hoert doch auf euch wie kleine kinder zu benehmen..
Die Verwendung der mehrfachen Satzzeichen, wie in "Hallo ???", wie Du
z.B. Deinen Beitrag hast beginnen lassen, macht auf mich einen
wesentlich unfreundlicheren Ton aus als alle heutigen Beiträge in diesem
Thread zusammen. Woran liegt das wohl?
Ich hab mir grad die ASM-Files gezogen, einmal nach meiner Methode und
einmal mit ISR und Attribut (signal, naked).
Anbei beide Files.
Die differenz ist gut erkennbar, und besteht nur im proloque/epiloque.
Baut man das ganze in c nach, und verwendet es als ISR, funktioniert es.
Die Datei "...with..." ist die funktionsfähige Version, die andere eben
die defekte.
Baue ich das ganze in C nach, funktioniert es ebenfalls (ist ja klar):
void TIMER_VECTOR() _attribute_ ( ( signal, naked ) );
ISR(TIMER_VECTOR)
{
asm("push __zero_reg__");
asm("push __tmp_reg__");
asm("in _tmp_reg_,__SREG__");
asm("push __tmp_reg__");
asm("clr __zero_reg__");
asm("push r18");
asm("push r19");
asm("push r20");
asm("push r21");
asm("push r22");
asm("push r23");
asm("push r24");
asm("push r25");
asm("push r26");
asm("push r27");
asm("push r30");
asm("push r31");
scheduler();
asm("pop r31");
asm("pop r30");
asm("pop r27");
asm("pop r26");
asm("pop r25");
asm("pop r24");
asm("pop r23");
asm("pop r22");
asm("pop r21");
asm("pop r20");
asm("pop r19");
asm("pop r18");
asm("pop __tmp_reg__");
asm("out _SREG_,__tmp_reg__");
asm("pop __tmp_reg__");
asm("pop __zero_reg__");
asm("reti");
}
Es gibt 2 Fehlerbilder:
Wenn ich den scheduler direkt einfüge (statt des Aufrufs scheduler() )
ist schicht, es geht gar nichts mehr.
Allerdings wird die ISR komplett abgearbeitet. Eventuell scheitert der
Rückspung oder das wiedereinschalten der Interrupts.
Das selbe gilt auch, wenn ich statt reti nur ein return verwende.
Das interessante in diesem Fall ist, dass schon der Rücksprung aus
Scheduler() in die ISR schiefgeht. Der Scheduler wird bis zu ende
abegarbeitet, aber in die ISR kehrt er nie zurück. Das habe ich mangels
debug-hardware mit nem simplen PORTD = 0x01 (LED an PD1 an) geprüft.
Wenn ich den alles bis auf den aufruf weglasse, läuft es zwar im
prinzip, aber es werden eben Register überschrieben.
Ich bin heut vermutlich einfach zu kaputt, um dahinterzukommen. oder zu
blöd ;)
Jedenfalls werden im proloque / epilog nur einige Register, sowie das
SREG gesichert und wiederhergestellt - eben normale Kontextsicherung und
-wiederherstellung. Irgendwas läuft hier schief.
Any Ideas?
Ich habe bis jetzt noch nichts von Hr. Greschenz gehört, aber ich habe
mein OS zum teil umgeschrieben, und ihm dies auch mitgeteilt.
Ich werde die neue Version veröffentlichen, wenn ich mich mit ihm
abgestimmt habe, um Probleme zu vermeiden.
gruß
tobi
Ohne jetzt hier bewerten zu wollen, wer nun von wem abgeschrieben hat
(und ob überhaupt!):
Ich halte es durchaus für möglich, dass beide Autoren eine gemeinsame
Quelle hatten, die durchaus dafür sorgen kann, dass man mit bestimmten
Ideen geimpft wird und in der Folge - gerade bei einer doch ziemlich
weitgehend vorgezeichneten Aufgabe wie hier - verdammt ähnlichen Code
produziert.
Wer weiß, vielleicht hat Schwabl sich von GOS inspirieren lassen... :-)
Viele Grüße,
Simon
Denkbar ;)
Vor allem da Schwabl und Tanenbaum (das war das 2. Buch, dessen Name
fiel mir vorhin nicht ein) auch nicht so ganz unbekannt und auch ziel
zitiert sind (legal wie illegal).
Na ja, wie auch immer. Ich hab mein OS angepasst, und mit Hr. Greschenz
Kontakt aufgenommen. Mehr kann ich zur Zeit eh nicht tun ;)
Ich wünsche einen guten Morgen.
tobi
Frank M. schrieb:> Du rufst aus der ISR die Funktion scheduler() auf und dort machst Du> einen RETI. Damit machst Du den Stack, den sich der Compiler beim> Übersetzen der ISR und der Funktion secheduler() selbst gebaut hat,> kaputt. Besser gesagt: Du baust den Stack, der bei jedem ISR-Aufruf> aufgebaut wird, nicht wieder korrekt ab.>> Vielleicht schaust Du Dir den vom Compiler erzeugten ASM-Code für die> ISR und für scheduler() mal an und prüfst den auf saubere> Stackbehandlung.
siehe Beitrag "Re: NeuesOS für AVR Mikrocontroller"
war beim AVR-GCC mit Optimierungsstufe 3
So, ich hab jetzt genug drüber nachgedacht, und denke, dass ich das
Rätsel um das reti nun mal aufklären kann:
Ok es ist etwas unsauber, da es ersten Start eines Tasks tatsächlich
dazu kommt, das er nicht mehr in die ISR zurückspringt (daher
funktionierte auch "return" im Scheduler nicht), da er hier den von
task_create() vorgegeben Initialwert des PC für den Rücksprung nutzt.
Aber danach springt er in die ISR, und der Stack wird auch wieder
abgebaut. Der Grund dafür ist der zweistufige Einsprung in den
Scheduler:
Zunächst springt der in die ISR, und die Rücksprungadresse landet auf
dem Stack.
Dann sichert er dort einige Register auf dem Stack, und ruft den
Scheduler auf, wobei jetzt die Rücksprungadresse in die ISR auf dem
Stack landet.
Der Scheduler sichert nun den Kontext und schaltet den Task um, wobei
auch der SP verändert wird.
Das macht aber nichts, denn das eben gesagte gilt für alle Tasks. Somit
findet er nach dem zurücksichern des Kontext wieder den Rücksprung in
die ISR. Für diesen Task werden zusätzlich innerhalb der ISR noch einige
Dinge vom Stack gelesen. Und dann wird wieder in den Task selbst
verzweigt.
Ich hab zwar keinen debugger hier, aber eine simple Zählvariable in der
ISR hinter dem Scheduler-Aufruf, ausgegeben auf PORTC oder sonstwo,
verrät einem, das ich Recht habe ;)
So erzeugt z.B.
SIGNAL (SIG_OVERFLOW0)
{
scheduler();
PORTC++;
}
ein mit der Freuenz der Scheduler-Aufrufe hochzählendes binärlauflicht
;)
Ich hoffe ich hab mich hier verständlich ausgedrückt...
Was ich interessanter finde ist die Tatsache, dass der proloque/epiloque
überhaupt notwendig ist, aber ok...das System ist insgesamt recht
komplex. Ich möchte jetzt nicht den ganzen Code durchforsten, aber da
gibts bestimmt noch irgendwo ein paar Dinge außerhalb der eigentlichen
Tasks, die gesichert werden, wie z.B. Rücksprungadressen und lokale
Variablen.
Aber da ließe sich bestimmt noch optimieren.
Fakt ist, mit dieser Variante funktioniert das System unabhängig vom
Optimierunslevel etc. sehr gut. Ändere ich es, in dem ich den Scheduler
direkt in die ISR packe, und dort "naked" verwende, ist zwar der
proloque/epiloque weg, aber es gibt eben auch massive Probleme mit den
Tasks untereinander. Das Multitasking arbeitet zwar, aber es kommt zu
Interferenzen zwischen den Tasks.
Ich selbst kann mit den paar Befehlen proloque/epiloque zur Zeit leben.
Es ist zwar interessant, mal rauszubekommen, ob es da noch Potential
gibt, aber ich bin zur Zeit dabei, mich in nen neuen Job einzuarbeiten,
und privat will man ja auch nochmal was anderes tun ;)
Wenn mal zeit ist, grabe ich mich da gern durch. Auch jeder der dies
liest, ist dazu eingeladen. Ansonsten bleibt der Scheduler erstmal, wie
er ist.
gruß
tobi
... deine letzten Postings lesen sich so, als hättest du den Scheduler
nicht geschrieben und müsstest jetzt erst rausfinden, was der überhaupt
macht und wie er funktioniert ...
Irgendwie glaub ich dir einfach nicht ;-)
hi Helli,
in C weiß ich wie der funktioniert ;) In Assembler bin ich nicht so der
crack. Wie gesagt, manches war trial & error ;)
Ich frage mich nur immer noch, warum der proloque/epiloque notwendig
ist. aber das schau ich mir echt wann anders in ruhe an, jetzt muss ich
erstmal im neuen job ankommen.
übrigens...von günther hab ich nichts gehört bis jetzt. ich warte noch
etwas und dann werd ich meine geänderte version online stellen. ich
denke, ich werde auch romans anregung mit aufnehmen, den stack in ein
globales array zu verlagen, und die stackgrößen variabel zu machen. das
ist ja nicht soviel arbeit.
bis dahin sind weitere anregungen gern wilkomen.
gruß
tobi
hi
also für mich als außenstehenden und jemanden der auch hier und da
programmiert und versucht
ich sehe das so :
er hat ein OS gesucht und versucht es zu verstehen wie es arbeitet
ihm sind dann einige stellen aufgefallen was man eventuell verbessern
könnte
bzw erweitern ...
das ist lobenswert und würde auch den author von GOS glücklich machen
was mir daran so misfällt:
er "verkauft" es als sein OS trotz dessen es hunterte zeilen sind die
wirklich identisch sind sogar variablen gleich .. ja sogar kommentare
ich würde vermuten sogar schreibfehler und groß/kleinschreibung
für mich is der typ nen blender der sich hier ma etwas wichtig machen
will
ich hätte es besser gefunden bei der wahrheit zu bleiben ...
er hat GOS erweitert vlt verbessert ... mehr nicht
es aber nach so vielen beweisen immernoch abzustreiten ...
ist etwas .. naja ... dreist
Hi fremder (interessanter name),
ich hoffe, du hast auch gelesen, das mein Scheduler älter ist als GOS.
Aber es ist schon richtig, ich habe im Rahmen einer Diplomarbeit die
Funktionsgrundlagen für ein OS definiert, und daraus ist dann eben Nano
OS entstanden.
Und es sind ca 100 Zeilen, mal abgesehen davon, dass GOS ein reiner
Scheduler ist, und nano os sehr viel mehr Funktionen bietet.
Aber ok, ich kann auch jeden verstehen, der da anders denkt. Das die
Sachlage aus Sicht des Forums eine andere ist, ist klar, und ich kann es
nicht beweisen.
Ich will und werde aber auch dem GOS-Author keinen Vorwurf machen, zumal
ich denke, dass wir evtl. schlicht die gleichen Quellen benutzt haben.
Aber wie auch bereits geschrieben, habe ich den Scheduler nochmal
überarbeitet, damit die identischen Teile weg sind.
Und ich habe mich auch mit dem Author von GOS in Verbindung gesetzt, der
sich aber bis heute nicht gemeldet hat.
Ich warte noch etwas ab, weil ich mich eigentlich mit ihm abstimmen
möchte, bevor ich die neue Version online stelle. Aber wenn da in
nächster Zeit nichts kommt, dann geht das Ding online.
Diesmal zur Sicherheit unter GNU GPL.
Ansonsten noch "happy coding" und gute n8:)
Ich melde mich spätestens wieder, wenn die neue Version online geht.
Nochmal was ganz anderes...jetzt wurde hier soviel über den Scheduler
geredet...wie siehts denn mit den anderen Teilen aus? Hatte da schonmal
jemand gelegenheit, zu testen, und evtl. Anregungen oder Fehler
gefunden?
Insbesondere würde mich der Bereich der Messages interessieren, denn die
Semaphore sind einfach gestrickt, und auch das RAM-Management ist nicht
allzu komplex.
gruß
tobi
Eine LETZTE Anmerkung zum Thema der abgeschrieben Scheduler noch:
In meiner nano_os.h steht als supported device nur der Mega168. GOS hat
da viel mehr devices stehen, den Mega168 übrigens nicht, wenn ich das
aktuell richtig im Kopf habe.
Ich habs eben auf nem Mega168 getestet und geschrieben, da ich diesen
für mein Uhrenprojekt verwendet habe.
Ich finde es auch spannend, das in der ganzen Diskussion allein das
veröffentlichungsdatum von GOS bzw. nano os und die gemeinsamkeiten
zählen. Das ist zwar aus Sicht des Forums verständlich, aber das
Veröffentlichungsdatum muss nunmal nicht dem Entwicklungsdatum
entsprechen.
Und auch die Tatsache, dass der GOS - Author und ich die gleichen
Quellen verwendet haben könnten, spielt eine Rolle.
Auch wurde scheinbar nur von wenigen zur Kenntnis genommen, das ich hier
in die Offensive gegangen bin, und den Author von GOS kontaktiert habe.
Ich möchte jetzt auch langsam echt mal wieder zum Ursprung, ergo der
technischen Weiterentwicklung zurück. Ich werde den neuen Scheduler in
einem neuen Thread veröffentlichen, da ich befürchte, das in diesem
Thread keine echte technische Weiterentwicklung mehr entsteht.
Damit nicht die Behauptung aufkommt, dass ich hier wegen nem schlechten
Gewissen weg will, werde ich auch auf diesen Thread verweisen.
Mehr als voll in die Offensive gehen kann ich nicht...und auch aus
anderen Gründen möchte ich mich hier zum Thema des Abschreibens nicht
mehr äußern.
Versteht mich nicht falsch, aber bei mir steht da noch eine Arbeit im
Hintergrund, und ich habe mich mit meinem Betreuer über diesen Thread
hier ausgetauscht, und darauf geeinigt, dass ich mich hier nicht mehr zu
diesem Thema äußern werde. Tut mir leid, aber das hat definitiv
Priorität für mich.
Technische Anregungen sind weiterhin gerne gesehen, auch im neuen Thread
für den neuen Scheduler. Ich poste hier dann den neuen link.
so, nun geh ich aber mal ins bett.
Hallo Tobias,
ich finde es schade, dass einige auf dir herumhacken. Es gibt Leute, die
stören sich an jeder Trivialität, selbst an so Dingen wie einem
abgeschriebenen "define ...". Da vergeht einem natürlich die Lust, noch
irgenndwas zu veröffentlichen.
Meine Meinung: Lass Dich nicht von denen entmutigen und gehe Deine Weg
einfach weiter.
Viele Grüße,
Markus
Hallo Tobias,
bitte, bitte, bitte rücke deinen Code anständig ein. Klar gibt es da
verschiedene Stile, aber so bitte nicht.
Hier mal einen Auszug, wie man viel lesbarer formatieren könnte:
hallo leute :-)
long time no see...
wie ihr gemerkt habe, bin ich schon seit geraumer zeit nicht mehr so
recht aktiv hier :-( mir fehlt einfach momentan die zeit für so ein
tolles hobby... (aber ich habe inzwischen meinen sohn infiziert, mal
schaun... :-)
muss ich das alles jetzt durchlesen ? oje :-)
erstmal meine meinung zu GOS:
-> GOS ist 100% von mir, ohne quellen direkt VHIT !
das kann ich (wenns wirklich unbedingt sein muss, ich müsste heftig
suchen) belegen, da ich entwicklungs-snapshots (zips) habe, die jeder
als authentisch ansehen dürfte !
ich habe es aus reinem interesse geschrieben (damals auf meinem guten
alten palm-pilot) und dann nochmal für den avr...
ich bin dann daran gescheitert eine schöne "sleep(ms)" funktion zu
bauen, da gos ja keinen "festen tick" hat...
die zeitscheibenlänge definiert die priorität, ich hätte dann dafür
einen 2. timer gebraucht (böse ressourcen-verschwendung) und die beiden
dann auch noch irgendwie syncen müssen...
ist das in nano-os drin ? würde mich interressieren wie das gelöst ist /
werden kann. d.h. z.b. wie zeitgenau -> kann ich damit servos steuern ?
und zu nano-os:
-> ich habs mir aus zeitmangel noch nicht angeschaut...
also:
1) "Ich will und werde aber auch dem GOS-Author keinen Vorwurf machen,
..."
-> na danke aber auch ;-)
2) keine ahnung ob tobi nun abgeschrieben hat oder nur inspiriert war
oder was auch immer.
der hintergrund des "(C)" war
a) dass mein name erhalten bleibt (ist grade umso wichtiger, da mein
momentaner arbeitgeber evtl. den standort hier zumacht, und so ne
"google-referenz" ist grade jetzt für mich umso wichtiger, naja, evtl.
hab ich dann ja wieder zeit für GOS&co. !)
b) dass kein kommerz getrieben wird (da will ich dabei sein, kann dann
auch gerne weiterentwickeln :-)
privat habe ich (natürlich !) nichts dagegen
@tobi: have fun damit !
wenn du was schriftliches brauchst / willst mail mich einfach an ! (wenn
nicht dann nicht :-)
ich will und werde dir übrigens auch keinen vorwurf machen :-)
::: aber mal was ganz anderes :::
@alle: mal kurz zu meinem avr-wiz
der läuft immernoch auf weinem wohnzimmer-vdr @home.
da ich aber überhaupt keine zeit habe daran weiter zu bauen oder ihn
auch nur zu warten überlege ich gerade was ich damit mache.
wenn mein vdr nach einer aufnahme runterfährt (was er momentan noch
nicht macht) wäre er in zukunft nur noch zwischen 20:15 und 00:00 zu
erreichen.
ich habe mir nun überlegt, ihn evtl. den "avrfreaks" anzubieten, d.h.
sie könnten ihn in ihre web-präsenz einbauen.
oder ist evtl. "mikrokontroller.net" interessiert (liest hier evtl. ein
admin mit ?) ?
ich will nur nicht, dass er stirbt, die "google-referenz" ist mir auch
hier recht wichtig...
any other ideas ?
bye, gg
@Günther:
Erstmal danke für die Rückmeldung. Ich habe mit sleep(ms) das selbe
Problem. Ist ja auch klar ;). Was ich eingebaut habe ist ein funktion
wait_for_laps(), mit der man einen Task eine bestimmte Anzahl von
Scheduler-Runden schlafenlegen kann. Ein genaues timing ist damit
natürlich nicht möglich, die Funktion dient eher dazu, einen Task
"ruhigzustellen", wenn absehbar ist, dass er länger nichts zu tun hat.
Zusätzlich gibt es -wie in GOS auch- Funktionen zum Schlafenlegen und
Wecken eines Tasks, allerdings mit dem Unterschied, das du ein
TaskSignal dafür nutzt, während ich direkt auf den Task selbst arbeite.
In meinen Uhrenprojekten habe ich zur Erzeugung des Grundtakts für die
Uhr den timer2 genutzt, da ich diesen (beim Mega168) mit einem externem
Uhrenquarz betreiben kann.
Also auch bei mir kein sleep(ms) oder sonstwas ;(
Ansonsten geht die Funktionaliät in nano_os allerdings deutlich weiter,
so kann es dynamisch tasks erstellen/verwerfen, und auch Dinge wie
Speichermanagement, Semaphore und Message Queues sind dabei. Gerade für
diese hätte ich gern noch "Funktionsberichte".
Ich habe meinen Scheduler schon neu geschrieben, um die Ähnlichkeiten
weg zu bekommen. Dann gibts hier definitiv kein Thema mehr, hoffe ich.
Den stelle ich dann in einem neuen thread unter GPL zur Verfügung.
Vorher werden noch einiger der hier gesammelten Anforderungen mit
aufgenommen, hauptsächlich die Idee, den Stack in ein globales Array zu
verlagern.
@Nico: Nehme ich mit. Hier hat eben jeder "seinen" Stil. Aber das ist ja
kaum Arbeit, und ich denke, da lässt sich was machen.
Die Formatierung ist auch in Zusammenhang mit der Diplomarbeit
entstanden. Ich gebe dir aber recht, für sich ist sie etwas "schwierig".
sorry, muss dich erstmal korrigieren:
@Günther: -> @Günter:
danke :-)
warum ich gos angefangen habe:
* ursprünglich wollte ich servos steuern.
* "ich kann das, also tu ichs" (1. informatiker-gesetz :-)
* einfach mal schaun wie wenig assembler nötig ist (am liebsten hätt
ichs ja in c++ gemacht)
sollte also von anfang an ein lern/lehr sample werden...
warum ich mit gos nicht weitergemacht habe:
da ich mit dem verwendeten konzept ein sehr genaues "sleep(ms)" nicht
realisieren konnte (die servos flackerten ohne ende) hab es ich dann
nicht weiterverfolgt. ich mag es, wenn der unterbau stimmt bevor ich
darauf aufbaue, und ein sleep gehört für mich dazu. das wird in recht
vielen anwendungen gebraucht...
hat evtl jemand ne idee wie man
*) ohne 2. timer
*) in C :-)
einen möglichst genauen timer in gos (oder nano-os :-) einbauen könnte
?
da die slice-grössen sich ja verändern müsste man die irgendwie
aufsummieren
und dann die prio des letzten tasks dynamisch berechnen...
hört sich kompliziert an :-(
@ Günter Greschenz:
Ohne jetzt sehr lange darüber nachgedacht zu haben: Aber wie wäre es,
den einen Timer einfach schneller laufen zu lassen und damit dann die
anderen Timer "emulieren"?
Also wenn ich einen 200-ms-, einen 500-ms- und einen 1000-ms-Timer
brauche, dann initialisiere ich einfach einen 100-ms-Timer und kann
damit alle anderen Auflösungen emulieren, wenn du verstehst, was ich
meine.
Gruß,
Nico
Erstens: Man könnte die Prioritäten weglassen, und einfach alle x
Systemtakte via TimerXX_ovf umschalten.
Dann wäre ein sleep() problemlos machbar, aber es stünden eben auch
keine Prioritäten mehr zur Verfügung.
Man könnte natürlich auch die Task-Umchaltung (in Abhängigkeit von der
Priorität) jeweils erst nach n timerXX_ovf - Interrups auslösen (z.B.
n=1 bei Prio low, 2 bei medium, 3 bei high oder so). Auch dann wäre ein
sleep möglich, auch in Verbindung mit Prioritäten. Aber Priority "low"
wären dan n schon 256*1024 Takte, was dem aktuellen prio high
entspricht. Und vorzeitiges Ausberechen aus den Tasks a la task_switch()
ist ebenfalls tabu, da hier TCNT neu gesetzt wird.
Das ganze sehe dann eben (nur der Kopf) in etwa so aus:
void scheduler()
{
sleep++; //increase variable for sleep-function
act_prio_count++;
if (task->prio <= act_prio_count)
asm volatile("reti");
else
{
akt_prio_count = 0;
//Contextswitch
}
}
Evtl gäbe es auch andere Ideen, z.B. in dem man den Compare-Mode
nutzt...
@nico: geht so nicht, denn in beiden OSsen wird das TCNT0 (timer-counter
Register) in Abhängigkeit von der aktuellen Priorität verändert. Das ist
das Grundproblem.
hacker-tobi schrieb:> Evtl gäbe es auch andere Ideen, z.B. in dem man den Compare-Mode> nutzt...
hmm, damit kenn ich mich gar nicht (nur seeeeehr grob) aus.
evtl. hast du da echt ne heisse spur...
wie gesagt hat momentan echt zu wenig zeit das zu verfolgen :-(
oder halt doch nen 2. timer spendieren (geht aber gegen mein ego :-)
Das Zeitproblem kenne ich....der Compare mode ist einfach:
Sobald TCNT0 einen definierten Wert erreicht, gibts nen Interrupt. Den
kann man natürlich für nen Scheduler nutzen.
Die simpel-Lösung:
Mit jedem Timer0_OVF führt man einen Task-Wechsel aus. Jetzt definiert
man den Compare-Wert auf:
1 für low, 64 für medium und 255 für high.
somit hätten die Tasks 1024, 64*1024 und 255*1024 takte zeit.
Das TCNT0 bliebe unverändert, und damit könnte Timer0_OVF auch für ein
definiertes sleep() genutzt werden.
Wird der Compare-Interrupt ausgelöst, wechselt man (z.B.) in einen
Idle-Task der bis zum nächsten Timer0_OVF nichts tut.
Das Problem ist folgendes: Was macht man bei low und medium-tasks mit
der Zeit bis zum nächsten Timer0_OVF (immerhin 254 bzw. 191 * 1024
Takte)?
Die würden nämlich bei dieser simpelst-Lösung einfach ungenutzt
verpuffen.
Also von Ideal ist das weit entfernt...
> Also von Ideal ist das weit entfernt...
zumindest wenn man alles auf einmal erschlagen will.
evtl. reichts ja für "standard" apps mit servo, rs232, midi (ums nicht
zu einfach zu machen)
Günter Greschenz schrieb:> da ich mit dem verwendeten konzept ein sehr genaues "sleep(ms)" nicht> realisieren konnte (die servos flackerten ohne ende) hab es ich dann> nicht weiterverfolgt.
Verstehe ich das richtig, Du wolltest mittels sleep(ms) mehrere
Soft-PWM-Kanäle erzeugen (z.B. fünf Tasks, die jeweils einen anderen Pin
ansteuern)?
jupp, so in der art, nur halt nicht 5 sondern so viel wie geht, d.h. wie
pins als "out" schaltbar sind (wollte mal nen kleinen roboter baun :-)
mit richtigen timern hats sehr gut geklappt, die servos waren saustabil,
aber halt zu wenig...
So, nun gehts ja hier doch mal mit der Entwicklung und Ideen weiter.
Daher habe ich mich entschlossen, auch meinen neuen Scheduler hier zu
veröffentlichen.
Was ich getan hab:
-Code der Taskverwaltung neu geschrieben,
-die Stack(s) in ein globales array im RAM verlagert.
To Do:
Die Stacksizes dynamisch veränderbar machen. Sorry, ich hab zur Zeit
einfach zu wenig Zeit. Und wenn dann mach ich das richtig, also inkl.
"best-fit"-Algorithmus, um das array möglichst auszureizen.
Thema Formatierung: Ich weiß nicht, aber irgendwie ist das mein Stil,
code zu schreiben. und das seit Jahren ;) Daher bin ich bis jetzt bei
meiner Formatierung geblieben. Wer sich das anders formatieren will,
kann das gern tun.
Leute,
die Version von eben bitte nicht verwenden. Da ist mir ein grober Fehler
in task_control.c unterlaufen, durch den ihr euch beim dynamischen
Anlegen von Tasks zur Laufzeit den Stack zerschießt.
Nun ists bereinigt. Anbei die funktionierende Variante.
Hallo zusammen,
bisher habe ich nur ab und zu mitgelesen, weil ich nicht so viel
Ahnung von der Programmierung habe. Aber zu dem Thema sleep() ist mir
folgendes eingefallen:
Soweit ich das (ohne in die Quellen zu schauen) verstanden habe, gibt es
ja eine Liste mit Tasks, in der auch die Prioritäten festgelegt werden.
Was ist, wenn man die Prioritäten als "Startzeiten" ansieht. Der
Task-Timer läuft mit einem konstanten TCNT. Die Tasks laufen solange,
bis die nächste Startzeit fällig ist. Im Interrupt müsste dann nur noch
ein Zähler mitlaufen, der "Startzeit"-Zähler systick. Ist systick >=
"Startzeit" wird der aktive Task gewechselt und der neue Startzeitpunkt
des alten Tasks festgelegt.
Wenn ein Task jetzt einen Sleep() haben will kann man den Startzeitpunkt
für den Task entsprechend anpassen und einen IDLE-Task starten, bis der
nächste Task an der Reihe ist.
Werden 2 Tasks gleichzeitig zuteilungsreif, entscheidet die Prio.
Man könnte das noch soweit erweitern, dass man zu der Startzeit noch
eine Laufzeit aufnimmt. Dann kann man mit der Laufzeit die Betriebszeit
einer Tasks begrenzen und einen IDLE-Task aufnehmen, welcher Aufgaben
niedrigster Priorität übernehmen kann.
Ich hoffe, das ergibt einigermaßen einen Sinn.
Zu dem Sleep-problem, wie wärs damit:
Der Taskswitch wird nicht im Overflow gemacht sondern im Comparematch.
Der Timer läuft frei durch. Der Comparematchwert ergibt sich einfach aus
dem letzten Comparematchwert und der Priorität des Tasks (einfach
zugeteilte Zeit plus aktueller Wert) und wird bei jedem Taskwechsel neu
geschrieben. Auf diese Weise bleibt der Overflow frei für eine feste
Zeitbasis.
Ich hoffe das war jetzt nicht totaler mist. Kenne nämlich weder die
Sourcen von GOS noch von nano OS ;)
Sebastian
weden hier die Register ein bischen spät gesichert, oder?
Davor sind schon einige Zeilen Code, in denen die Register ja verändert
werden. Gut, es funktioniert, weil ja der Compiler dafür sorgt, daß die
dort verwendeten Register auch gesichert werden, d.h. aber es werden
viele / einige Register unnötigerweise doppelt gesichert. Das brauch
nicht nur Stack, sondern auch CPU Zeit.
Meiner Meinung nach ist der saubere Ansatz, den Scheduler (oder
zumindest Save und Restore der Register) direkt in die Interruptroutine
zu setzen und diese als _attribute_ ((naked)); anzulegen.
Wenn man aus einer Interrupt einen Funktionsaufruf macht, dann sichert
der Compiler üblicherweise einen Haufen Register, deshalb den Scheduler
direkt in die "naked" Interruptfunktion.
Gruß,
Bernhard
@Bernhard: Ja das ist im Prinzip richtig. Den scheduler in die ISR zu
legen, funktioniert aber nicht ;(
Siehe auch Beiträge vom 24.09.2010 20:37 ff.
Zum "späten" sichern: Das if-Konstrukt ist ein Test auf eine
Stack-Violation, und sollte daher möglichst früh erfolgen. Daher steht
es an erster stelle. Hier werden aber ausschließlich volatiles
verglichen, daher sind keine Operationen auf dem Stack nötig.
Das "TIMER REGISTER =" könnte auch hinter den pushes stehen, aber auch
hier wird am Stack nichts geändert.
@Martin/Sebastian: Stimmt, so sollte es mit dem Compare Match klappen.
Ok wird getestet.
gruß
tobi
Hi,
Der Scheduler muß in der ISR funktionieren, da muss man halt mal den
erzeugten Assembler-Code analysieren.
Selbiges muß man mit der Stack-Prüfung machen, die kann man nur dann
vorziehen, wenn der Compiler dabei nicht ans Sichern von Registern geht.
Notfalls müsste man das halt mit inline-Assembler erledigen.
Was für eine Compiler-Version?
Was spricht eigentlich gegen eine ordentliche Programmstruktur, mit
C-sourcen und dazugehörigen Headern? Der include von C-sourcen ist
normalerweise ein absolutes no-go! Mir persönlich fehlt da auch ein
Makefile...
Gruß,
Bernhard
Bernhard M. schrieb:> ... Mir persönlich fehlt da auch ein Makefile...
der avrwiz-online (achtung: eigenwerbung :-) erzeugt auch das fehlende
makefile :-)
nochmal zum thema "perfekter sleep":
wenn man einfach statt prio=zeitscheibenlänge die scheibchen kleiner
aber fix breit macht und dafür hoch-prio tasks z.b. mehrfach drankommen
lässt (d.h. die prio definiert einfach, wie oft nacheinander ein
bestimmter task drankommt) hätte man zumindest ein festes raster, das
macht die sleeps dann verlässlicher.
nachteile:
*) mehr interrupts (weil mehr & kleinere scheibchen)
*) nicht alle sleep-zeiten würden gehen, nur vielfache schlafzeiten der
scheibchen-zeiten.
*) bestimmt noch mehr :-)
Tobi,
was du suchst, glaube ich, zu mindest.. ist die naked isr von avr-libc.
<zitat>
#define ISR_NAKED
# include <avr/interrupt.h>
ISR is created with no prologue or epilogue code. The user code is
responsible for preservation of the machine state including the SREG
register, as well as placing a reti() at the end of the interrupt
routine.
</zitat>
dh. die pushs vor dem scheduler werden nicht mehr gamacht und dann
sollte es wieder stimmen mit der stack organization. muss aber zugeben,
ich habe die neuste version noch nicht angeschaut..
lg roman
Bernhard M. schrieb:> Meiner Meinung nach ist der saubere Ansatz, den Scheduler (oder> zumindest Save und Restore der Register) direkt in die Interruptroutine> zu setzen und diese als _attribute_ ((naked)); anzulegen.
deswegen mach ich es ja auch genau so :-)
(wieder eigenwerbung, sorry :) schau die das ganze generierte konstrukt
einfach mal an (natürlich im avrwiz :-).
*) im linken fenster haken "multitasking" setzen
*) im rechten dann auf "tasks.c" klicken und anz nach unten
mir war wichtig, dass der ctx-switch seeeeehr wenig cyclen braucht.
ich hatte das mal ausgerechnet, waren nicht sehr viele ;-)
deswegen auch so sachen wie "#ifdef TASK_USE_SIGNAL": wenn mans nicht
braucht spart man ein paar cyclen wenns disablet wird...
@Roman65536
was macht denn "#define ISR_NAKED" ?
ist das nicht das gleich wie "__attribute__ ( ( signal, naked ) )"
kenn ich noch gar nicht (wie so vieles)
oh mann ich brauch mal wieder zeit für son hobby, die sw die ich
beruflich baue hat >1000 source files, sowas hübsches kleines wie
gos/nano-os nicht mal 1000 zeilen. seufz...
@guenter
eigentlich das selbe.. nur anderst definiert :)
und sogar fuer den reti gibt es ein define .. reti() wenn die
"avr/interrupt.h" included ist.. :)
<zitat>
oh mann ich brauch mal wieder zeit für son hobby, die sw die ich
beruflich baue hat >1000 source files, sowas hübsches kleines wie
gos/nano-os nicht mal 1000 zeilen. seufz...
</zitat>
geht manch einem so.. fuer das haben wir ja so ein hobby... ;)
autopilot fuer modelflieger unter 1000 zeilen .. cooles ziel 8D hihihi..
lg roman
>> Zum "späten" sichern: Das if-Konstrukt ist ein Test auf eine> Stack-Violation, und sollte daher möglichst früh erfolgen. Daher steht> es an erster stelle. Hier werden aber ausschließlich volatiles> verglichen, daher sind keine Operationen auf dem Stack nötig.> Das "TIMER REGISTER =" könnte auch hinter den pushes stehen, aber auch> hier wird am Stack nichts geändert.>
Schon mal das Assembler-Listening angeschaut? Den Stackverbrauch hast Du
damit enorm gesteigert! Du legst einige Register doppelt ab, genauso wie
SREG.
Wie sieht es eigentlich mit den Warnings aus? queue_read_byte schon
gefixt?
Günter Greschenz schrieb:> jupp, so in der art, nur halt nicht 5 sondern so viel wie geht, d.h. wie> pins als "out" schaltbar sind (wollte mal nen kleinen roboter baun :-)> mit richtigen timern hats sehr gut geklappt, die servos waren saustabil,> aber halt zu wenig..
Ich hab mir auch schon mal überlegt einen Roboter bzw. einen Roboterarm
zu bauen. Als Servos hätte ich dann OpenServo verbaut. Die Ansteuerung
über I2C finde ich eleganter als über PWM und die Möglichkeit die
Position auszulesen, könnte man auch irgendwie zu nutzen.
http://openservo.com/
@Mar IO: Ich weiß, das hier überflüssige Arbeit entsteht.
Aber wie gesagt, mit scheduler in die ISR und "naked" (wie bei GOS)
funktioniert es nicht ;(
Obwohl es das laut asm-file müsste, denn wie du richtig bemerkt hast,
werden im proloque/epiloque nur einige Register doppelt gesichert bzw.
wiederhergestellt.
Daher bleibt das erstmal so, bis ich mehr zeit habe, mal das "warum" zu
finden. Ich kenne mich auch mit assembler nicht so gut aus, daher
brauche ich zeit, um das asm-file zu analysieren.
Oder hast du da eine Idee, woran das liegen kann?
Ich verweise hierzu auf meinen Beitrag vom 24.09.2010 20:37 ff. dort ist
das Problem beschrieben.
trotz (bzw. gerade wegen) reti wird der Stack auch wieder abgebaut,
siehe meinen Beitrag vom 25.09.2010 18:49.
Sauber ist das derzeit noch nicht, aber wie gesagt, mir fehlt es zur
Zeit an Ideen und Zeit.
@Günter: Was ist der avr-wiz? Sagt mir jetzt so erstmal nichts.
Aber deinen Quelltext von GOS habe ich mir angesehen. Von daher ist mir
klar, worauf du raus willst. Ich weiß nicht, warum der Code bei mir
nicht funktioniert. Ist ja ansonsten nahezu identisch ;)
Roman65536 schrieb:> geht manch einem so.. fuer das haben wir ja so ein hobby... ;)> autopilot fuer modelflieger unter 1000 zeilen .. cooles ziel 8D hihihi..
wenn du das fertig hast: HER DAMIT :-)
mein sohn baut sich grade nen microcopter, der ist bestimmt gut
erweiterbar !
mar IO schrieb:> Ich hab mir auch schon mal überlegt einen Roboter bzw. einen Roboterarm> zu bauen. Als Servos hätte ich dann OpenServo verbaut. Die Ansteuerung> über I2C finde ich eleganter als über PWM und die Möglichkeit die> Position auszulesen, könnte man auch irgendwie zu nutzen.
naja, mir gings ums selbermachen und ich hatte den anspruch möglicht
billige hw zu benutzen. und die pwm-servos hatte ich halt @home ...
hacker-tobi schrieb:> @Günter: Was ist der avr-wiz?
schau mal auf http://greschenz.dyndns.org/avrwiz vorbei :-)
ich hab allerdings grade das problem, dass das mit chrome & ie nicht
mehr geht...
nimm den firefox und es sollte gehen (zumindest bei mir).
hab aber grad keinerlei zeit was zu fixen...
@mar io nochmal ;) Ich seh grad, mit dem argument, das die Abfrage der
SP-Volation viel Arbeit auf dem Stack verursacht, hast du recht. Ich
kann es aber auch nicht hinter die Registersicherung legen, denn dann
wäre es definitiv zu spät.
Außerdem würde es die Arbeit ja auch nur "verlagern". Mal sehen, ob ich
das evtl. vereinfache oder wieder herausnehme.
So jetzt arbeite ich erstmal weiter...bis heut abend ;)
<zitat>
wenn du das fertig hast: HER DAMIT :-)
mein sohn baut sich grade nen microcopter, der ist bestimmt gut
erweiterbar !
</zitat>
http://diydrones.com/profiles/blogs/announcing-arducopter-the
btw.. die diskusion mit den servos.. zwar sind wir weg von os.. futaba
hat doch auch irgend so ein bus system ?? weiss jemand wie den das geht
??
lg roman
Hi @ all:
Zum Thema sleep()
Folgender Code funktioniert
(nano_os.h)
SIGNAL (SIG_OUTPUT_COMPARE0A)
{
scheduler();
}
(task_control.c)
void task_schedule()
{
cli();
set_sleep_mode(SLEEP_MODE_IDLE);
TCNT0 = 0xFF;
TIMER_REGISTER = _BV(CS00);
//TIMER_ENABLE |= _BV(TOIE0);
TCCR0A=0x00;
OCR0A=TCNT0+1;
TIMER_ENABLE = _BV(TOIE0) | _BV(OCIE0A);
sei();
sleep_mode();
}
Im scheduler() statt
TCNT0 = active_task->priority;
neu
if (TCNT0 + active_task->priority <= 255)
OCR0A = TCNT0 + active_task->priority;
else
OCR0A = TCNT0 + active_task->priority - 255;
Das ist jetzt nur "quick&dirty" geschrieben und kurz angetestet, da ich
die Funktionalität nicht brauche.
Es ist auch nicht unproblematisch, gerade in Verbindung mit den
Wartefunktionen
wait_for_message() und
wait_for_semaphore()
da diese die Taktung des Timers "hochdrehen".
Da ich die Funktionalität nicht benötige, übernehme ich es nicht.
Aber es könnte eine Anregung für Günther sein, wenn er das in GOS
einbauen will.
Die Priorities müssen allerdings angepasst werden (low=1, medium=64,
high=254).
kurze erklärung: Timer0 läuft jetzt im Compare-Mode. Jedes mal, wenn
TCNT0 den in OCR0A definierten Wert erreicht, gibts nen Interrupt.
Dieser ruft über die ISR den Scheduler auf. Im Scheduler wird OCR0A
entsprechend der Prio des aktuellen Task neu gesetzt, und das Spiel
beginnt von vorn.
TIMER0_OVF ist damit frei für anderes...
@mar io Roman Bernhard:
Mein Problem ist nicht, das mir unlar ist, was es mit ISR auf sich hat,
oder warum es besser wäre, den Scheduler in die ISR zu ziehen, und diese
mit atrribut naked laufen zu lassen. Das habe ich im angehängten C-File
schonmal gemacht.
Mein Problem ist, dass es ohne den zusätzlichen Proloque/epiloque zu
Interferenzen zwischen den Tasks kommt, das Scheduling selbst
funktioniert.
Anbei das c-file des Schedulers mit ISR_NAKED, sowie die beiden
Assemblerfiles (einmal original, einmal mit ISR_NAKED).
Mich selber stört es auch nicht so sehr, dass da etwas zusätzliche
Arbeit notwendig ist. Meine Uhren laufen, das reicht mir zur Zeit. Mir
fehlt momentan echt die Zeit und bei Assembler auch das know-how.
@Bernhard:
Thema Struktur: Da spricht nichts dagegen ;) Das war irgendwan mal ne
Notlösung und dann hab ichs schlicht vergessen. Kommt in die nächste
Version mit rein.
Ja Tobias, ich denke dort irgendwo ist ja der hund versteckt..
denn, je nach optimierungs level, verschiebt sich der stack verbracht
(meinst mehr) den mehr optimierung heisst mehr die register zu nuetzen.
das problem ist, der scheduler muss ja den stack vorbereiten fuer den
task contex switch, inklusive den was vor dem scheduler auf stack war,
sie wie auch danach..
im klar text, im naked, hast du die absolute kontrolle was vorher auf
dem stack war und was danach sein wird. (ausser, man deklariert etwas
locales)
zu dem, der gcc und auch andere compiler, verwenden gewisse register
exklusiv fuer sich. da kann man tun was man will, plus sie werden nicht
gesichert...
siehe r18,19 in der naked version.. meistens findet man dies irgendwo in
der compiler beschreibung. daher ist es immer besser beim multitasking,
alle register als aller erstes auf den stack zu sicher noch bevor
ueberhaupt der scheduler aufgerufen wird (Solaris tut es so) oder gleich
in die task struktur (linux) und zwar im assembler. sind ja nicht viele
assembler commands.. und.. jenachdem .. muss man dies tun fuer alle
interupts. den.. ist das system beschaeftigt mit 1+1 rechnen und es
kommt ein interupt das zb. etwas von uart gekommen ist, auf das ein task
wartet, will man ja das dieser gleich rescheduled wird und sofort auf
die cpu kommt. oder .. man definiert ganz einfach, das kein scheduling
waerend einem interrupt statt findet. ein sehr aehnliche ansatz
verwendet linux. Die interrupts werden aufgerufen wie sie im system
registriert sind, jedoch, die device driver, resp. system setzt ein
flag, das ein rescheduling statt finden soll. nach dem alles fertig ist,
kurz vor der return from interrupt wird gepruefft ob dieses flag gesetzt
ist oder nicht.
dh. die reti springt dann gleich in einen anderen task.
ein andere weg, ist es ueber den longjmp zu arbeiten.. .irgendwo auf dem
net habe ich auch schon solch ein multitasking gesehen.
lg roman
Hi,
ich hab mal eben ne absolute minimalversion des schedulers gebaut, aus
der alles raus geflogen ist, was nicht notwendig ist. aber auch bei
dieser version bleibt es dabei...definiere ich ISR und naked, gibt es
Probleme mit Interferenzen. Aber ich bin mittlerweile so schlau, dass
ich sagen kann, wo die Interferenzen entstehen:
"Schuld" ist die Funktion wait_for_message(), denn die wartet jetzt
schlicht nicht mehr auf Nachrichten, sondern springt zurück, und zwar
unabhängig davon, ob hier eine Nachricht vorliegt oder nicht. Eventuell
ist auch die ähnlich konzipierte Funktion wait_for_semaphore()
betroffen. Und ich kann auch nicht ganz ausschließen, dass dies nicht
der einzige Fehler ist.
Na ja, bei zeiten werd ich mir mal das ASM dieser Funktionen ansehen.
Anbei der "minimal" Scheduler und das passende .s - File
Hi,
anbei die letzte Version. Aber viel ist nicht passiert. Im Wesentlichen
habe ich alle Compiler-Warnings wegbekommen und ein Makefile erzeugt.
gruß
tobi
Hallo Zusammen,
hier ein alternativer Vorschlag für den Scheduler. Der spart den extra
PUSH und POP-Block.
zusätzlich muss in der task_control.c der Stackpointer korrigiert
werden.
Statt
Hallo Maarten,
gute Idee, das SREG separat zu sichern, und die Bearbeitungsreihenfolge
im Scheduler etwas anzupassen. Das hat das Problem mit den Task -
Interferenzen gefixed. danke dir.
Ich habe noch einige Anpassungen gemacht, damit der Scheduler ins System
"passt".
Anbei die neue Version.
Ich habs eben sowohl mit der "einfachen" user-software als auch mit der
komplexeren Variante in allen optimierungsleveln getestet, und es sieht
gut aus - bis auf Optimierungslevel 3, da schmeißt der Compiler gut
doppelt so großen code (6400 gegenüber 3500 Byte) raus, und das asm-file
wird - sagen wir - unaufgeräumt. Aber das ist wohl eher ein Problem
meiner Compiler-Installation...
gruß
tobi
Hallo Tobias,
ich habe mir die letzte Quelldatei vom Datum: 11.10.2010 23:17 geladen
und im Makefile alle Pfade gelöscht, da unter Linux der gcc-avr und alle
Tools im Pfad liegen.
Dann habe ich für spätere Tests einen atMega88 eingebaut, siehe
"system/header/nano_os.h".
Stimmen die Angaben ?
1
#elif defined (__AVR_ATmega88__)
2
#define RAMSTART 0x60
3
#define HEAPSTART 0x02FF
4
#define STACK_SIZE 96
5
#define TIMER_REGISTER TCCR0B
6
#define TIMER_ENABLE TIMSK0
7
#define TIMER_VECTOR TIMER0_OVF_vect
8
#define CLK1 _BV(CS00)
9
#define CLK1024 _BV(CS02) |_BV(CS00)
10
#else
In "nano_os.c" stand noch
1
#define F_CPU 8000000
, das ist zu viel, da im Makefile auch definiert.
Ich erhalte nur eine Warnung:
1
In file included from nano_os.c:27:
2
system/scheduler.c:26: Warnung: Funktionsdeklaration ist kein Prototyp
Gibt's dafür eine Lösung?
Und habe ihr noch Beispiele, wie man etwas Programmieren könnte ?
Z.B. könnte man noch eine LCD-Display anschließen und die Ausgabe der
Zeichen über eine eigenen Task und die Daten über eine MessageQueue
einlesen.
Wenn ich richtig gerechnet habe, können maximal 7 Task laufen.
Hallo Uwe,
Interessant, das dein avr-gcc das bemängelt. Trotz "-Wall" wird das bei
mir nicht bemängelt(ich arbeite ebenfalls mit avr-gcc unter Linux).
Er sagt damit, dass die Funktionsdeklaration nicht korrekt als Prototyp
definiert ist.
Probier mal
void TIMER_VECTOR(void) _attribute_ ( ( signal, naked ) ); statt
void TIMER_VECTOR() _attribute_ ( ( signal, naked ) );
Wie viel Tasks auf dem System laufen können, ist meist nur durch den
verfügbaren Speicher begrenzt. Jeder Task benötigt 9 Byte (bei Nutzung
aller Features) + STACK_SIZE byte für den Stack. Das System selbst kann
max. 255 Tasks verwalten.
Zu den werten:
Deine Stack_size ist sehr groß gewählt. Du hast vermutlich das
"Original" übernommen. Je nachdem, wie viel Stack du brauchst, kannst du
sie auch kleiner wählen (minimum sind 32 Byte für die Register).
Auch die Werte für RAMSTART und HEAPSTART solltest du nochmal überprüfen
(s. Datenblatt).
Die Prescaler (CS00 und CS02) stimmen bei beiden Prozessoren überein.
Aber im Zweifelsfall verrät dir auch hier das Datenblatt, welche Bits
gesetzt sein müssen, um den Timer0 mit Prescaler 1 bzw. 1024 laufen zu
lassen.
Bei den anderen Zuweisungen handelt es sich lediglich um aliasnamen.
Wenn hier etwas falsch ist, gibt der Compiler einen Fehler aus und
bricht ab.
Aber auch diese stimmen meines Wissens nach beim Mega88 mit dem Mega168
überein.
Danke auch für deine Hinweise zum Makefile. Allerdings ist die
Konfiguration hier sehr individuell; bei mir liegt der avr-gcc z.B.
nicht im Standardpfad und es wird für einen Mega168 übersetzt. Von daher
sind die Makefiles eben unterschiedlich.
gruß
tobi
hätte ich selbst kommen sollen.
Damit läuft der Compiler durch!
Ich hänge Dir das avr-gcc logfile an.
/Deine Stack_size ist sehr groß gewählt. Du hast vermutlich das
"Original" übernommen. Je nachdem, wie viel Stack du brauchst, kannst du
sie auch kleiner wählen (minimum sind 32 Byte für die Register).
Auch die Werte für RAMSTART und HEAPSTART solltest du nochmal überprüfen
(s. Datenblatt)./
Das verstehe ich noch nicht geschossen, da ich nicht weiß mit RAMSTART
und HEAPSTART eingestellt wird.
Da würde mir eine Grafik mit der Rambelegung sehr helfen.
.
RAMSTART ist die erste verfügbare Adresse im RAM, also der Beginn des
RAM.
HEAPSTART gibt die erste Adresse dews HEAPs an.
Die Speicherbelegung bei Atmel AVRs sieht (hier am Besispiel des Atmega
168) wie folgt aus:
0x0000 - 0x005f Regeister
0x0060 - 0x00ff (ext i/o-register) *Typabhängig.
0x0100 - 0x04ff RAM
Der Ram teilt sich nochmal in Data-Section, HEAP und STACK:
0X0100 - 0X02FF ram
0X02FF - 0X04FF Heap
0X04FF - 0x02FF Stack
Der Stack und Heap teilen sich einen Bereich, wobei der Heap nach oben
hin wächst, der Stack nach unten.
Die Bereiche werden (grob) wie folgt genutzt:
Ram: Ablage von Variablen etc.
Heap: allokierter Speicher (malloc)
Stack: Stapelspeicher des Prozessors für Register, Rückspungadressen
usw.
Nun noch ein Wort zu den Makros:
HEAPSTART wird in memory.c benutzt, umzu vermeiden, dass versehentlich
ein Speicherblock im Heap reserviert wird (das Speichermanagement von
nano_os nutzt nur den Ram-Bereich).
RAMSTART wird nur für die Berechnung der max. Anzahl an Tasks benötigt.
STACK_SIZE gibt die Größe des Stacks an, der für jeden Task reserviert
wird. Dies müssen mind. 32 Byte (für die 32 GPIO-Register des AVRs) sein
+ dem, was man noch selbst für lokale Variablen braucht. Hier lohnt sich
ausrechnen oder experimentieren.
Ausrechnen ist simpel:
-Berechnung des gesamtspeicherbedarfs aller Variablen für jeden Task
separat.
-Dann nehme man das größte Ergebnis und rechne 32 dazu. Das ist dann
schonmal ein guter Richtwert für die STACK_SIZE.
-Evtl. ist dann noch etwas experimentieren notwendig, da der Compiler
den Stack ebenfalls verwendet. Hier hilft ein Blick in das vom Compiler
erzeugte asm-File weiter.
gruß
tobi
Du kannst natürlich auch deinen User-Code mal hier posten, dann kann man
dir hier etwas unterstützung beim berechnen der Stack-size geben. Falls
es der Originalcode der Binäruhr ist, langt STACK_SIZE 64
So, ich hab noch folgende Änderungen eingepflegt:
-ISR-Attribute in
void TIMER_VECTOR(void) attribute ( ( signal, naked ) );
geändert und in nano_os.c gepackt
-nano_os.c aufgeräumt/altlasten entfernt.
Anbei das neue zip-file
noch was...irgendwie hatte ichs heut mittag:
-ISR-Attribute in
void TIMER_VECTOR(void) attribute ( ( signal, naked ) );
geändert und in nano_os.h (nicht nano_os.c!) gepackt
-nano_os.h aufgeräumt/altlasten entfernt.
@Uwe: Mach dir keinen Stress. Ist nur ein Hobby.
Heut überschlagen sich die Entwicklungen ;)
-Funktion "queue_get_mumber_of_messages()" war falsch benannt. Umbenannt
in "queue_get_number_of_messages()"
Viel wichtiger:
Die Funktionen "wait_for_message()" und "wait_for_semaphore()" so
angepasst, das hier keine Takte mehr unnötig mit warten verschwendet
werden. Liegt keine Message/ kein freier Semaphor vor, wird direkt in
den scheduler gesprungen.
Alter code (am Beispiel wait_for_messages):
uint8_t queue_wait_for_message(Queue *qp)
{
...
while (qp->number == 0)
{
TCNT0=0xFF;
}
return TRUE;
}
neuer Code
uint8_t queue_wait_for_message(Queue *qp)
{
...
while (qp->number == 0)
{
TIMER_REGISTER = CLK1;
TCNT0=0xFF;
}
return TRUE;
}
Funktion "shutdown_system()" eingefügt. Diese Funktion fährt das System
bei Bedarf herunter, in dem sie Interrupts und den watchdog abschaltet
und in eine Endlosschleife geht.
Vorher ruft sie noch "shutdown_user_environment()" in "user.c" auf.Hier
kann der user Kommandos festhalten, die vor dem shutdown noch ausgeführt
werden sollen.
Doku hab ich natürlich auch angepasst.
Die Änderungen hab ich mit beiden Varianten der
Binäruhren-Beispiel-Software in allen Optimierungsleveln getestet.
Funktioniert komplett fehlerfrei (jetzt sogar mit Optimierungslevel 3,
obwohl da der Code immer noch sehr groß wird...).
Ich glaub es wird mal Zeit für sourceforge oder ähnliches...Vorschläge?
gruß
tobi
Und noch ne Änderung wieder in "wait_for_message". Diesmal hab ich die
Funktion so angepasst, dass sie auf neue Nachrichten reagiert, nicht
mehr wie bisher auf das bloße verhandensein von Nachrichten.
Aus
{
...
while (qp->number == 0)
{
TIMER_REGISTER = CLK1;
TCNT0=0xFF;
}
return TRUE;
}
wurde
{
uint8_t number_old = qp->number
...
while (qp->number == number_old)
{
TIMER_REGISTER = CLK1;
TCNT0=0xFF;
}
return TRUE;
}
Anbei das neue zip-file
Hallo Tobias,
ändere doch bitte die Taktangeben wieder auf das Makefile ab,
dann kann man auch weitere externe Objekte mit diesem Makefile mit dem
richtigen Takt übersetzen.
Auch könntest Du meine Erweiterung um den atMega88 mit einbauen.
Danke.
Hallo Uwe,
ok, fließt in die nächste Version mit ein. Poste hier doch bitte nochmal
deine aktuellen Einstellungen für den Mega88 in nano_os.h (ich weiß,
weiter oben steht da schon was, aber ist das noch aktuell? Du warst dir
ja damals wegen einiger Parameter nicht sicher.)
Was ich bei interesse auch noch anbieten kann, ist die Abgabe von
eval-boards, welche auf dem Mega168 basieren, zum Selbstkostenpreis.
Aber natürlich können auch andere AVR-basierte Boards für die
Entwicklung genutzt werden.
Anbei der Schaltplan und die brd-files (egale) des eval-boards.
Es beinhaltet einige Taster, LEDs und einen Piezo zur Ausgabe von
Signalen, sowie einen ISP-Stecker und einen Erweiterungssteckplatz, auf
dem fast alle PINs des Atmega zugänglich sind.
Die Stromversorgung sowie ein Uhrenquarz inkl, Bürdekapazitäten sind
auch mit an Board.
Und nochmal die Frage: Besteht interesse daran, das ich das ganze auf
sourcefourge setze?
gruß
tobi
Hallo Tobias,
mein Projekt wird sich um die Ausgabe von Informationen für Sehschwache
oder Bilde OM bewegen.
Die benötigte Sprachausgabe (1) habe ich schon als PCM-->PWM
Soundausgabe mit einem atmega861V getestet und klingt an einem kleine
2-Weg Lautsprecher klasse.
Nun soll der nanoOS Kern die Eingabe über Taster/Tastatur, die Ausgabe
der TRX-Telegramme an eine LCD-Anzeige und ein Interface für ein
CAT-Interface (TRX) bereitstellen.
Es gibt viele CAT-Protokolle, so wird es auch eine Voreinstellung für
die verbreitetsten geben müssen.
Die Ausgabe einer der 255 Sprachdateien ist über 8-Bit möglich, ob nun
parallel oder seriell ist noch zu überlegen.
Eine Versionsverwaltung wäre zukünftig für alle Dateien wichtig, mehr:
http://www.ica1.uni-stuttgart.de/Courses_and_Lectures/C++/script/node34.html
Oder einfacher in jede Datei ein Change-Log der Form:
// 2010-10-25 <autor> <änderungen>, <kommentare>
// Version 1.00 vom 2010-10-25
Quelle :
(1) http://elm-chan.org/works/sd20p/report.html
.
Ein Funkamateur ;) 55+73 de Tobias, DD3AAA
Das Projekt klingt sehr interessant, aber auch sehr ambitioniert. Meinst
du, du kommst da mit nem Atmega88 hin? Ich mein die CAT-Ausgabe für den
Transceiver und die Ein- und Ausgabe über Taster bzw. LCD halte ich für
machbar, aber die Sprachausgabe ist denke ich nicht so einfach. Vor
allem da das Multitasking die Sprachausgabe unterbricht (wenn sie über
den Atmega läuft). Evtl. bietet sich hier ein zweiter AVR oder ein
externer Sprachaufzeichnungs-Chip an.
Ich werde das ganze Projekt in nächster Zeit auf Sourceforge o.ä.
abbilden. Eine Versionshistorie in den Dateien ist auch machbar.
Auch cvs ist denkbar, aber erst mittelfristig. Ich gebe ehrlich zu, dass
ich so etwas noch nie verwendet habe, und zur Zeit fehlen mir da etwas
die Kapazitäten, um mich einzuarbeiten (ein neuer job geht vor).
Was ich im Rahmen der Distribution nicht übernehmen kann, sind die
verschiedenen Makefiles, da diese einfach zu individuell sind. Aber ein
generisches Makefile liegt ja bei.
Die einzelnen Treiber bzw. Module (z.B. für das LCD) übernehme ich gern,
sofern sie die Mechanismen von Nano OS zur Initialisierung
(init_user_environment) und Kommunikation (Message queues)
implementieren, und somit auch für andere Nutzer verwendbar sind.
Ich denke, ich werde dazu in nächster Zeit mal einen kleinen Guide
schreiben, in dem ich meine Vorstellungen davon festhalte, wie Software
für nano_os aussehen sollte. Diesen werde ich dann natürlich zur
Diskussion stellen. Keine Sorge, nix großes, nur ein paar grundlegende
Richtlinien ;)
Hallo ich bin an dem neuen nanoos sehr interessiert. Ich habe da noch
eine Frage. Läuft dieses OS auch auf dem Atmega8535? Wieviel kb Ram bzs.
Rom benötigt dieses OS?
Moin Leo,
ich habe das Makefile und einen Eintrag in "nano_os.h" gemacht.
Hier sind noch die Stellen im Quellcode, die angepasst werden müssen.
Dort findest Du SIG_PIN_CHANGE0 das ist ein Hinweis, dass die
PCINTxyy bei deinem älteren µP fehlen.
.
Schau mal in das Datenblatt eines ATmega168 oder ATmega88, dort sind die
Pins mit diesen Bezeichnungen vorhanden.
D.h. nur jeder Pin kann in seiner Pin-Gruppe einen eigenen Interrupt
auslösen.
Was..SIG_PIN_CHANGE0? Sorry, aber das wird im nano_os quelltext
nirgendwo verwendet!
Was du prüfen musst, sind folgende Parameter in nano_os.h:
#define RAMSTART 0x60
Beginn des RAMs (siehe Datenblatt
#define HEAPSTART 0x02FF
//Beginn des HEAPs (meist genau auf der Hälfte der Adressen im Speicher)
#define STACK_SIZE 96
//Die Größe des Stacks jedes Tasks. Muss ggf. individuell angepasst
werden
#define TIMER_REGISTER TCCR0B
//Das Steuer-Register für Timer0
#define TIMER_ENABLE TIMSK0
//Das Interrupt-Mask-Register für Timer0
#define TIMER_VECTOR TIMER0_OVF_vect
//Der Overflow-Interrupt für TIMER0
#define CLK1 _BV(CS00)
#define CLK1024 _BV(CS02) |_BV(CS00)
//die Prescaler-Werte für Timer0 (CLK/1 und CLK/1024)
Das ganze packst du dann zusammen und schreibst es in nano_os.h
Sieht dann so aus
#elif defined (_AVR_ATmega8535_)
#define RAMSTART 0x60
#define HEAPSTART 0x02FF
#define STACK_SIZE 96
#define TIMER_REGISTER TCCR0B
#define TIMER_ENABLE TIMSK0
#define TIMER_VECTOR TIMER0_OVF_vect
#define CLK1 _BV(CS00)
#define CLK1024 _BV(CS02) |_BV(CS00)
Im Code lese ich mehrfach noch das Timer_register TCNT0 aus. evtl. muss
das auch angepasst werden, wenn es bei Mega8535 anders heißt. Aber da
wird dich der Compiler schon drauf aufmerksam machen ;)
Ansonsten müssen evtl. noch Änderungen in scheduler.c gemacht werden,
falls die Syntax der "alten" AtmMegas unterschiedlich ist, oder falls
die Anzahl der Register nicht simmt (die neueren haben 32 Register,
darauf ist nano_os ausgelegt).
Sorry für die kurze und sehr technische Einweisung, aber ich habe grad
wenig Zeit. Ich mußte jetzt aber mal intervenieren. Am WE hab ich Zeit,
das Datenblatt des 8535 zu lesen. Dann kann ich dir die Parameter geben,
falls du nicht weiterkommst. Aber lieber ists mir, wenn du das selbst
machst, dann lernst noch was dabei ;)
gruß
tobi
kurz nochmal was zur error.txt: Die ganzen PC_INT fehler stammen aus
user.c und user.h, also aus dem user code. das hat mit nano_os direkt
nichts zu tun. Das einzihe nano_os relevante ist TCCR0B und TIMSK0, also
die Einträge
#define TIMER_REGISTER TCCR0B
#define TIMER_ENABLE TIMSK0
für den Mega8535 in nano_os.h. Diese müssen also nach Datenblatt
geändert werden. Ansonsten gilt das oben gesagte.
Und nochmal ich ;)
Sorry....hab die Frage nach dem Speicherverbrauch überlesen.
Beim ROM hängt es von den Features ab. Nutzt du nur den Scheduler, bist
du bei ca. 1 kB. Mit allen Features (Message Queues, Semaphore,
dynamisches Taskmanagent und Speicherverwaltung) belegt das System
ungefähr 4,5 kB.
Das bezieht sich jetzt auf eine Übersetzung mit avr-gcc und
Optimierungslevel s.
Dies sind Richtwerte, da die konkrete Größe von der Zielplattform, dem
eingesetzten Compiler, der Größe des Usercodes, den genutzten Features
und dem eingestellten Optimierungslevel abhängt.
Im RAM ist es ähnlich: Nur der nackte Scheduler belegt wenige Byte.
Nutzt du alle Features, sind es etwa 200 Byte (grob). Dazu kommen noch:
-9 Byte + STACK_SIZE Byte für jeden Task inkl. des idle-task.
-1 Byte für jeden Semaphor bei Nutzung der Semaphore.
-7 Byte + n für jede Message Queue (n = MessageQueueDepth * item_size)
bei Nutzung der Message Queues.
-3 Byte für jeden Speicherbock + (MAX_BLOCKS * BLOCK_SIZE) Byte zur
Ablage der Daten im RAM bei Nutzung des Speichermanagements.
Noch ein Wort zum Thema Resourcenverbrauch in Bezug auf die vom System
verbrauchte Rechenzeit: Je nach Taktfrequenz und Anzahl/Priorität der
Tasks sowie genutzten Features bewegt sich der Grundlastverbrauch im
Bereich 2% (16 Mhz, 3 high-prio-tasks im System, nur Nutzung des
Schedulers) - 35% (1 Mhz Takt, 3 low-prio-Tasks im System, Nutzung der
Message Queues und Semaphore).
Dies sind allerdings auch nur Richtwerte, Abweichungen nach unten und
oben sind möglich, je nach konkreten Bedingungen (Taktfrequenz, Anzahl
und Priorität der Tasks, Nutzung der Message Queues/Semaphore usw...)
Verständlich. Komme auch grad vom QRL heim. Für nicht Amateuerfunker QRL
= Arbeit ;)
Melde dich, wenn du Hilfe brauchst oder Anregungen/Fragen/ideen hast.
Hallo,
ich hab das NanoOs auf meinem at90s8535 zum laufen gebracht.
Dafür habe ich zunächst nur mal zwei Tasks erzeugt, in der jeweils eine
LED zum blinken gebracht wird. Ich muss sagen, dieses OS lässt sich echt
einfach auf einen anderen AVR portieren. Gibt es für dieses OS eine
Dokumentation ?
hi leo,
welche aenderungen musstest du durchfuehren? bitte sende sie mir damit
ich sie einarbeiten kann.
eine einfache apidoku liegt im Verzeichnis software/doku.eine
vollstaendige doku folgt wenn ich zeit hab.
gruss
tobi
Hallo hacker-tobi,
ich kann dir meine Änderungen erst heute Abend sagen.
Ich habe eigentlich nur in der Headerdatei nano_os.h Änderungen
durchgeführt.
Den Timer für den Time Tick habe ich in der user.c Datei entfernt.
Hat dieses OS auch einen Pool Mechanismus? So wie es aussieht nicht.
Hallo Leo,
dann poste hier einfach mal deine Änderungen in nano_os.h
Die user.c ist hier unwichtig, denn dass ist dein user-code bzw. der
Beispielcode, und hat nichts mit dem OS selbst zu tun.
Pool:
Du meist doch nicht etwa resourcenpools, oder? So etwas auf dem AVR
umzusetzen ist nach meiner Ansicht unnötig, da man die wenigen Resourcen
gut "von Hand" verwalten kann, und Art und Anzahl der Tasks von Anfang
an bekannt sind.
Das OS verfügt über:
-preemptives Multitasking inkl. Prioritäten,
-binäre Semaphore (Mutex),
-Message Queues,
-ein einfaches Speichermanagement (basiert auf einem array im RAM) sowie
-Funktionen zur Task-Kontrolle (anhalten, löschen usw...)
nicht weniger aber auch nicht mehr ;)
gruß
tobi
Danke ;)
Mich würde mal interessieren, wo genau nach deiner Ansicht die
stärken/schwächen von nano_os im Vergleich zu FemtoOS liegen.
Kannst du das mal kurz zusammenschreiben?
Im Anhang befindet sich das Beispiel für den at90s8535.
Das femoos konnte ich bis jetzt nicht auf meinem at90s8535 zum laufen
bringen. Mit dem nanoos bin ich viel schnell zum Ziel gekommen.
Hi Leo,
deine Angaben stimmen nicht mit dem Datenblatt überein.
Lt. deinen Angaben beginnt der Speicher bei 0x060 und endet irgendwo
oberhalb von 0x02FF
Das kann aber nicht sein, denn 0x02ff = 767 Byte dezimal. Der Prozessor
hat aber nur 512 Byte RAM. Rechnet man noch die 0x60 (96 Dezimal) für
Register etc dazu, kommt an auf 512 Byte + 96 Byte - 1 = 607 Byte
gesamter Adressraum = 0x025F hex.
Das entspricht dann auch dem Datenblatt, nach dem der RAM bei 0x25F
endet.
Ergo ist dein HEAPSTART verkehrt. HEAPSTART berechnet sich aus:
(letzter Adresse im RAM (hier: 0x025F) - erster Adresse im RAM (0x060) /
2) + erster Adresse im RAM = (0x025F - 0x060 / 2) + 0x060 = 0x015F.
Zur Erklärung: Der Datenspeicher teilt sich bei den Atmels nochmal auf
in:
-DATA-Bereich: hier liegen die meisten Variablen etc
-HEAP: Dies ist ein Bereich für reservierten Speicher (z.B. malloc())
-STACK: Der Stack wird für Rücksprungadressen und teils auch für
Variablen genutzt.
Der HEAP beginnt dabei in der Regel genau ab der Hälfte des verfügbaren
Speichers, und wächst nach oben hin; Der Stack beginnt am Ende des
verfügbaren Speichers, und wächst nach unten hin.
Und genau hier kommt HEAP_START ins Spiel; Dieser Wert wird vom
Ram-Manager genutzt, um zu prüfen, ob allokierter Speicher den HEAP
verletzt (das Speichermanagement von Nano_OS arbeitet im Data-Bereich,
nicht im HEAP).
Das System funktioniert grad bei zu hoch angesetztem HEAP_START, aber
die Kontrollmechanismen versagen.
Bitte prüf mal, ob die unten angebenen Einstellungen hier funktionieren;
Ich habe keinen 8535 hier.
Darüber hinaus hast du deine Stack_Size sehr groß gewählt, mit 96 Byte
pro Task wirst du kaum mehr als 3-4 Tasks im System unterbringen können.
Bitte prüfe doch mal, ob auch kleinere Stacksizes funktionieren.
Da ich davon ausgehe, das es funktioniert, habe ich die geänderte
Version bei sourceforge hochgeladen.
#define RAMSTART 0x060
#define HEAPSTART 0x015F
#define STACK_SIZE 96
#define TIMER_REGISTER TCCR0
#define TIMER_ENABLE TIMSK
#define TIMER_VECTOR TIMER0_OVF_vect
#define CLK1 _BV(CS00)
#define CLK1024 _BV(CS02) |_BV(CS00)
Hallo *.*,
hat schon einer von Euch die Software von Tobias im AVR Studio (4.18
SP3) zum "Laufen" gebracht?
Eine Erfahrungsaustausch wäre für mich hilfreich (ggf. außerhalb des
Forums)
schneereiche Grüße
Bernd
Hallo Tobi,
hallo Olli
und *.*,
DANKE Euch für die Anteilnahme....
Das Problem ist nicht gelöst - jedoch umgangen.
Die *.c-Datei - bis auf nano_os.c - habe ich einfach von der Liste der
Sourcedateien in die Liste der Headerdateien verschoben, und schwupp,
dann werden diese *.c-Dateien auch nicht compiliert. Keine Ahnung, ob
das der eleganteste Weg ist, er funktioniert.
schneereicher werdende Grüße
Bernd
PS
Offensichtlich werden alle Sourcedateien in der obengenannten
Source-Liste kompiliert und dann fehlen einige Deklarationen, da einige
notwendige Headerdateien nicht gelesen worden sind.
es sollte reichen wenn du nur nano_os.c in der liste der zu
kompilierenden dateien hast, und die liste der header leer ist, da die
abhaengigkeiten in nanoos.c selbst aufgeloest werden.
gruss tobi
Hallo Tobi,
DANKE für Deine Nachfrage und meine Antwort ist JA.
Einige Ideen habe ich noch zum NanoOS. Wenn ich damit fertig bin, mag
ich mit Dir gerne darüber diskutieren. Deine E-Mail kenne ich ja
bereits.
DANKE und noch eine schöne Adventszeit... jetzt hier leider ohne Schnee
Bernd
Danke dir, Uwe.
Hab die Änderungen in nano_os.h übernommen und es auf sourceforge
hochgeladen.
Damit sind wir jetzt bei Version 003, und supporten folgende Hardware:
Atmega32,
AtMega88,
AtMega168
At90s8535
gruß
tobi
Hab grad mal nachgesehen..Heapstart müsste 0x0460 sein, korrekt?
Der RAM beginnt ja bei 0x0060 = 96 Dez, und endet bei 0x85F = 2143 Dez.
Berücksichtigt man den offset, ist HEAPSTART = 2143 -1024 = 0x0460 Hex.
Merke HEAPSTART ist in der Regel genau SRAM/2.
gruß
tobi
Uwe hat mir per Mail mitgeteilt, dass die Änderungen funktionieren.
Damit läuft Nano OS jetzt auf folgenden yC's:
Atmega32,
AtMega88,
AtMega168
At90s8535
Ich habs auch mal in der Code-Sammlung verlinkt.
gruß
tobi
Zur Info: Ich arbeite grad an ner Displayansteuerung für Graphic
Displays (basierend auf KS-Kontroller). Ich melde mich, wenn ich da was
habe.
gruß
tobi
Hallo Tobias,
ich habe Dein OS mit win-gcc nach Anpassung der Pfade am makefile und
den "only placebo" Userfunktionen für ein mega32 mit allen Fähigkeiten
übersetzen können. Jetzt möchte ich das natürlich mit Leben füllen...
Dazu 2 verwandte Fragenkomplexe.
1. hat sich mit der Timerproblematik noch was ergeben? Ich meine damit,
wie man genaue Timer z.B. für Servos hinbekommt, die Idle- oder Task
tauglich sind. Ich hätte auch nichts dagegen, einen 2.ten Timer dafür zu
"verschwenden" wenn dieser flexibel nutzbar ist. Ich weis nur leider
nicht, wie man das passend für das OS anstellt. Schön wäre natürlich,
wenn man dem OS sagen kann: "Wecke mich alle 20ms auf" oder "wecke Task
x in 3ms" und der Task dann z.B. in Tiefschlaf geht, also auch nicht im
normalen Scheduler geweckt wird. Eine Art Timeralarmfunktion für Tasks
also, gefüttert z.B. durch eine Eventliste. Irgendwie sowas...
2. ich möchte ein TWI Treiber für das OS bauen, der per ISR Slave mode
macht. Kann ich mir da jetzt einfach ne ISR basteln oder muss ich in
Bezug auf das OS was beachten? Wenn ja, was? Gibt es vielleicht ein
Template für ISRs so wie das User File? Ist das Messagesystem geeignet
um es für die Zeichenübertragung an/von TWI bzw. an die ISR zu
flanschen?
Wie löst man hier überhaupt systemnahe oder zeitkritische Aufgaben am
besten? Als Usertask? Und dann TASK_ENTER_CRITICAL;/TASK_LEAVE_CRITICAL;
?
Ein paar Beispiele wie man das OS mit der Hardware zusammen bringt wären
nicht schlecht, und vielleicht noch ein paar Taskhandling Funktionen
bei/für Event Steuerung würden mir helfen.
LG Rolf
So,
jetzt die versprochenen Antworten:
1.)
Du kannst einen 2. timer benutzen; Das OS selbst belegt ja lediglich
timer0.
Auch gibt es eine Funktion task_sleep_for_laps(), welche einen Task für
eine definierte Anzahl an aufrufen aus dem Scheduling nimmt. Die länge
einer solchen Aufrufrunde ist fest, wenn nicht irgendwo das Multitasking
(z.b. mit TASK_ENTER_CRITICAL) unterbrochen wird.
2.)
Du kannst mit einer ISR arbeiten. Dabei musst du allerdings bedenken,
das die ISR Interrupts und damit das Multitasking unterbricht, während
sie abgearbeitet wird.
Die abgefragten Daten kannst du in eine Message Queue schreiben und sie
von dort später wieder auslesen. Genau dafür ist das Queuing ja da.
3.)
Die Programmierung jeder Art von Aufgaben erfolgt genauso, wie bei der
Programmierung ohne Multitasking, mit dem unterschied, dass der Code
hier in einen Task verlagert wird.
Sind Aufgaben zeitkritisch, kann das Multitasking mit
TASK_ENTER_CRITICAL (unterbricht alle Interrupts) oder
MULTITASKING_DISABLE (unterbricht nur das Multitasking) unterbrochen
werden.
Im nano_os quelltext (https://sourceforge.net/projects/nanoos/
) ist in user.c ein Beispiel für eine Binäruhr enthalten, welche Tasten
per ISR abfragt, LEDs über separate Tasks steuert und Timer2 zur
Zeitberechnung nutzt.
gruß
tobi
Hallo Tobias,
das ist mir soweit klar, trotzdem suche ich eine Möglichkeit bestimmte
Tasks eventgesteuert (per Timer,INT) sofort zu wecken bzw. schlafen zu
legen wie es RT-OSe üblicher Weise anbieten - und nicht abzuwarten bis
der Scheduler den richtigen Task irgendwann weckt. Ich sehe meine
Anfrage auch als Vorschlag das OS in dieser Richtung weiter zu
entwickeln. Ich hatte mir den Source und das Uhrenbeispiel bereits
angesehen.
Aber Danke für die Antwort, ich werde sehen ob ich mit den jetzt
vorhandenen Möglichkeiten mein Ziel erreichen kann. Evtl. geht es mit
der ISR und den Queues auch.
LG Rolf
Hallo Rolf,
Dafür gibt es die Funktionen task_sleep() bzw. task_wake(), welche einen
Task schlafen legen bzw. wecken, und auch einen Taskwechsel auslösen.
Diese Funktionen sind Interrupt-fest, d.h. du kannst sie z.B. in deiner
ISR verwenden, um Tasks schlafen zu legen bzw wieder zu aktivieren.
Allerdings beeinflusst task_wake() die Reihenfolge des Schedulings
selbst nicht. Ergo kannst du einen Task sofort schlafenlegen, aber nicht
sofort wieder aufwecken. Ich habs damals nicht gebraucht, und von daher
nicht implementiert.
Dies wäre aber recht einfach implementierbar, z.B. über eine globale
Variable, in der man dem Scheduler vorgibt, welchen Task er als nächstes
anzusteuern hat.
Im Grunde müsste es sogar funktionieren, einfach active_task_id selbst
zu manipulieren, in der art
active_task_id = t-> ID -1;
innerhalb von task_wake();
Aber ich bin müde und daher ist das nur als Anregung zu sehen.
Wenn ich Zeit hab, implementier ich das gern mal. Oder du darfst es auch
gern implementieren, und ich würde es dann übernehmen, wenn du magst.
Hilft dir das weiter?
gruß
tobi
Hallo Tobias,
Danke, das hilft mir sicherlich aber ich werde Zeit brauchen um das
umzusetzen. Ich denke doch, das es dem OS viel bringen würde auch wenn
Du es vielleicht nicht selbst brauchst. Wenn man schnell auf Daten
reagieren muss (Uart mit hohen Baudraten, Encoderauswertung usw.), macht
es Sinn den betreffenden Task von der ISR aus direkt zu wecken oder man
müsste die ISR quasi "am Scheduler vorbei" viel erledigen lassen - was
wohl nicht im Sinne von ISR's und Taskswitching ist.
Ich will versuchen das OS auf einem Bot einzusetzen und da gibts erst
mal jede Menge anderer Baustellen. Danke also erst mal für die Tips.
Sollte ich es wider Erwarten vor Dir umsetzen, geb ich Dir den Code
natürlich.
LG Rolf
Hi,
ich habe die Funktionalität implementiert und getestet.
task_wake() schaltet jetzt direkt zum aktiven task um und aktiviert
diesen.
Zusätzlich gibt es eine neue Funktion task_switch(), welche zu einem
bereits aktiven Task umschaltet.
Die neue Version liegt auf Sourceforge bereit.
Anbei ein Beispiel der Binäruhr, welches task_wake() und task_sleep()
unter Einbeziehung von ISR implementiert.
gruß
tobi
Das freut mich sehr, da kann man ja echt nur den Hut ziehen.
Der Compiler nimmt es auch wie ich grade getestet habe. Damit ist das OS
nun auch echtzeitfähig.
Wau... SUPER! Danke.
LG Rolf
Da übersetzt du aber unoptimert, oder?
Und die user.c muss im Grunde komplett leer sein, mal abgesehen von den
Funktionsaufrufen selbst.
Ich meine, der reine Scheduler waren so 1200 Byte auf nem Mega168.
Ich werd demnächst mal alle footprints ermitteln, und auch den
Speicherverbrauch neu berechnen.
PS. Ich habe task_wake() nochmal geändert. Es gibt jetzt einen
zusätzlichen Parameter realtime, der steuert, ob sofort zu dem task
umgeschaltet werden soll, oder ob das Scheduling normal weiterlaufen
soll.
Ich habs auf Sourceforge hochgeladen.
Hallo Tobi,
ich habe deine aktuellen Quellen bei mir übersetzt und eine (fast) leere
user.c/.h verwendet.
Das Makefile hat noch weitere optimierungs Parameter erhalten !
atmega168
$ avr-size nano_os.hex
text data bss dec hex filename
0 744 0 744 2e8 nano_os.hex
atmega88
$ avr-size nano_os.hex
text data bss dec hex filename
0 692 0 692 2b4 nano_os.hex
atmega32
$ avr-size nano_os.hex
text data bss dec hex filename
0 712 0 712 2c8 nano_os.hex
Hallo Tobi,
den atTiny861, habe ich auch eben noch eingebaut.
Die Quelldateien sende ich Dir noch zu.
atTiny861
$ avr-size nano_os.hex
text data bss dec hex filename
0 526 0 526 20e nano_os.hex
Ich hatte -Os bzw. OPT = s
und MCU = atmega32 und sonst nur die Pfade im makefile angepasst, eine
quasi leere user.c und alle Funktionen in der nano_os.h angeschlatet.
Wie eben beschrieben. Allerings übersetzt mit der aktuellen winavr bzw.
gcc.
Mich wundern etwas eure .text Segmente mit 0 byte da bei mir dort der
Code drin liegt. Wenn ich nicht alles einschalte wie im Beispiel
vorgegeben, komme ich so auf 2,7k codesegemt. Ihr habt wohl bischen doll
optimiert oder? *lach
LG Rolf
Mit den extra Flags aus dem Makefile da, und allen bisherigen
Einstellungen komme ich auf:
Size after:
nano_os.elf :
section size addr
.text 796 0
.data 2 8388704
.bss 404 8388706
Ob der Code so stramm gezogen noch lauffähig ist, kann ich grade nicht
testen. Da aber quasi kein Usercode da ist, könnte das passen wenn der
gcc gut optimiert. Nur ist das eben auch kein realistischer Usercode.
Das Hex hat 2272 byte.
LG Rolf
Achso.. das Codesegmet liegt dort scheinbar in Data... Sachen gibts...
## Zusatz Flags
CFLAGS += -fno-inline-small-functions
CFLAGS += -fno-split-wide-types
CFLAGS += -fno-tree-scev-cprop
CFLAGS += -fno-move-loop-invariants
CFLAGS += -ffunction-sections -fdata-sections -Wl,--gc-sections
CFLAGS += -Wl,--relax
## -- ende --
Was ist von den Flags im OS zu halten? Spricht was gegen die Nutzung?
LG Rolf
Hallo Uwe,
ich brauche eigentlich nur die Einstellungen in nano_os. h für den
tiy861. Wie viel RAM/FLASH hat der denn?
Kurz zum footprint:da dies ja den reinen Bedarf des OS angeben soll,
bitte nur ohne usercode und mit verwendeten Optimizations angeben.
Ich komme mit gcc opt-level 3 auf etwa 900-2500 Byte, je nach Anzahl der
aktivierten features.
RAM-Bedarf habe ich jetzt nur grob nachgerechnet und ist auch stark von
der Anzahl der Tasks und der Feature-nutzung abhängig, aber grob lässt
sich von max. 250 Byte (alle features aktiv)
+ 9 Byte und STACK_SIZE für jeden task
+ 1 Byte für jeden Semaphor
+ 7 Byte pro Message Queue
+ x Byte für Speicherböcke, Messages usw.
ausgehen.
Der Bedarf an Rechenzeit ist natürlich vom Prozessortakt, der Anzahl und
Nutzung der Features sowie Priorität und Anzahl der Tasks abhängig.
Er bewegt sich gerechnet (also geschätzt g) im Bereich von 1% (16 MHz,
keine Featurenutzung) bis 25% (1 MHz, Features werden massiv genutzt).
gruß
tobi
Hallo Rolf
ich habe bei meine Atmel Projekten lange mit den Compiler- und
Linker-Flags gespielt, bis ich eine minimale Codegröße erreichte.
Der Link kann nun Daten und Codesegmente löschen, die nicht benötigt
werden.
Somit ist bei meinem Angaben einer Codegröße nur wirklich der Code
aufgeführt, der auch aufgerufen wird.
Hier zum Vergleich die Angaben für den atTiny861:
$avr-size nano_os.elf
text data bss dec hex filename
516 2 402 920 398 nano_os.elf
$avr-size nano_os.hex
text data bss dec hex filename
0 518 0 518 206 nano_os.hex
Hier die Makefile Erweiterung zur Optimierung:
Hallo Tobias,
also per default sind im include 4 Tasks eingetragen... (aber nicht
angelegt.. egal), dann hab ich meine Einstellungen schon genannt, -Os ,
mega32 , alle Funktionen enabled, als "usercode" die Nops aus dem
Beispiel-Template wie gepostet, und die Size wie sie dem Linker bekannt
sind mit text/bss Segmentangabe. Und dann einmal ohne Uwes Optionen und
einmal mit. Der Code ist ungetestet. Jetzt auch mit der letzten Version
incl. realtime == 1 Abfrage.
Da Du nach -O3 fragst, noch mal meine Werte für O3 statt -Os, alles
andere wie vorher.
Ohne Uwes CFLAGS
Size after:
nano_os.elf :
section size addr
.text 3720 0
.data 8 8388704
.bss 419 8388712
Mit Uwes CFLAGS
Size after:
nano_os.elf :
section size addr
.text 856 0
.data 2 8388704
.bss 404 8388706
LG Rolf
@Rolf/Uwe: Ich wär sehr daran interessiert zu erfahren, ob der
optimierte Code noch lauffähig ist.
Mein aktueller Code für einen atmega168 ist für die Binäruhr mit den
Features
-"Message Queue",
-"dynamic task management" und
-"Speichermanagement"
also
#define TASK_USE_ANHILATE
#define TASK_USE_MESSAGE
#define TASK_USE_MEM
mit dem original makefile genau 3608 byte groß:
section size
.text 3600
.data 8
.bss 0
Hi Tobias,
Ich warte auf ein Ersatzteil aber hoffe das ich gegen Ende der Woche mit
Tests beginnen kann. Ich werde auf jeden Fall meine Ergebnisse zum Thema
Optionen posten. Bedenke aber, das man für -fno-tree-scev-cprop min. den
GCC 4.3.0. braucht. Ich könnte mir vorstellen, das mancher noch ältere
gcc Versionen preferiert. Ich nutze den gcc version 4.3.3 (WinAVR
20100110)
Da der Parameter aber NO-tree-scev-cprop heisst, denke ich das es eher
negativen Einfluß hat wenn man ihn nutzt... weil er offensichtlich was
abschaltet.
Aber das nur nebenbei.
Die Compileroptionen von Uwe scheinen mir also nicht optimal zu sein.
Wenn man -fno-split-wide-types weg lässt, spart man noch mal 4 Byte im
text Segment. Lässt man -fno-inline-small-functions weg, spart man noch
mal ganze 96 byte - vermutlich schnöde pushs/pops die ggc sonst anlegt.
Weglassen von -Wl,--relax und Anderen erhöht den Code um 6 Byte - das
einzige was wirklich entscheidend auf die Codegröße einwirkt ist:
-ffunction-sections -fdata-sections -Wl,--gc-sections, das wäre also mal
genauer zu hinterfragen.
Die -OS und -O3 machen dabei auch nur Unterschiede einiger weniger Bytes
aus.
Das auch nur nebenbei.
LG Rolf
Und jetz wieder ich ;)
Habe die Anpassungen für den Tiny861 überprüft und mit aufgenommen.
Damit sind wir bei Version 0.05 und supporten folgende Prozessoren:
Atmega32,
AtMega88,
AtMega168
At90s8535
AtTiny861
Das neue File liegt wie immer auf Sourceforge.net
http://sourceforge.net/projects/nanoos/
Die Compiler-Optimierungen kann ich selbst auch frühestens am WE testen.
So lange hier nicht geprüft ist, dass der Code unter allen Umständen
funktioniert, übernehme ich sie noch nicht ins Makefile.
Noch mal zum Tiny861. Ich hab mir mal das Datenblatt angesehen. Reich
bestückt mit Timern ist er ja nicht grad...da das OS einen Timer
braucht, stellt sich die Frage, ob es sinnvoller ist, beim 861 den
Timer0 oder Timer1 zu nutzen:
-Timer 0 ist 16 Bit-fähig, aber bietet weniger Features und weniger
Compare Register
-Timer1 ist ein reiner 8-Bit-Timer (was für nano_os reicht), bietet aber
mehr features (die bei Nutzung für nano_os verloren gehen).
Wie seht ihr das?
gruß
tobi
BTW: Wer hat lust auf sourceforge einen review zu schreiben... ;)
Hallo Tobias,
danke für die Umsetzung, der atTiny861 hat eine PLL für die PWM-Kanäle
und drei PWM, die sollten erhalten bleiben.
Keine Angst mit den Linkeroptionen, ich arbeite nur damit und bisher
läuft jeder Code und alle Programme die ich damit übersetze !
Siehe: Beitrag "Jumbo-LED Uhr"
.
Hallo Tobias,
hab noch mal bischen wegen der Linkeroptions recherchiert.
Da ist im Prinzip nichts gegen einzuwenden, allerdings ist grade in
Bezug auf ISRs, Handler (anspringen über selbstgestrickten Pointer) zu
beachten, das diese nicht fälschlicher Weise vom Compiler entfernt
werden. Siehe auch:
http://www.mikrocontroller.net/articles/GCC:_unbenutzte_Funktionen_entfernen
D.h. die Flags entfernen Code auf Linkerlevel, der nicht direkt
angesprungen wird. Da der Code eh per #define configuriert wird, macht
das wenig Sinn mit den Linkerflags. Will sagen, die Fehler die man damit
provoziert und ggf. debugen muss, stehen für den normalen Anwender in
keinem Verhältnis zum Gewinn an Bytes da man denn unbenutzten Code auch
anders und risikoärmer entfernen kann. Es würde nur was bringen wenn man
aus einem Funktionspaket wie Messaging zwar eine Funktion nutzt aber den
Rest raus haben will.
In Einzelfällen mag das angebracht sein, allgemein würde ich das strikt
ablehnen zumal es auch um so weniger bringt, je mehr Funktionen man
aktiv nutzt. Eine feinere Granulierung von #define würde da ohne die
Fehlerquote anzuhheben mehr nutzen aber selbst da ist fraglich ob sich
der Aufwand wegen ein paar Byte lohnt. Ich sehe das nicht so.
Selbstgeschriebene Programme enthalten auch selten unbenutzen Code, aber
wers braucht... wirds sich schon selbst ins makefile einbauen können :)
Das einzige was ich für mich gern nutzen würde ist CFLAGS +=
-Wl,--relax aber auch das scheint avr-ld wie bei -Wl,--gc-sections
zumindest nach avrfreaks.net nen Bug zu haben. @Uwe, deine Beteuerung in
Ehren...aber nen einzelnes Programm ist was anderes als ein OS - das
Leute ggf. nutzen ohne sowas noch mal zu verifizieren. Tobias tut gut
daran, sowas konservativ zu sehen.
Da Du den Mega32 schon drin hast, kannst du glaube ich auch den Mega16
noch direkt einbauen, so weit mir bekannt hat der nur einfach bissel
weniger Speicher. 16k Flash, Ramstart ist 0x60 und Ramend 0x45F, also
1KB Ram, sonst baugleich zum mega32. Ob das OS auf nem mega8 Sinn
macht... keine Ahnung.
LG Rolf
Hallo @all,
Ich denke auch, das ich das Makefile zunächst einmal so lasse wie es
ist.
Zusätzlich zu den von rolf angeführten Bedenken frage ich mich auch,
inwieweit Funktionen, welche über Pointer addressiert werden (wie z.B.
die Tasks selbst) "wegoptimiert" werden, da der Compiler deren Aufruf
schlicht nicht erkennt, und sie somit für überflüssige Funktionen hält.
gruß
tobi
Ups...vergessen:
Ich muss auch ehrlich gestehen, dass ich mich mit den Optimierungen des
gcc nicht so gut auskenne, auch von daher bin ich damit lieber erstmal
vorsichtig.
Zum Mega16...kannst du das in Hardware verifizieren? Ich habe aktuell
leider keine Mega16 da.
Der Mega8 ist auch sehr interessant!
gruß
tobi
Hi,
habe den Mega8/16 mit aufgenommen und auf sourceforge hochgeladen.
Auch gibts jetzt eine Fehlermeldung, wenn ein unbekanntes device
verwendet wird, und ich habe den Parameter "STACK_SIZE" ausgelagert, da
er vom verwendeten Device unabhängig ist.
Ab jetzt gibt es dort auch ein changelog und die "alten" releases als
Historie.
Damit sind wir bei Version 0.06
gruß
tobi
hacker-tobi schrieb:> [..] Wird noch irgend was benötigt [..]
Benötigt nicht unbedingt, aber eine Portierung auf die AVR-XMega-Serie
fände ich echt gut.
hacker-tobi schrieb:> @Rolf/Uwe/anybody ;)>> Gibts news? Wie weit sind eure Entwicklungen? Wird noch irgend was> benötigt oder gibts bugs?
Vielleicht könnte man mal das includieren von *.c files rausnehmen. Oder
gibt es einen vernünftigen Grund dafür?
Hallo @all
Hm... neues gibts wenig - mir fehlt etwas die Zeit aber das gibt sich
hoffentlich. Zum Thema .c includieren, ich hab da kein Problem mit und
hätte ich eins, würd ich mir vielleicht die includierten c-files nach .h
umbenennen und gut is. Was ich jedoch anregen möchte ist eine kleine
Internetpräsenz für das OS. Muss ja nicht mal umfangreich sein aber es
würde sicherlich mehr Aufmerksamkeit geben und man kann auch besser die
"Fan-Gemeinde" betreuen und bei Bedarf ausbauen.
Sich die Facts hier in dem Thread zusammen zu suchen ist zwar auch ok
aber besser ginge das sicherlich strukturiert auf einer Webseite. Is
aber nur eine Idee denn ich hab keine Ahnung, wie viel Dir an der
Verbreitung des OS gelegen ist bzw. wieviel Zeit Du da investieren
kannst/willst.
Ich hoffe, ich komme in den nächsten 2 Wochen dazu, das i2c an das OS zu
flanschen.
LG Rolf
Hi,
das Thema c-Files includieren gab es oben irgendwo schonmal.
Ich lasse das bis zum nächsten major Release so wie es ist, denn es
funktioniert problemlos, und ich hab momentan ehrlich gesagt keine Lust,
da jedes File nochmal anfassen zu müssen.
Wenn nochmal ein major Release ansteht, nehm ich es in dem Zug aber mit
auf.
Eine Internetpräsenz gibt es doch:
http://sourceforge.net/projects/nanoos/
Dort findet man alle Files, eine kurze Erläuterung sowie die Features,
einen Bugtracker und release Notes.
Auch Erfahrungsberichte können dort hinterlassen werden, worum ich jeden
herzlich Bitte!
Zum Thema mit den c Files Includieren, das hab ich gelöst. siehe Anhang
Wenn ihr es verwenden wollt ok, der svn ist ja noch leer ;-)
sonst weg damit.
Compilieren tut es mit WinAVR (gcc 4.3.3) und auch MVHTools (gcc 4.5.2)
viel spass
Hallo,
Ich sehe mir gerade die Änderungen von Achill an.
Ich bekomme hier 2 Warnungen, das
init_user_environment() und shutdown_user_environment()
keine Prototypen wären, durch ein
#include "nano_os.h"
#include "user.h"
in user.c lässt sich das umgehen. Dann hab ich in nano_os.h die Zeilen:
//+++++++++++++++++++++GLOBAL DEFINE+++++++++++++++++++
/* set in Makefile !
...
*/
gefunden, im Makefile werden sie nicht gesetzt, auch im Makefile von
Sourceforge tauchen sie nicht auf. Es leuchtet mir zwar der Sinn ein,
die Defines projektabhängig ins eigene Makefile zu packen aber dann
sollten die auch im Beispiel makefile - ggf. auskommentiert -
auftauchen, oder?
Ich hab mir das Ganze jetzt noch im AVR Studio 4 geladen und es scheint
alles gut. Leider bin ich mit meinem Projekt noch nicht viel weiter
gekommen.
Ich bin auf den Grafiktreiber gespannt
LG Rolf
Hi,
ich wolltemal hören,wie der Stand der NanoOS-Projekte so ist.
Zwischendurch bin ich etwas weitergekommen; Das Display-board ist
fertig. Aktuell sitze ich grad an dem Treibermodul.
gruß
tobi
Welchen Vorteil bringt ein solches Multitasking-OS auf so kleinen
Controllern, welche Art von Anwendungen sollen es sein die ein solches
voraussetzen? Ist die klassische Programmierung via Interrupts nicht
viel effektiver? Ein Timer-Interrupt für periodische Aufgaben und
diverse Geräteschnittstellen-Interrupts sind sehr viel sparsamer und
auch schneller, ersparen oft genug sogar ein eigenes Hauptprogramm als
dritter Arbeitsebene. Der große Overhead eines solchen OS, die ständigen
Datenkopieraktionen zur Registersicherung erzeugen vor allem eines:
Wärme...
Hallo Max,
entschuldige die späte Antwort. Ich hab das OS damals geschrieben, um zu
beweisen, das es geht. Praktische Anwendung hat es bei mir z.B. in Form
von Multifunktionsuhren gefunden, bei denen mehrere Tasks gleichzeitig
abgearbeitet werden (z.B. Erfassung der Position, Auslesen von
Infrarotdaten usw für eine Propelleruhr).
Da das OS auch cooperative Multitasking beherrscht, kann ein Task bei
Bedarf auch beliebig lang laufen, oder Rechenzeit vorzeitig abgeben, was
es sehr flexibel macht.
Zusätzlich bestehen Kommunikationsmöglichkeiten, wie z.B. Semaphore.
Auch komplexere Architekturen, wie z.B. Treiber mit einheitlicher
Schnittstelle wären denkbar.
gruß
tobi
Nach langer Zeit geht es weiter.
Zunächst einmal habe ich den Code nur auf die aktuelle AVR-LIBC
angepasst.
Dafür waren nur wenige Anpassungen notwendig.
Derzeit denke ich über weitere Funktionen nach, z.B. counting Semaphore.
Besteht denn von anderer Seite Interesse oder Badarf?
Falls ja schreibt einfach.
gruß
tobi
Hey!
Hab jetzt in der Vielzahl der Threads keinen Download oder Link zur
Veröffentlichung deiner Diplomarbeit gefunden. Gibt es diesen schon,
hast du deine Diplomarbeit bereits veröffentlichen können?
Würde mich sehr freuen, wenn ich deine Arbeit lesen könnte!
Grüße
M
hacker-tobi schrieb:> Die user - Software ist hiervon> ausgenommen.
Das geht nicht. Wenn die lib GPL ist dann muss alles was dagegen gelinkt
wird ebenfalls unter die GPL fallen.
Nimm lieber die LGPL mit zusätzlicher static linking exception Klausel
(zum Beispiel so wie die Runtime von FreePascal lizenziert ist, denn die
wird auch statisch gelinkt, aber die damit gelinkten Anwendungsprogramme
sollen in jedem Falle unberührt von jeglicher Lizenz bleiben.
Lizenzwahl ist nicht ganz ohne und Du solltest das genau bedenken um
nicht den potentiellen Anwendern unnötige Steine in den Weg zu legen,
ihnen Rechtsunsicherheiten oder andere Kopfschmerzen zu bereiten.
Hi zusammen,
das Thema ist 6 Jahre alt.
@Mathias: Ich wüßte nicht mal mehr, ob ich die Arbeit veröffentlichen
dürfte. Die habe ich vor etwa 5 Jahren abgegeben. Das müßte ich erst bei
der Hochschule erfragen und der Aufwand erscheint mir etwas zu hoch,
zumal ich dort keinerlei Kontakte mehr habe.
@Bernd:
"Solltest du den Code des OS selbst verändern, wäre eine Meldung
(hacker-tobi@gmx.net) nicht schlecht. Die user - Software ist hiervon
ausgenommen."
Das bezog sich glaube ich darauf, das er mir nicht mitteilen braucht,
wenn er die User Software anpasst. Ansonsten hast du aber recht .