Multitasking mit AVR

#2399756
Lesenswert?

Klar geht das...

Jeder Task bekommt seinen eigenen Stack und dann gehts los:
1. Alle Register in zu Anfang der ISR auf den Stack sichern: SREG, 
R0-R31
2. Dann den Stackpointer sichern
3. Den Stackpointer auf den nächsten Task ändern
4. Alle Register zurücksichern
5. Rücksprung mit reti

Schau dir mal den FreeRTOS-Port an, da solltest du fündig werden.

MfG
Marius
#2399760
Lesenswert?

Eine Möglichkeit wäre z.B. folgendes:

Du hast eine Sturktur, in der Platz für alle 32 Register, SP und PC ist. 
Diese stellt den Zustand eines Threds dar. Dann gibt es eine Liste von 
Zeigern auf diese Sturkturen, mit in deinem Fall 3 elementen, so wie 
einen Index, der immer auf das momentan verwendete Element zeigt.

In der ISR liest du den Index aus und speicherst alle Register, SP und 
PC in den aktuellen Eintrag. Dann wird der Index erhöht (FIFO-Prinzip) 
und zeigt auf den nächsten auszuführenden Thread. es werden dann alle 
Register aus der Sturktur gelesen, der SP gesetz sowie der gespicherte 
PC als letzes auf den Stack gelegt. Mit einem reti wird dann "zurück" in 
den nächste Task gesprungen. usw...

Jeder Thread muss natürlich einen eigenen Stack haben.

MfG Mark
#2399776
Lesenswert?

chris schrieb:
> Zur Übung würde ich gerne ein sehr kleines Multitasking System bauen. Es
> soll nichts weiter tun, außer zwischen 3 Tasks im Millisekundentakt
> wechseln.
>
> Wie kann man in einer Timer ISR den Kontext-Switch realisieren?

Multitasking heisst noch lange nicht Kontext-Switch. Kooperation ist 
nicht nur im Leben sondern auch bei kleinen uCs besser, siehe Artikel 
Multitasking
Gast #2399811
Lesenswert?

Vielen Dank erst mal für eure Antworten.
>Jeder Task bekommt seinen eigenen Stack und dann gehts los:
1
// neuen Stack erzeugen 
2
// aber wie?
3

4
  task1(); // task1 mit neuen Stack starten
5

6

7
void task1()
8
{
9
 while(1)
10
 {
11
  tuewas();
12
 }
13
}

Bei machen C-Kompilern gibt es einen Parameter und einen Call-Stack.
Gast #2400098
Lesenswert?

Danke für die Links. Leider bin ich mit der Beantwortung der Frage, wie 
man vor dem Call einer Funktion einen neuen Stack-Bereich anlegen kann, 
nicht weitergekommen. Vielleicht weiß von euch jemand, wie man so etwas 
macht.
#2400105
Lesenswert?

Es wird z.B. im Sourcecode von FreeRTOS und auch uc/OS-II gut gezeigt.
Es wird in den anderen vielen kleineren RTOS sicher auch zum "Nachlesen" 
drinstehen.
Einfach nur versuchen das nachzuvollziehen.
Hier im Thread wurden auch schon Lösungen gezeigt. Ach ja, ohne 
Assembler wird es nicht gehen.
#2400153
Lesenswert?

Bei FreeRTOS findest du das erzeugen des Stacks
in der Datei port.c in einem AVR-Port directory.
Z.B: FreeRTOS\Source\portabe\GCC\ATMegaxxx\port.c

pxPortInitialiseStack heißt die Funktion, die z.B. von 
xTaskGenericCreate() in tasks.c aufgerufen wird.

Der Context-Switch selber findet in vPortYieldFromTick() in port.c 
statt.

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