hallo!!
ich möchte einen thread im programm starten, hat mir jemand ein kleines
codebeispiel wie so ein thread aussehen muss, wie ich ihn starte und was
ich sonst noch so alles dafür brauche(includes prototypen usw.)?
controller ist ein attiny2313, falls es jemanden interessiert :~)
dank euch schonmal :)
Threads hast du, wenn dein Betriebssystem dir welche anbietet.
Falls du eines hast ... :-)
Auf einem AVR wirst du das in aller Regel von Hand bauen müssen
mit Interrupts - siehe Tutorial.
Klaus Wachtler schrieb:> Auf einem AVR wirst du das in aller Regel von Hand bauen müssen> mit Interrupts - siehe Tutorial.
interrupts sind kein problem, das tutorial habe ich auch schon fast ganz
durch. möchte einen 2ten thread parallel zum hp starten der mir dann zb
was einliest oder so.
simon schrieb:> möchte einen 2ten thread parallel zum hp starten der mir dann zb> was einliest oder so
und genau das macht mit mit interupts, dafür braucht man keine Threads.
heinzhorst schrieb:> Multitasking
genau das ist das stichwort :)
wie stelle ich es bem avr an??
die abarbeitung meines programms soll "parallel" erfolgen, also ein
interrupt scheidet aus.
simon schrieb:> die abarbeitung meines programms soll "parallel" erfolgen, also ein> interrupt scheidet aus.
mach es am besten so wie es die meisten leuten auf einem Amtel machen,
also mit interupts. Man sollte auf einem µC nicht wie auf einem PC
programmieren, threads sind nicht immer die beste wahl.
Εrnst B✶ schrieb:> Musst also nur die Einzelaufgaben in kleine Stückchen zerlegen, und die> jeweils abwechselnd ausführen.
das war mal meine ursprüngliche idee, wenn ich jetzt aber (nur
beispielhaft) zb eine led blinken lassen möchte im thread 1 (also
irgendwas prozessor blockierendes) und mit dem 2ten thread zb einen
taster einlesen möcht (blödes beispiel :), dann sollte ich ja schon
echtes multithreading betreiben.
Auf einem Prozessor mit nur einem Kern gibt es kein "parallel".
Es gibt höchstens ein "quasi parallel", indem laufend zwischen
den Dingern umgeschaltet wird, die du "Thread" nennst.
Und das musst du auf einem AVR von Hand programmieren, und
dazu brauchst du Interrupts.
Wenn du echte Threads (die das für dich irgendwo versteckt dann
auch machen), brauchst du ein Betriebssystem - und wahrscheinlich
einen etwas kräftigeren Prozessor.
simon schrieb:> das war mal meine ursprüngliche idee, wenn ich jetzt aber (nur> beispielhaft) zb eine led blinken lassen möchte im thread 1 (also> irgendwas prozessor blockierendes) und mit dem 2ten thread zb einen> taster einlesen möcht (blödes beispiel :), dann sollte ich ja schon> echtes multithreading betreiben.
nein auch dafür braucht man das nicht, die LED kann schön von interupt
geblinkt werden dafür muss auch nichts blockieren.
Klaus Wachtler schrieb:> Wenn du echte Threads (die das für dich irgendwo versteckt dann> auch machen), brauchst du ein Betriebssystem - und wahrscheinlich> einen etwas kräftigeren Prozessor.
geht es nicht das ich zwei threads vom hp aus starte?
das es nicht wirklich parallel ist, ist mir klar :)
simon schrieb:> Klaus Wachtler schrieb:>> Wenn du echte Threads (die das für dich irgendwo versteckt dann>> auch machen), brauchst du ein Betriebssystem - und wahrscheinlich>> einen etwas kräftigeren Prozessor.>> geht es nicht das ich zwei threads vom hp aus starte?> das es nicht wirklich parallel ist, ist mir klar :)
@peter: war ja nur ein beispiel :)
wenn jetzt die led über einen längeren zeitraum blinkn soll und ich
währenddessen was anderes machen möchte wie stelle ich das an,
interrupts sollten ja nicht ewig laufen!
simon schrieb:> wenn jetzt die led über einen längeren zeitraum blinkn soll und ich> währenddessen was anderes machen möchte wie stelle ich das an,> interrupts sollten ja nicht ewig laufen!
i++;
if ( i == 100 ) {
LAMPE_AN
}
if ( i == 200 ) {
LAMPE_AUS
i = 0;
}
Interrupt regelmäßig auslösen und jedes Mal LED-Port
setzen/zurücksetzen.
Alles andere läuft im Hauptprogramm und wird nur für das
Setzen/Rücksetzen unterbrochen.
Wenn du auf ein AVR mit threads Arbeiten willst, wirst du selber denn
Thread Wechsel Programmieren müssen. Das Läuft im Allgemeinen darauf
hinaus das du einen Timerinterrupt hast der regelmäßig kommt und ein
Scheduling auslöst das deine thread ggf umschaltet, ob sich das bei ein
Tiny2313 wirklich Lohnt ist fraglich, aber eine schöner Zeitvertreib.
Zumal man dann ganz schnell solche Sachen wie Priotäten und Semaphore
will. Dann Kommt man auf Problem wie Priotätsinversion etc. Das Ganze
ist ein schönes aber nicht Trivialesfeld um zu verstehen wie
Betriebsysteme Ticken.
Ich wünsch echt viel Erfolg wenn du dich da hinein Arbeiten willst,
allerdings Driftest du da schnell vom Hundertstel ins Tausendstel.
Benutz mal die Suche,ich meine wir hatten vor ein paar Wochen eine
Diskussion hier im Forum wo jemand seine Arbeit zu denn Thema Tasks &
AVR vorgestellt hat. Vielleicht Hilft dir das ein Anfang zu finden.
Mann, da hab ich ja was losgetreten...
Für das Blinken on LEDs braucht man keine Interrupts zu verschwenden. Ob
eine LED dabei ein paar ms früher oder Später eingeschaltet wird ist
Sch**ßegal.
Also erstmal ganz zum Anfang. Prinzipiell sollte mal seine Firmware für
eine bessere Portierbarkein und wiederverwertbarkeit von einmal
erstelltem Quellcode modular aufbauen. Jedes Modul bekommt seine eigene
Quellcode und Headerdatei. Darüber hinaus hat jedes Modul:
- Initialisierungsfunktion
Hier werden alle Aufgaben abgeaubeitet, die Das Modul beim Booten
erledigen Muss, z.B. Variablen und Register mit Startwerten vorbelegen,
Initialisierung der Hardware, etc.
- Task
Hier werden alle zyklisch auszuführenden Aufgaben abgearbeitet, z.B.
Werde von externem Sensor abholen, Werte von ADC abholen. Der Task darf
nicht durch das Warten auf irgendein Ereignis oder durch Zeitschleifen
blockiert werden.
- IO-Funktionen
Die IO-Funtionen dienen zur Kommunikation der Module untereinander.
Beispiel: Der im Taskabgefragte Wert aus dem ADC wird durch eine
IO-Funktion den anderen Mudulen zur Verfügung gestellt.
So. Nun zurück zum Multitasking. Die Main ruft nacheinander alle
initialisierungsfunktionen auf. Danach läuft sie in eine Endlosschleife,
in der nacheinander die Tasks der einzelnen Module abgearbeitet werden.
Das sieht dann so aus:
simon schrieb:> das klingt gut, aber wird so nicht jeder task zyklisch abgearbeitet und> darauf dann der nächste gestartet?
Wenn jeder Task nur kurz genug ist, ist das ja kein Problem.
Das Zeitscheiben Prinzip ist simpel, aber oft auch ausreichend.
Messaufgaben, Tastenabfragen, ... können so z.B. alle 10ms aufgerufen
werden und Display-Ausgaben alle 0,5s.
Da wird auch nur ein Timer benötigt, also echt resourcenfreundlich.
Du musst nur darauf achten, dass sie einzelnen Tasks nicht länger dauern
als die Aufrufe.
Task_1ms(void)
{
CheckAlarmFlags();
}
Task_10ms(void)
{
ReadInPuts();
ReadADC();
}
Task_100ms(void)
{
ToggleLEDs();
HandleWatchdog();
}
Task_1s(void)
{
RefreshDisplay();
}
Wenn Dein Timer z.B. einen 10ms-Takt generiert und alle weiteren
(langsameren) Zeitscheiben von der 10ms-Zeitscheibe abgeleitet werden,
darf die Summe aller Abarbeitungszeiten in allen Zeitscheiben nicht mehr
als 10ms betragen.
Ansonsten überschreitest Du den 10ms-Basistakt und verlässt die
Echtzeitfähigkeit. Andersrum sind die Zeitpunkte der Abarbeitung der
einzelnen "Tasks" in den Zeitscheiben sowieso von der Abarbeitungszeit
der restlichen vorher durchlaufenen "Tasks" abhängig und verschiebt sich
daher ständig ein wenig hin und her.
Je nach Implementation würdest Du dann einen 10ms-Zyklus vergessen oder
die 10ms-Zeitscheibe nach Durchlauf sofort wieder starten.
Ist aber beides nicht sinnvoll. Beim ersten wie auch beim zweiten würde
Dein grobes Timing nicht mehr vorhersagbar sein.
Eine Ausnahmebehandlung bei Zeitüberschreitung sollte daher immer
vorhanden sein.