Forum: Mikrocontroller und Digitale Elektronik Betriebssysteme der Fluch der Menschheit?


von verzweifelter Programmierer (Gast)


Lesenswert?

Hi Zusammen

Ich versuche gerade eine Projeckt mithilfe eines
Echtzeitbetriebssystems auf die Beine zu stellen, mit mäsigem Erfolg.
Anfangs lief es wirklich gut und ich kam schneller vorran als erhofft
aber um so komplexer das Programm wird um so häufier kommen Bugs die
ich absolut nicht nachvollziehen kann. Simulieren fällt leider weg, das
AVR Studio packt das mit dem Betriebssystem nicht mehr. Im Augenblick
habe ich eine ganz konkretes Problem und hoffe ihr habt eine Idee woran
das liegt.
Folgendes, das Programm läuft nahezu feherfrei bis ich auf die
unverschämte Idee komme eine einzige zusätzliche int Variable zu
deklarieren. Ich poste nur mal den einen Auszug, das gesammte Programm
ist viel zu Groß.
So Funktioniert noch alles weitgehend:
...
void display (void)  // Display anzeige Task
{
char text_buffer[21];
char stat;
int i =0;
...

Und so hängt sich das Programm bei der eingabe einer Taste sofort auf:

void display (void)  // Display anzeige Task
{
char text_buffer[21];
char stat;
int i =0;
int e;

Die Variable e wird nirgens verwendet und wird mit Sicherheit an dieser
Stelle zum ersten mal deklariert. Ich hätte nun die Vermutung das ein
Speicher oder Stacküberlauf der Grund sein könnte nur wie finde ich das
raus? Wie gesagt, Simulieren ist nicht...soll ich das von "Hand"
ausrechnen oder wie könnte ich den Fehler ergründen?

Danke für eure Ideen!

Gruß

von miwitt001 (Gast)


Lesenswert?

Anscheinend machst du das ganze ja mit AVRs. Ich weiß zwar nicht welchen
Compiler du benutzt, aber falls du WinAVR verwendest, da gibts ein
Programm namens avr-size.exe. Das zeigt die Code und Speicher-Göße an
bzw wie viel noch frei ist. Bei google gibts noch etwas namens
avr-sizex.exe, das gibt das ganze dann schön als Prozentsatz der noch
frei is an. Geht aber nur mit WinAVR, bzw avr-gcc.
mfg Michael

von wolli (Gast)


Lesenswert?

Ich benutze eigentlich immer ein LCD zum debuggen. Du kannst Dir z.B. ab
und zu den Stackpointer ausgeben lassen. Allerdings wollen die
Zeitpunkte dieser Ausgaben wohl überlegt sein, sonst macht der uC
nichts anderes mehr.

Prinzipiell sollte man aber vorher einschätzen, wie tief die Rekursion
in einem Programm ist.

von genauso namenlos (Gast)


Lesenswert?

hi,
wär schon angenehmer wenn Du Deinen Namen posten würdest !!

Aber mach mal was "Ordentliches":

http:\\www.e-lab.de

Was erwartest Du denn von dem Chaos, das ein C-Compiler
zuläßt ???

<dito> Gruß

von verzweifelter Programmierer (Gast)


Lesenswert?

@Michael: Ich benutze CodeVisionAVR zum compilieren. Ich habe mir schon
die informationen nach dem compiliervorgang nagekucjt aber nichts
auffälliges gefunden. Villeicht seht ihr da etwas das nicht passt:
6030 line(s) compiled
No errors
1 warning(s)

Bit variables area: 2h to 2h
Bit variables size: 1 byte(s)

Data Stack area: 100h to 4FFh
Data Stack size: 1024 byte(s)
Estimated Data Stack usage: 68 byte(s)

Global variables area: 500h to 71Eh
Global variables size: 543 byte(s)

Hardware Stack area: 71Fh to 10FFh
Hardware Stack size: 2529 byte(s)

@wolli
"Prinzipiell sollte man aber vorher einschätzen, wie tief die
Rekursion in einem Programm ist."
Theoretisch schon richtig, aber mit einem Betriebssystem ist das nicht
so einfach nach zu vollziehen was es wann auf den Stack legt.

von verzweifelter Programmierer (Gast)


Lesenswert?

@genauso namenlos:
"wär schon angenehmer wenn Du Deinen Namen posten würdest !!"
Markus Kempf - fühlst du dich jetzt besser?

"Aber mach mal was "Ordentliches":
http:\\www.e-lab.de"
Also bevor ich fast 500€ für noch mehr verbugte Software ausgebe kauf
ich mir lieber ein JTAG ICE debugger. Wobei ich im Augenblick nicht
wüsste wo ich als armer Technikerschüler soviel Geld hernehmen sollte.

"Was erwartest Du denn von dem Chaos, das ein C-Compiler
zuläßt ???"
Natürlich ist mir klar das jeder Compiler unötiges und unsauberes
Produziert aber was ist die alternative? Alles in Assembler zu proggen?
Assembler ist auch kein allerheilmittel gegen Bugs, das haben wir erst
diesen Dienstag wieder festgestellt als wir in Automatisierungstechnik
ne einfache RS232 kommunikation Programmiert haben und 2 Stunden nach
Fehlern suchten.
Ach noch was...Weisheiten bringen mich nun gar nicht weiter, trotzdem
danke!

von Fiffi (Gast)


Lesenswert?

Hallo,

Um welches Betriebssystem handelt es sich denn ?

Pack das ganze Projekt (inkl. hex und map files) doch mal in den
Anhang, sonst können wir nur raten ...


Gruß

Fiffi

von Peter Kasi (Gast)


Lesenswert?

Also irgendwie hab ich in erinnerung das ein Betriebssystem
normalerweise für jeden Task seinen eigenen Stack anlegt, also sollte
die Stackgröße min. so groß sein wie für den einzelnen Task notwendig.
Bei einem Taskwechsel werden zusätzlich noch die Register mit auf den
Stack gelegt, aber mehr sollte da eigentlich nicht passieren. Also wenn
du deinen Task wie eine selbständige main-Routine betrachtest, solltest
du auch abschätzen können wie groß der Stack sein sollte.
Aber das kann ja bei deinem OS alles ganz anders sein, also schau mal
in die Doku, ob sich jemand darüber auslässt.......

Gruß
Peter

von Stefan Kleinwort (Gast)


Lesenswert?

Ich schreibe ans Stackende eine Sequenz, die ich dann im Timer-IR
regelmässig teste. Läuft der Stack über, ist die Sequenz überschrieben,
und ich kann entsprechend reagieren: während der Entwicklung mit einer
Warnmeldung, im fertigen Produkt mit einem Watchdog-Reset.

Ich habe auch den JTAG-Debugger und kann den nur empfehlen. Es gibt
auch Nachbauprojekte, die preislich sehr günstig kommen (habe ich aber
noch nicht probiert).

Welches Betriebssystem verwendest Du?

Stefan

von ingo (Gast)


Lesenswert?

Hall Leute,
ich hätte da mal ne ziemlich DUMME FRAGE:

Wenn der Fehler erst nach der Deklaration der Variablen "e"
aufgekommen ist und das Programm vorher stabil lief, warum stellt Ihr
die Leistung des Compilers in Frage????
Kann es nicht vielmehr sein, das die Variable "e" vom Betriebsystem
für die Funktion "e hoch x" als Konstante (2,71828.....) vordefiniert
ist und das System durch die erneute Deklaration ins "trudeln"
kommt??????

GRUSS
INGO

von Peter D. (peda)


Lesenswert?

Wie schon oben gesagt wurde, muß ja ein Multitaskingsystem extrem
verschwenderisch mit Speicher umgehen, da es ja jeden Prozeß
vollständig sichern muß, bevor es auf einen anderen umschalten kann.

Beim Main-Loop Prinzip laufen die Programmteile echt nacheinander, d.h.
es wird nur soviel Speicher benötigt, wie ihn der größte Prozeß
benötigt.

Beim Multitasking läuft zwar auch alles hintereinander ab, aber vom
Compiler aus gesehen gleichtzeitig, da die Taskumschaltung ja völlig
willkürlich erfolgt.
Deshalb muß er notgedrungen "maximalen Speicherverbrauch einer Task"
* "Anzahl der Tasks" reservieren also Unmengen mehr.

Und in Deinem Fall wird warscheinlich für jede Task eine maximale
Speicherbelastung von 24 Byte reserviert. Und beim 25 Byte krachts dann
eben.


Da MCs aber relativ wenig Speicher haben und die Taskumschaltung auch
einen erheblichen Anteil an Rechenzeit benötigt, wird Multitasking auf
MC sehr selten verwendet.
Eher bei kleinen Aufgaben, wo insgesamt nicht viel Speicher gebraucht
wird, der MC-Typ also reichlich überdimensioniert ist.


Der Nachteil der Main-Loop Methode ist ja, daß die einzelnen Prozesse
laufzeitfreundlich geschrieben werden müssen, d.h. nicht in einer
riesen Delay-Loop verhungern dürfen, sondern bei ungenutzer Rechenzeit
selber zum main() zurückkehren müssen.
Wenn man sich aber erstmal daran gewöhnt hat, so zu programmieren, sind
die Programme sogar echtzeitiger (schneller) als ein Echtzeit-OS.


Peter

von Stefan Kleinwort (Gast)


Lesenswert?

Hallo Peter,

könntest Du mal genauer erklären, mit welchem Multitasking-System Du
persönlich so schlechte Erfahrungen hast? Oder kann es sein, dass Du
das alles nur vom Hörensagen kennst?

Stefan

von verzweifelter Programmierer (Gast)


Lesenswert?

Ok,
danke für eure beteiligung an meinem Problem aber ich hab es soeben
gelöst.
Es lag wirklich am Stackspeicher. Ich habe heute morgen nocheinmal
konzentriert die gesammte Doku des PR_RTX der Firma Progressive
Resources LLC durchgeshen und eine Möglichkeit gefunden die Stackgröse
für jeden Task anzupassen. Ich habe dann die Stackgröse für den Task
mit der zusätzlichen Variable "e" um einige bytes erhöht und das
Problem war behoben.
Ich entschuldige mich für meinen übereilten Post aber ich war nach
einem langen Programmiertag einfach etwas frustriert und musste das
irgendwo loswerden.

Gruß Markus.

von Peter D. (peda)


Lesenswert?

@Stefan

"könntest Du mal genauer erklären, mit welchem Multitasking-System Du
persönlich so schlechte Erfahrungen hast?"

Ich hab doch nirgends was von schlechten Erfahrungen gesagt.
Es gib ja einen Haufen verschiedene OS.

Wenn jenes, welches Markus verwendet, die Vergrößerung des Speichers
für jeden Task einzeln gestattet, dann stimmt in diesem konkreten Fall
meine obige Formel natürlich nicht mehr.
Das ändert aber grundsätzlich nichts an der Tatsache, daß wesentlich
mehr Speicher benötigt wird.

Und das macht dann auch die Programmierung nicht gerade einfacher, wenn
man sowas machen muß, um ein Progamm wieder zum Laufen zu bringen.


Peter

von Gunter (Gast)


Lesenswert?

Hi @all,

>Wie schon oben gesagt wurde, muß ja ein Multitaskingsystem extrem
>verschwenderisch mit Speicher umgehen, da es ja jeden Prozeß
>vollständig sichern muß, bevor es auf einen anderen umschalten kann

>Beim Main-Loop Prinzip ...

da muß ich auch mal eine Lanze für den o.a. AVRco brechen:

der unterscheidet zw. Prozessen und Tasks.
Ein Task ist das, was Peter als "Main-Loop"-Programm bezeichnet.
Es gibt also für ALLE Tasks nur eine Umgebung. Der Task muß natürlich
sicherstellen, daß er innerhalb seiner erlaubten Zeit (einstellbar
mittels Prioritäten) fertig wird. Sonst wird er abgebrochen.

Jeder Prozess läuft "immer im Kreis rum". D.h. für JEDEN Prozeß wird
beim Unterbrechen die gesamte Umgebung gesichert und -wenn der Prozeß
wieder dran ist- die Umgebung wieder hergestellt und er wird dort
fortgesetzt wo er unterbrochen wurde.

Man kann sich -je nach Teilaufgabe- das geeignete Konzept wählen. Das
finde ich optimal.

@Markus:
zieh Dir von E-Lab mal das Tutorial. Da ist gleich am Anfang der
Verweis auf ein Beispiel, das mit der freien (eingeschränkten)
Version erstellt wurde. Alleine schon damit kann man sehr viel
machen.
Außerdem gibt es auch noch eine Spezialversion für den Mega8 für
(IIRC) EUR 25,-. Bislang hat die für meine Projekte immer mehr als
genügt.

Und unschätzbar wertvoll ist m.E. der Support im Forum.
Bei Problemen (auch bei Verständnis-Schwierigkeiten) hilft Dir der
Chef-Programmierer persönlich. Und - wenn Du mal einen Bug entdeckst:
Du bekommst ein paar Stunden später per Mail eine korrigierte Version
des Compilers und am nächsten Morgen steht diese für alle zum Down-
load bereit.

Für Stack-Probleme gibt es übrigens einen Simulator. Da kannst Du
alle möglichen Kombinationen testen und Dir dann eine Statistik
anschauen, die für jeden Task/ Prozess div. Werte anzeigt(Rechenzeit /
max. Stack Verbrauch etc.).

Bevor jetzt falsche Vermutungen aufkommen:
ich werde NICHT von E-Lab bezahlt.  ;-)
Ich bin nur von dem AVRco und dem Support restlos begeistert.
Deshalb auch nochmal der Link: www.E-Lab.de

Schöne Grüße
Gunter

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.