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?
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
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?
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?
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.
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.
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
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.
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.
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.
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.
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
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.
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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.