Hallo zusammen
ich stehe vor folgendem Problem:
Ich habe hier ein FreeRTOS am laufen mit 3 Tasks.
1
functionA
2
{
3
PrüfeObBufferzumSchreibenaufSDvollist.
4
WennJa,StopRequest=1;
5
}
6
7
8
TaskA
9
{
10
11
warteBisDatenInQueueA
12
{
13
VerarbeiteDaten.
14
GibIDausQueueAinQueueBein.
15
16
if(StopRequest&&QueueAleer)
17
{
18
give(SemaphoreWriteSD);
19
}
20
}
21
}
22
23
TaskB
24
{
25
26
if(StopRequest==0)
27
{
28
warteBisDatenInQueueB
29
{
30
FunctionA()
31
VerarbeiteDaten.
32
GibtIDvonQueueBzurückinQueueA
33
}
34
}
35
}
36
37
38
TaskC
39
{
40
TakeSemaphore(SemaphoreWriteSD);
41
{
42
SchreibeaufSD....
43
StopRequest=0;
44
}
45
}
Nun, wie ihr seht, koordiniere ich die Tasks mit einer externen
variabel.
Diese habe ich als
1
uint8_tStopRequest
definiert.
Unklücklicherweise, tritt nach ca. 2-3 Stunden (kein exakter Zeitpunkt)
der Fall ein, dass die Variabel stehts auf 1 ist, der TaskC welcher nach
dem Schreiben die Variabel auf 0 setzen würde, aber nie augerufen wird.
Da sich alle Programmzustände nach ca. 30 Sekunden wiederholen, gehe ich
hier von einer Eigenheit des Schedulers aus.
Deshalb die Frage an euch, darf man überhaupt, so wie hier versucht,
Tasks synchronisieren? Müsste die Variable als volatile definiert
werden?
Ich habe keine Semaphoren verwendet, weil ich nicht wirklich sehe, wie
sich dies mit diesen elegant lösen liesse.
Hoffe auf eure Inputs.
Danke
Stefan K. schrieb:> Und wann und wo wird functionA aufgerufen?>> Gruß, Stefan
Sorry, habs ergänzt.
Arduino F. schrieb:> Holger K. schrieb:>> Müsste die Variable als volatile definiert>> werden?>> Preemptives Multitasking?> Dann garantiert: Ja!
#define configUSE_PREEMPTION 1
Dann lags wohl an dem!
Aber noch kurz zur Grundsatzfrage.
Ist es legitim solche dinge über eine Variable zu steuern, oder sollte
man strikt Semaphoren verwenden?
volatile hilft Dir in diesem Fall NICHT! Wenn die Zuweisung
StopRequest = 1
nicht atomar übersetzt werden kann, sind beim preemptiven Multitasking
immer Szenarien (race Konditionen) denkbar, in denen die Variable nicht
den Wert der gedachten logischen Folge hat. volatile Deklaration
garantiert keinen atomischen Zugriff!
Prinzipiell ist das Vorgehen aber legitim. Du kannst alle Zugriffe auf
die Variable unter Mutexkontrolle vornehmen, oder aber je nach
verwendetem Prozessor atomare Operationen nutzen (beim Cortex gibt's
z.B. den exclusive access monitor, der über die Maschinenbefehle ldrex
und strex arbeitet).
In meinem Buch diskutiere ich die Problematik ausführlich in Kapitel 6.
Ich weiss, es fängt mir selber an, auf den Senkel zu gehen, wiederholt
auf mein eigenes Buch zu verweisen, aber die Problematik ist recht
weitreichend, so dass eine vollständige Diskussion hier den Rahmen
sprengen würde.
Ruediger A. schrieb:> nicht atomar übersetzt werden kann, sind beim preemptiven Multitasking> immer Szenarien (race Konditionen) denkbar, in denen die Variable nicht> den Wert der gedachten logischen Folge hat. volatile Deklaration> garantiert keinen atomischen Zugriff!
Hat auch tatsächlich nicht funktioniert.
Ruediger A. schrieb:> In meinem Buch diskutiere ich die Problematik ausführlich in Kapitel 6.> Ich weiss, es fängt mir selber an, auf den Senkel zu gehen, wiederholt> auf mein eigenes Buch zu verweisen, aber die Problematik ist recht> weitreichend, so dass eine vollständige Diskussion hier den Rahmen> sprengen würde.
Das stimmt wohl.
Ich verwende einen Cortex M3.
Da du der Community ja nahe bist, und ich das Problem möglichst Zeitnah
lösen sollte, wärst du eventuell so freundlich und würdest mir einen
Tipp geben, wie ich dies in diesem Fall lösen könnte?
Soll ich für den Zugriff auf die Variabel einen Mutex erstellen?
Danke und Gruss
Ruediger A. schrieb:> StopRequest = 1>> nicht atomar übersetzt werden kann, sind beim preemptiven Multitasking> immer Szenarien (race Konditionen) denkbar, in denen die Variable nicht> den Wert der gedachten logischen Folge hat. volatile Deklaration> garantiert keinen atomischen Zugriff!
kannst du das bitte etwas genauer erklären?
Wie kann eine 8bit Variable nicht atomar beschrieben werden? Es geht mir
nur ums setzen der Variabel nicht um abfrage und dann setzen.
Holger Kraehe schrieb:>> Da du der Community ja nahe bist, und ich das Problem möglichst Zeitnah> lösen sollte, wärst du eventuell so freundlich und würdest mir einen> Tipp geben, wie ich dies in diesem Fall lösen könnte?>
Sieh Dir mal diesen Funktionssatz an:
http://gcc.gnu.org/onlinedocs/gcc-4.4.5/gcc/Atomic-Builtins.html
der übersetzt plattformspezifisch atomisch.
> Soll ich für den Zugriff auf die Variabel einen Mutex erstellen?>
wie gesagt ist das eine Alternative für den Fall, dass die
Nichtatomarität das Problem ist. "Soll" ist eine etwas ungünstige
Formulierung. Du MUSST etwas tun, was das Problem löst, und die
Entscheidung, was das ist, liegt bei Dir. Wenn Du etwas tun SOLLST, dann
deswegen, weil Dir ein Vorgesetzter das sagt. Da ich in deinem Projekt
in keinster Form involviert bin, kann ich Dir nicht sagen, was Du tun
sollst, ich kann nur versuchen, Dir Hilfestellung bei der Entscheidung
zu geben, was Du tun MUSST (wobei die Entscheidung am Ende des Tages bei
Dir liegt, was auch voraussetzt, dass Du nach Bestem Wissen und Gewissen
sagen kannst, dass Du WEISST, wo das Problem ist).
Dein Ansatz ist falsch; eine schnelle Lösung (also eine Lösung die so
aussieht also ob sie funzt) ist bei der Nebenläufigkeit selten eine
funktionierende Lösung. Vielleicht verzögert eine schnelle, auf den
ersten Blick funktionierende Lösung das Fehlerbild nur so, dass der
Fehler statt also 20 Minuten nur noch alle 14 Tage auftritt, d.h. nach
Bestehen der internen Tests und Rollout im Feld. Einfach nur zu sagen
"jetzt ist es eine halbe Stunde nicht mehr aufgetreten, also Problem
gelöst" hat so manche Firma in die Pleite getrieben. Bei Fehlern in
nebenläufigen Architekturen muss man sich schon mit spiztem Bleistift
und viel Papier hinsetzen und alle möglichen Raceszenarien trocken
durchspielen, bis man sich sicher ist, dass man weiss warum. DIE Arbeit
wird sich hier auf dem Forum sicherlich Niemand für Dich machen.
Peter II schrieb:> Ruediger A. schrieb:>> StopRequest = 1>>>> nicht atomar übersetzt werden kann, sind beim preemptiven Multitasking>> immer Szenarien (race Konditionen) denkbar, in denen die Variable nicht>> den Wert der gedachten logischen Folge hat. volatile Deklaration>> garantiert keinen atomischen Zugriff!>> kannst du das bitte etwas genauer erklären?>> Wie kann eine 8bit Variable nicht atomar beschrieben werden? Es geht mir> nur ums setzen der Variabel nicht um abfrage und dann setzen.
Hallo Peter,
Cortex Prozessoren arbeiten grundsätzlich im Load-and-Store Modus (ich
bin mir sicher, dass Du das weisst), also ist das Setzen einer Variable
egal welcher Grösse grundsätzlich eine mindestens zwei Instruktionen
umfassende (also nicht atomische und damit unterbrechbare) Operation.
Der EAM umschifft dieses Problem, muss aber halt explizit genutzt
werden.
Ich stimme mit deinem Punkt überein, dass die Atomizität in dem Fall,
dass kein Set-und-Test involviert ist, vermutlich keine Rolle spielen
sollte; ich habe nur grundsätzlich auf die Frage geantwortet, wo es
Probleme mit der Synchronisation über globale Variablen geben kann (und
den Irrweg mit der volatile Annahme aufgegriffen).
Möglicherweise ist eine andere Racekondition Schuld an der Inkonsistenz
als die einer unterbrochenen Zuweisung; wie ich schon vorher schrieb,
muss man dafür die möglichen Kontrollpfade sehr genau analysieren. DIE
Arbeit kann einem Niemand abnehmen.
Stefan K. schrieb:> Ich nehme mal an, in den Tasks gibt es noch while(1) Schleifen?> Wie ist die Priorität der Tasks?>> ...>> Falls TaskB eine höhere Priorität als TaskA hat, kann TasksB hier in> einer Endlosschleife laufen, wenn (StopRequest == 1).>> Gruß, Stefan
Sehr guter Punkt; hier könnte man ein vTaskDelayUntil() andenken, um
sicherzustellen, dass die Anderen Tasks eine Chance bekommen.
Interessanterweise könnte eine Mutexlösung hier durch die Priority
Inversion Policy das Problem lösen, aber aus Anderen Gründen als man
denkt. Deswegen ist nebenläufige Programmierung niemals durch
trial-and-error richtig zu bewältigen.
Holger Kraehe schrieb:> Bei mir haben alle Tasks die selben prioritäten.>> Ich habe nun folgendes implementiert:>> An allen stellen, wo ich auf die Variable zugreife.>
1
>xSemaphoreTake(xStopProcessMutex,portMAX_DELAY);
2
>stopProcess=1;
3
>xSemaphoreGive(xStopProcessMutex);
4
>
>>>> Leider hat sich das System erneut aufgehängt.
Installiere mal den tracealyzer von percepio, der integriert sehr gut
mit FreeRTOS. Du wirst offensichtlich nicht drumrumkommen zu verstehen,
wie dein System als Ganzes funktioniert, und dabei hilft die
Visualisierung enorm.
Ruediger A. schrieb:> Installiere mal den tracealyzer von percepio, der integriert sehr gut> mit FreeRTOS. Du wirst offensichtlich nicht drumrumkommen zu verstehen,> wie dein System als Ganzes funktioniert, und dabei hilft die> Visualisierung enorm.
funktioniert der auch in Atollic?
Tracealyzer von Percepio ist eigentlich nicht mehr zu empfehlen. Es gibt
da eine bessere Variante von SEGGER. Nennt sich SystemView:
https://www.segger.com/systemview.html
FreeRTOS wird auch unterstützt und die große Vorteil gegenüber Percepio
ist das es völlig kostenlos ist!!
Ansonsten überlege dir doch mal anstatt FreeRTOS ein kommerzielles RTOS
einzusetzen, z.B. embOS von SEGGER. Dann bekommst du direkt Support und
Training vom Hersteller und bist nicht hier auf das Forum angewiesen. Im
Endeffekt sparst du damit Zeit und Geld.
Karl schrieb:> Tracealyzer von Percepio ist eigentlich nicht mehr zu empfehlen. Es gibt> da eine bessere Variante von SEGGER. Nennt sich SystemView:> https://www.segger.com/systemview.html
Was genau benötige ich, um den Tracealyzer zum laufen zu bekommen?
Genügt eine SWD Verbindung zum Controller?
Ich vermute dass ich dafür einen Segger J-Link benötige?
Karl schrieb:> Tracealyzer von Percepio ist eigentlich nicht mehr zu empfehlen.
? Warum nicht und speziell warum nicht MEHR?
> Es gibt> da eine bessere Variante von SEGGER. Nennt sich SystemView:> https://www.segger.com/systemview.html>
Was ist daran besser?
> FreeRTOS wird auch unterstützt und die große Vorteil gegenüber Percepio> ist das es völlig kostenlos ist!!>
? Tracealyzer gerade für FreeRTOS war und ist kostenlos (habe gerade
nochmal mit der HP gecheckt)!
> Ansonsten überlege dir doch mal anstatt FreeRTOS ein kommerzielles RTOS> einzusetzen, z.B. embOS von SEGGER. Dann bekommst du direkt Support und> Training vom Hersteller und bist nicht hier auf das Forum angewiesen. Im> Endeffekt sparst du damit Zeit und Geld.
Damit würde ich übereinstimmen. Es gibt nichts umsonst; wenn Du "freie
Software" einsetzt, bezahlst Du Anders als mit direkten Kosten (eine
Binsenweisheit, die erst langsam in die Köpfe eindringt). Segger ist
sicherlich eine gute Wahl, es gibt aber z.B. auch kommerzielle Derivate
von FreeRTOS, falls man auf das FreeRTOS Modell nicht verzichten will.
Holger Kraehe schrieb:> Bei mir haben alle Tasks die selben prioritäten.
In diesem Fall: ist Time-Slicing aktiviert?
Aus: FreeRTOS -> Task Priorities:
Any number of tasks can share the same priority. If
configUSE_TIME_SLICING is not defined, or if configUSE_TIME_SLICING is
set to 1, then Ready state tasks of equal priority will share the
available processing time using a time sliced round robin scheduling
scheme.
Ich bin mir ziemlich sicher, dass Du Dir ein DeadLock-Problem eingebaut
hast. Leider ist Deine Code-Beschreibung nicht ganz exakt
(while(1)-Schleifen fehlen, etc...), als dass man dieses Problem daraus
wirklich erkennen kann.
Insgesamt bin ich mittlerweile der Meinung, dass zur
Intertask-Kommunikation ausschliesslich die Mechanismen verwendet werden
sollten, die vom FreeRTOS zur Verfügung gestellt werden. Das hat nicht
nur den Vorteil, dass Fragen wie Atomar j/n erst gar nicht aufkommen.
Auch das Debuggen mit Tools wie dem von Rüdiger erwähntem tracealyzer
wird dadurch konsistenter.
Viele Grüße, Stefan
Ruediger A. schrieb:> Karl schrieb:>> Tracealyzer von Percepio ist eigentlich nicht mehr zu empfehlen.>> ? Warum nicht und speziell warum nicht MEHR?
Ich meinte nicht mehr seitdem es SystemView gibt. Mir persönlich gefällt
das besser. Ich glaube auch nicht das es Percepio noch lange geben wird.
Wieso sollten Kunden für deren einziges Produkt bezahlen wenn es das in
besser von Segger kostenlos gibt? Der Percepio Stand auf der EW2017 war
recht überschaubar ;-).
Ruediger A. schrieb:> Was ist daran besser?
Ich finde die Darstellung einfacher zu verstehen. Bei Percepio finde ich
das eher unübersichtlich. Außerdem basiert SystemView auf RTT, d.h. dort
können deutlich mehr Trace Daten übertragen werden und beeinflußen
weniger das Target.
Holger Kraehe schrieb:> Was genau benötige ich, um den Tracealyzer zum laufen zu bekommen?>> Genügt eine SWD Verbindung zum Controller?> Ich vermute dass ich dafür einen Segger J-Link benötige?
Meinst du jetzt Tracealyzer oder SystemView? SystemView funktioniert
natürlich perfekt mit dem J-Link aber es geht auch ohne, dann ist es nur
nicht mehr so komfortabel, geht aber auch. Ich habe das z.B. schon auf
einem RL78 benutzt und da gibt es kein JTAG.
Danke für eure Antworten
Ich habe nun die Sourcefiles aus dem Zip SystemView_Src_V242.zip in mein
Projekt includiert.
Habe _ARM_ARCH_7M_ global definiert, damit überall CM3 ausgewählt
wird.
Ich verwende einen STM32F105RBT6
Ich habe zudem #define SYSVIEW_RAM_BASE (0x20000000) gesetzt,
da laut Datenblatt ab dort das RAM beginnt.
FreertosConfig.h ist im Anhang.
Der Code wir compiliert.
Er warnt nur dass gewisse defines, redefines sind. Siehe Bild im anhang.
Leider findet der SystemView keinen RTT Block.
Muss ich den Code auf dem Controller noch irgendwie "Starten"?
Ich gehe zu 98% davon aus, dass du kein Sync-Problem sondern ein
Logik-Problem hast.
Was ist, wenn TaskA das Flag immer auf 1 setzt? (Gewöhnlicherweise
füllen MCU Puffer deutlich schneller als externe Peripherie ihn leert)
Was ist, wenn die SD Semaphore nicht freigegeben wird, weil nur 1
Bedingung war ist?
Ist der Pseudocode überhaupt identisch zum C-Code?
Zudem solltest du den den TaskC über Events/Notifications steuern.
mfg
Felix F. schrieb:> Ist der Pseudocode überhaupt identisch zum C-Code?
Ja ist er.
Felix F. schrieb:> Zudem solltest du den den TaskC über Events/Notifications steuern.
Ich hab den doch über eine Semaphore gesteuert.
Oder wie würde das anderst gehen?
Holger Kraehe schrieb:> Nun findet SystemView einen RTT Block.> Aber Bei Timeline steht nur Unified. Und sonst nichts.
Welche FreeRTOS Version benutzt du? Das FreeRTOS muss ja dafür
instrumentiert sein, das es die Trace Daten in den RTT Buffer schreibt.
Das sollte aber im SystemView Manual beschrieben sein.
SystemView manual "8.3.1 Configuring FreeRTOS for SystemView":
The patch file Sample.2.3_Core.patch shows the required modifications of
the FreeRTOS 8.2.3 source and the GCC/ARM_CM4F port. It can be used as a
reference when using another version or port of FreeRTOS. I.e. if
another port than GCC/ARM_CM4F is used, the traceISR_ENTER(),
traceISR_EXIT(), and traceISR_EXIT_TO_SCHEDULER() calls have to be added
accordingly.
Hast du das Patch File benutzt?
Karl schrieb:> Welche FreeRTOS Version benutzt du?
8.2.3
Karl schrieb:> Hast du das Patch File benutzt?
Ja, hab ich angewendet und habe FreeRTOS_TRace auf 1 gesetzt.
Das Patchfile ersetzt ja die Tracefunktionen von FreeRTOS mit jenen aus
dem SystemView.
Ich habe jedoch einen CM3. Daher sieht mein Port anderst aus.
Aktuell kann ich im SystemView Record klicken und es tut irgenwas, Daten
sehe ich allerdings keine. Wenn ich dann auch stop clicke und dann auf
Read Recorded Data, kommt "0 Bytes received"
So, nun tut das ganze etwas mehr.
Es zeigt mir nun die SysTick interrupts an (Sehr viele halt)
Ein Problem bleibt aber noch bestehen.
Jenes mit dem "Redefined defines".
Hat jemand einen Tipp?
Irgendwie muss ich es hinkriegen, dass zuerst die Defines vom
SystemView.h definiert sind anstellen von jenen des FreeRTOS.
Also, SystemView läuft.
Für jene welches interessiert, ihr müsst
#include "SEGGER_SYSVIEW_FreeRTOS.h"
In der FreeRTOSConf.h hinzufügen!
Leider sehe ich in SystemView meine Semaphoren nicht.
Zudem scheint es masslos überforert zu sein mit meinen events.
Holger Kraehe schrieb:> Bei mir haben alle Tasks die selben prioritäten.>> Ich habe nun folgendes implementiert:>> An allen stellen, wo ich auf die Variable zugreife.>
1
>xSemaphoreTake(xStopProcessMutex,portMAX_DELAY);
2
>stopProcess=1;
3
>xSemaphoreGive(xStopProcessMutex);
4
>
>>>> Leider hat sich das System erneut aufgehängt.
Gibt es da irgend eine Behandlung der Timeout-Situation?
Carl D. schrieb:> Holger Kraehe schrieb:>> Bei mir haben alle Tasks die selben prioritäten.>>>> Ich habe nun folgendes implementiert:>>>> An allen stellen, wo ich auf die Variable zugreife.>>> xSemaphoreTake(xStopProcessMutex,portMAX_DELAY);>> stopProcess = 1;>> xSemaphoreGive(xStopProcessMutex);>> >>>>>>> Leider hat sich das System erneut aufgehängt.>> Gibt es da irgend eine Behandlung der Timeout-Situation?
Nein, ich gehe davon aus, dass ich irgendwan Zugriff erhalte, da die
Tasks gleichberechtigt sind.
Anbei sind die TraceDaten.
Ab 02:23 ist das system gekippt, und die Variable permanent auf 1
Holger K. schrieb:> Carl D. schrieb:>> Holger Kraehe schrieb:>>> Bei mir haben alle Tasks die selben prioritäten.>>>>>> Ich habe nun folgendes implementiert:>>>>>> An allen stellen, wo ich auf die Variable zugreife.>>>> xSemaphoreTake(xStopProcessMutex,portMAX_DELAY);>>> stopProcess = 1;>>> xSemaphoreGive(xStopProcessMutex);>>> >>>>>>>>>> Leider hat sich das System erneut aufgehängt.>>>> Gibt es da irgend eine Behandlung der Timeout-Situation?>> Nein, ich gehe davon aus, dass ich irgendwan Zugriff erhalte, da die> Tasks gleichberechtigt sind.
Aha, Prinzip Hoffnung, das ist dann der Moment , in dem der Windows-PC
einen Restart braucht.
Gibt es eigentlich einen Plan welche Tasks, welche (geshared-ten)
Resourcen welche Funktion haben sollen. Bisher sieht das von außen eher
nach Extreme Progamming aus.
FreeRTOS hatte früher mal ein schönes Tutorial, mit schönen Beispielen,
das man sich genauer zu Gemüte führen sollte. Denn daß da keine
Jahrzente RT-Erfahrung am Werk sind, merkt man auch. Ist auch nicht
schlimm, jeder fängt halt mal an.
Carl D. schrieb:> Holger Kraehe schrieb:>> Bei mir haben alle Tasks die selben prioritäten.>>>> Ich habe nun folgendes implementiert:>>>> An allen stellen, wo ich auf die Variable zugreife.>>
>>>>>>>> Leider hat sich das System erneut aufgehängt.>> Gibt es da irgend eine Behandlung der Timeout-Situation?
Bei dem Code sollte ein Timeout beim Take unnötig sein, weil der durch
die Mutex geschützte Code die besitzende task nicht suspendieren kann.
In einem wie von Stefan geschilderten Lockout Szenario bei unendlicher
CPU bound Taskschleife würde diese Task auch gar nicht erst dran kommen,
könnte also auch nicht timeouten.
Allerdings war ja die Idee der fehlenden Atomizität in diesem Fall eh
eine geistige Sackgasse; man kann also die Mutex komplett wieder
entfernen und anfangen, einen anderen Baum hochzubellen.
Holger, Du solltest wirklich mal Dir die Zeit nehmen, Multithreading
etwas besser konzeptuell zu verstehen, dann hättest Du auch die
Werkzeuge an der Hand, um Dir deine Fragen selber beantworten zu können.
Wenn Du z.B. in dem fehlerhaften Zustand bist, wäre es sehr hilfreich zu
wissen, ob alle tasks suspendiert oder wartend sind (deadlock; läßt sich
durch OS plugins oder eben Visualisierung erkennen) oder z.B. bei jedem
Break dieselbe Task in derselben Funktion läuft (das wäre dann das von
Stefan skizzierte Lockout Problem).
Es kann auch sein, dass das Problem komplett woanders liegt, z.B. bei
fehlkonfiguriertem OS oder ein Problem in der Middleare (kann es z.B.
sein, dass eine Task in einer Aufruffunktion im FS hängt und nicht
zurückkehrt?) Dazu müsste man aber genauere Infos über den Systemzustand
im Fehlerfall haben.
Carl D. schrieb:> Holger K. schrieb:>> Carl D. schrieb:>>> Holger Kraehe schrieb:>>>> Bei mir haben alle Tasks die selben prioritäten.>>>>>>>> Ich habe nun folgendes implementiert:>>>>>>>> An allen stellen, wo ich auf die Variable zugreife.>>>>> xSemaphoreTake(xStopProcessMutex,portMAX_DELAY);>>>> stopProcess = 1;>>>> xSemaphoreGive(xStopProcessMutex);>>>> >>>>>>>>>>>>> Leider hat sich das System erneut aufgehängt.>>>>>> Gibt es da irgend eine Behandlung der Timeout-Situation?>>>> Nein, ich gehe davon aus, dass ich irgendwan Zugriff erhalte, da die>> Tasks gleichberechtigt sind.>> Aha, Prinzip Hoffnung, das ist dann der Moment , in dem der Windows-PC> einen Restart braucht.>> Gibt es eigentlich einen Plan welche Tasks, welche (geshared-ten)> Resourcen welche Funktion haben sollen. Bisher sieht das von außen eher> nach Extreme Progamming aus.> FreeRTOS hatte früher mal ein schönes Tutorial, mit schönen Beispielen,> das man sich genauer zu Gemüte führen sollte. Denn daß da keine> Jahrzente RT-Erfahrung am Werk sind, merkt man auch. Ist auch nicht> schlimm, jeder fängt halt mal an.
Habe mir das Tutorial bereits mehrmals angeschaut und durchgelesen.
Grundsätzlich geht es um folgendes:
Es müssen Flash Memories beschrieben werden, dann muss der jeweilige
sektor gelöscht werden und dabei die Zeit welche zum löschen benötigt
wurde, gemessen werden.
Leider haben die Chips keinen Busy pin sondern nur ein Flag welches per
SPI ausgelesen werden muss.
Ich habe zwei queues. Eine für den Poll Task und eine mit den Memories
welche Ready sind.
Der Polltask nimmt sich ein element seiner queue und prüft das
entsprechende memory ob es bereit ist. Wenn nicht, sendet er die ID
wieder ans ende der queue. Wenn es jedoch ready war, schreib er die
aktuelle anzahl der systicks in ein globales array, zudem schreibt er
die ID in die Queue für den Memory Process task.
Der Memory Process task, nimmt sich das erste element und schaut in
einem globalen array nach, welchen status das entsprechende memory hat.
Entsprechend führt er die aktion aus, und setzt das memory wieder auf
die liste der zu prüfenden memories in die Queue für den ersten task.
Wenn der prozess task merkt, dass zuvor ein memory gelöscht wurde
(anhand des states) dann schreibt er einen log eintrag mit der Zeit
(aktuelle ticks - ticks bei start) in einen buffer. Wenn dieser eine
gewisse grösse erreicht hat, wird die varable ProcessStop gesetzt.
Nun muss gewartet werden, bis der PollTask welcher prüft ob die memorys
ready sind, eine leere Queue hat. Denn dann sind alle memorys gelöscht
und die zeiten erfasst. Nun schreibt der SD-Task auf die Karte.
Dann wird stopProcess = 0 gesetzt und weiter gehts.
Leider kriege ich mommentan zufällige HardFault errors. Eventuell liegts
am systemview?
Es gibt also eine Anzahl HW-Geräte, deren Status gepollt werden muß,
wegen mangelnder Interruptfähigkeiten, und Benutzern dieser Geräte, die
notfalls auf "Ready" warten können müssen. Wenn sie eine Screiboperation
angestoßen haben, dann muß auf deren Abschluß gewartet werden.
Kann man den Status schnell ermitteln? Dann könnte man das im
ApplicatioTickHook machen und bei Ok einen Semaphore je Gerät releasen.
Jeder der auf ein Gerät schreiben will, muß sich vorher den zugehörigen
Semaphore holen, den er aber nie selber zurück gibt, sondern per
"Quasi-Interrupt" ApplicationTick.
Man kann das optimieren, indem jede Schreibfunktion ein Bit Futur 1
setzt, wenn es ein Gerät in den Zustand Busy versetzt hat, was nach
erfolgter Statusprüfung wieder zurückgesetzt wird, aber das muß man dann
wieder ordentlich synchronisieren. Erster Schritte wäre mal straigh
forward.
BTW, wichtige Regel: optimieren wenn's funktioniert, nicht früher!
Holger K. schrieb:>> Ich habe zwei queues. Eine für den Poll Task und eine mit den Memories> welche Ready sind.>
kann es sein, dass Du ein xQueueSend mit portMAX_DELAY benutzt und die
Queue voll ist? So etwas kann zu Deadlocksiutationen führen, wenn das
Flushen der Queue durch die Syncvariable unterdrückt wird (ich habe mir
den Code nicht so genau angesehen, ob das konkret hier möglich ist). Wie
gesagt wäre es zunächst mal hilfreich zu wissen, ob das System im
Deadlock, Lockout oder wie auch immer steht.
Holger K. schrieb:>> Gibt es da irgend eine Behandlung der Timeout-Situation?>> Nein, ich gehe davon aus, dass ich irgendwan Zugriff erhalte, da die> Tasks gleichberechtigt sind.
Das ist eine falsche Annahme. Wenn alle Tasks dieselbe Priorität haben,
dann kann kein Task den anderen unterbrechen (zumindest wenn
Time-Slicing abgeschaltet ist, e.g. configUSE_TIME_SLICING = 0). D.h.
wenn ein Task in einer Endlosschleife hängt, dann steht das komplette
System.
Holger Kraehe schrieb:>> Ist der Pseudocode überhaupt identisch zum C-Code?>> Ja ist er.
Exakt? Heisst das, es gibt in den Tasks keine while(1)-Schleife?
Der Weg, das System mit systemview zu debuggen, ist auf jeden Fall der
richtige Weg und wird Dir auch bei zukünftigen Problemen weiterhelfen.
Viele Grüße, Stefan