Parallel Programmieren

Gast #1948107
Lesenswert?

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 :)
Gast #1948150
Lesenswert?

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.
Gast #1948151
Lesenswert?

Ε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.
#1948152
Lesenswert?

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.
Gast #1948153
Lesenswert?

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.
Gast #1948159
Lesenswert?

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 :)
#1948165
Lesenswert?

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.
Gast #1948176
Lesenswert?

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.
Gast #1948203
Lesenswert?

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
}
Gast #1948950
Lesenswert?

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();
}
Gast #1952356
Lesenswert?

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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren