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.
Ok, Grundlangen der Mikrocontroller - Firmwareentwicklung. Weist du, was "kooperatives Multitasking" ist? Wenn nein - goolen und durchlesen.
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. in main:
1 | while(1) { |
2 | mach_ein_bischen_was_von_thread_a(); |
3 | mach_ein_bischen_was_von_thread_b(); |
4 | }
|
Musst also nur die Einzelaufgaben in kleine Stückchen zerlegen, und die jeweils abwechselnd ausführen.
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; }
zb so
1 | volatile uint8_t led_soll_blinken; |
2 | |
3 | interrupt service routine |
4 | {
|
5 | if( led_soll_blinken ) |
6 | schalte LED in den anderen Zustand |
7 | }
|
8 | |
9 | int main() |
10 | {
|
11 | |
12 | setze timer so auf, dass die interrupt service routine |
13 | regelmässig aufgerufen wird |
14 | |
15 | while( 1 ) { |
16 | |
17 | if irgendwas |
18 | led_soll_blinken = 1; |
19 | |
20 | if irgendwas anderes |
21 | led_soll_blinken = 0; |
22 | }
|
23 | }
|
In dem Moment, in dem du '_delay_ms' denkst, bist du schon falsch. Das wird dann nichts mehr.
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.
super, ich danke euch für die tollen antworten! ich weiß es wird nicht ganz trivial, aber mir geht es um den aha effekt :))
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:
1 | void main(void){ |
2 | |
3 | // initialisation
|
4 | |
5 | modu1_1_init(); |
6 | modu1_2_init(); |
7 | modu1_3_init(); |
8 | ...
|
9 | modu1_n_init(); |
10 | |
11 | // endless loop
|
12 | |
13 | while(1){ |
14 | |
15 | modu1_1_task(); |
16 | modu1_2_task(); |
17 | modu1_3_task(); |
18 | ...
|
19 | modu1_n_task(); |
20 | |
21 | }
|
22 | }
|
das klingt gut, aber wird so nicht jeder task zyklisch abgearbeitet und darauf dann der nächste gestartet? grüße und danke schon mal!
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.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.