Forum: Mikrocontroller und Digitale Elektronik tasks freertos


von Bernie (Gast)


Lesenswert?

Gibt es beim FreeRtos auf dem stm32 die Möglichkeit einen Task zu 
starten, nur einmal auszuführen und diesen wieder zu stoppen?
Jeder Task hat da irgendwie eine for(;;) (Endlosschleife) drin, was ja 
bedeuten würde, dass dieser eigentlich immer läuft, auch wenn dieser 
nicht benötigt wird.

Oder verstehe ich etwas falsch?
Ich möchte lediglich einen Befehl einmal ausführen.

Geht das denn irgendwie?

von pitschu (Gast)


Lesenswert?

Das ist kein Problem. Du machst eben keine for oder while loop, sondern 
führst deine Sachen aus und verlässt die Task über xTaskDelete().

pitschu

von moep (Gast)


Lesenswert?

Gehen tut das natürlich schon, wobei ich behaupten würde, dass das für 
ein Embedded-System eher untypisch ist - hier hat man eher 
wiederkehrende Aufgaben (was nicht heißen soll, dass es nicht vorkommen 
kann).

Es gibt ja auch Alternativen dazu hierfür eine Task anzulegen und direkt 
wieder zu beenden (es gibt nämlich durchaus auch einige RTOS die kein 
Anlegen von Task zur Laufzeit erlauben).

Bernie schrieb:
> Oder verstehe ich etwas falsch?
> Ich möchte lediglich einen Befehl einmal ausführen.

Aus Interesse: Was möchtest du denn genau ein mal machen?

von Bernie (Gast)


Lesenswert?

Danke euch

Ich möchte das einfach nur testen und mich da mal einarbeiten.
Ich hätte jetzt einfach mal nur mal eine Led im Task eingeschaltet, um 
zu sehen, ob das so funktioniert wie ich das möchte.

Wo gibt es denn eine Art Anleitung wo das ein Bisschen beschreibt? Im 
Reference Manual oder dem Datenblatt finde ich das ja nicht.

Ich weiss so ja auch nicht, welche Befehle es wie zB xTaskDelete() gibt?
Wo steht denn das alles?

von moep (Gast)


Lesenswert?

Bernie schrieb:
> Wo gibt es denn eine Art Anleitung wo das ein Bisschen beschreibt? Im
> Reference Manual oder dem Datenblatt finde ich das ja nicht.

Das mit dem Task nur einmal ausführen? Gute Frage... die Beispiele 
werden wie von dir schon gesagt fast alle eine Endlos-Loop nutzen, da 
das wie gesagt deutlich gebräuchlicher ist.


Bernie schrieb:
> Ich weiss so ja auch nicht, welche Befehle es wie zB xTaskDelete() gibt?
> Wo steht denn das alles?

Sowas findest du in der API reference 
[http://www.freertos.org/a00106.html].

Bernie schrieb:
> Ich möchte das einfach nur testen und mich da mal einarbeiten.
> Ich hätte jetzt einfach mal nur mal eine Led im Task eingeschaltet, um
> zu sehen, ob das so funktioniert wie ich das möchte.

Gehen wird das natürlich schon :)
Wie gesagt wird man aber in der Realität kaum Aufgaben haben die 
wirklich nur ein einziges mal laufen (irgendwann wird man die LED z.B. 
auch wieder abschalten wollen).
Die LED-Task könnte dann z.B. auf eine Semaphore warten, so lange bis 
wieder ein Zustandswechsel ansteht.

von Bernie (Gast)


Lesenswert?

ok, andersrum gefragt:
Was ist wenn zB eine Anweisung in einem Interrupt durchgeführt wird und 
die Anweisungen aber nacheinander zu lange benötigen würden. Ich meine 
also, der nächste Interruptaufruf steht schon vor der Tür, bevor dieser 
im vorigen Schritt fertig war. Das geht dann immer weiter so bis zu 
einem Absturz.
Das sind dann auch Anweisungen, die nicht immer durchgeführt werden 
müssen.
Da ist doch so ein Task genau das was man brauchen kann. Einmal starten 
und fertig. Dann kann der Interrupt sogar mehrmals kommen und man müsste 
ja mit einer globalen Variable nur immer abfragen, ob der Task fertig 
ist oder nicht.. super
Aber mit einer Endlosschleife??
Wie macht man es dann?
Das wäre mal sicher ein Fall, der nicht immer durchgeführt werden muss.

von Jay (Gast)


Lesenswert?

Hallo,

kommt etwas drauf an, um was für einen Interrupt es sich handelt und 
welche Informationen du haben möchtest.
Für die viele Interrupts kann man z.B. ne Queue verwenden ( 
http://www.freertos.org/a00018.html ) um Daten zwischen Interrupt und 
einem Thread hin und her zu schaufeln. Für ein Beispiel schau mal 
http://www.freertos.org/a00118.html .
Als Beispiel evt. UART: Der UART-RX Interrupt wird aufgerufen. Das 
empfangene Byte wird in die Queue geschrieben. Das kann eventuell öfter 
hintereinander passieren. Irgendwann kommt dann der Lesethread dazu die 
Daten aus der Queue wieder auszulesen und weiter zu verarbeiten.

Wenn du nur einen Thread informieren möchtest, dass ein Interrupt 
stattgefunden hat (z.B. GPIO Interrupt wird durch einen Tastendruck 
ausgelöst) kannst du einen Binary Semaphore verwenden: 
http://www.freertos.org/a00113.html

Gruss,
Jay

von moep (Gast)


Lesenswert?

Bernie schrieb:
> Aber mit einer Endlosschleife??
> Wie macht man es dann?

Du solltest dich mal in die Mittel zur Task-Synchronisation und 
-Kommunikation einlesen (Semaphoren, Mutexe, Events, Queues/Mailboxes).
Alle deine Beispiele werden dadurch eigentlich abgedeckt.

Das Prinzip ist immer ählich. Die "Endlosschleife" wartet am 
Schleifenbeginn auf ein Signal. So lange ist der Thread blockiert und 
wird nicht ge-scheduled (erzeugt also keine CPU-Last).
Sobald das Signal kommt läuft die Schleife ein mal durch und wartet dann 
wieder am Schleifenanfang. Es ist also keine "echte" Schleife im Sinne 
davon, dass sie dauernd im Ring läuft.

Pseudocode:
1
void TaskLoop()
2
{
3
  for(;;)
4
  {
5
    waitForSignal(); // this blocks the task
6
7
    DoSomething();
8
  }
9
}
10
11
void IrqHandler()
12
{
13
  sendSignal(); // tell the task to run one loop cycle
14
}

So kann der Interrupt auch "mehrmals" bzw "zu oft" kommen. So lange das 
"DoSomething" noch durchläuft passiert eben nix.

Bernie schrieb:
> Das wäre mal sicher ein Fall, der nicht immer durchgeführt werden muss

Mag sein. Trotzdem kommen die Anweisungen zyklisch und immer wieder. 
Hier jedes mal einen neuen Task zu erzeugen generiert einen riesen 
Overhead.

von Bernie (Gast)


Lesenswert?

moep schrieb:
> Bernie schrieb:
> Aber mit einer Endlosschleife??
> Wie macht man es dann?
>
> Du solltest dich mal in die Mittel zur Task-Synchronisation und
> -Kommunikation einlesen (Semaphoren, Mutexe, Events, Queues/Mailboxes).
> Alle deine Beispiele werden dadurch eigentlich


Danke vielmals

Kennt da jemand eine zusammenfassende Seite, eine empfehlenswerte.

von Reginald L. (Firma: HEGRO GmbH) (reggie)


Lesenswert?

Einfach mal auf die freertos Website die API Referenz anschauen. Die ist 
sehr überschaubar und sind immer Beispiele mit dabei.

Beim stm-port musst nur aufpassen mit den prios und timeouts.

von guest (Gast)


Lesenswert?

moep schrieb:
> Hier jedes mal einen neuen Task zu erzeugen generiert einen riesen
> Overhead.

Nicht nur das. Es wird auch jedes Mal der Stack für den Task neu 
alloziert und wieder beim Löschen freigegeben. Dadurch kann zur Laufzeit 
eine Fragmentierung des RAM entstehen und man bekommt evtl irgendwann 
keinen Speicher mehr.

Auf Embedded Systemen ist man gut beraten ein möglichst statisches 
Memorymap im RAM zu haben. Z.b. beim Start alles allozieren was man 
braucht und dann bleibt das so. Am besten auf dynamische 
Speicherverwaltung verzichten.

Fehler, die irgendwann nach Wochen zur Laufzeit auftreten sind übel zu 
debuggen.

von Darth Moan (Gast)


Lesenswert?

Moin,

guest schrieb:
> Nicht nur das. Es wird auch jedes Mal der Stack für den Task neu
> alloziert und wieder beim Löschen freigegeben.

Ist das bei freertos wirklich so?
Das freertos kenne ich bisher nicht, aber das waere ja (aus meiner
nicht objektiven Sicht) ein KO Kriterium.
Bisher kannte ich das immer so, das (fuer embedded) alle task fest
konfiguriert sind. Natuerlich kann man die nach belieben starten,
terminieren und neu starten. Aber da ist nix mit dynamischer
Speicherverwaltung. Alles ist statisch allokiert.

Ist das bei freertos generell anders, oder ist das nur eine
Konfigurationsmoeglichkeit unter anderen?

MfG,
Darth

von Ruediger A. (Firma: keine) (rac)


Lesenswert?

Darth Moan schrieb:
> Moin,
>
> guest schrieb:
>> Nicht nur das. Es wird auch jedes Mal der Stack für den Task neu
>> alloziert und wieder beim Löschen freigegeben.
>

Ab FreeRTOS 9 kann man Speicher für Objekte (z.B. Stack) präalloziiert 
übergeben (sh. http://www.freertos.org/xTaskCreateStatic.html). Default 
ist dass FreeRTOS es für einen tut.

von Markus F. (mfro)


Lesenswert?

Darth Moan schrieb:
> Ist das bei freertos wirklich so?

Das ist sicherlich bei jedem System so, das dynamisch zur Laufzeit Tasks 
neu anlegen und wieder löschen kann. Wenn die Task selbst ein dynamisch 
erzeugtes Objekt ist, wie kann da der Stack dazu statisch sein?

Daß man es bei einem mickrigen µC damit nicht allzusehr übertreiben 
sollte, sollte allerdings auch klar sein.
Da ist es sicher besser (wie ja schon geschrieben wurde), die Tasks beim 
Programmstart fest an und (wenn man sie gerade nicht braucht) 
zwischendurch schlafen zu legen.

von Darth Moan (Gast)


Lesenswert?

Moin,

Markus F. schrieb:
> Das ist sicherlich bei jedem System so, das dynamisch zur Laufzeit Tasks
> neu anlegen und wieder löschen kann. Wenn die Task selbst ein dynamisch
> erzeugtes Objekt ist, wie kann da der Stack dazu statisch sein?

Naja, wie ich schon schrieb, wird die Task Konfiguration als const
Datenstruktur gelinkt. Die Task IDs sind somit feste IDs, die ggf. in
entsprechenden header Files exportiert werden. Das heisst, man kann
dann eben nicht beliebeige Tasks selbst mit zur Laufzeit ermittelten
StartAdressen erzeugen. Das braucht man ja embedded eigentlich auch
nicht.
Ich kann mich nicht mehr an alle OS erinnern, aber Nucleus und
jetzt OSEK sind komplett statisch konfiguriert. Trotzdem kann man die
Tasks beliebig starten und terminieren. Wie es eben gebtraucht wird.
Alle ASIL belasteten Task muessen genau so aufgezogen sein (also sie
muessen sich nach einem Durchlauf selbst terminieren). Da wird zB im
1ms, 10ms, 100ms der zugehoerige Task neu gestartet. Sollte er
allerdings vom letzten Start noch nicht fertig geworden sein, gibts
eine doppelte Task Aktivierung.
Schwerer Fehler -> Sicherer Zustand.

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.