Hallo,
wie würdet ihr folgende Aufgabe mit C++ umsetzen?
Kurze vereinfachte Einführung:
Habe zwei freeRTOS Prozesse.
Im einen freeRTOS Prozess (DatenErfassen) sollen Daten, welche über eine
Schnittstelle hereinkommen, erfasst werden.
Im anderen freeRTOS Prozess (DatenSpeichern) sollen diese Daten auf eine
SD Karte abgespeichert werden.
Es geht mir um die Betrachtung der Daten.
*Sollte ich eine Klasse "CDaten" erstellen mit statischen Variablen.
Somit könnten beliebige Objekte in diesen beiden Prozessen auf diese
statischen "CDaten" Variablen zugreifen.
*Sollte ich im Prozess (DatenErfassen), noch vor dem endlosloop for{;;}
eine Instanz "oCDaten" einer "CDaten" Klasse mit nun nicht statischen
Variablen erstellen und wenn Daten geschrieben werden sollen, der Queue
zum Prozess (DatenSpeichern) den Zeiger auf "oCDaten" übergeben?
Über diesen Zeiger kann dann aus dem Anderen Prozess auf "oCDaten"
zugegriffen werden.
*Sollte ich noch vor dem Starten der beiden Prozesse (DatenErfassen) und
(DatenSpeichern) eine Instanz "oCDaten" einer "CDaten" Klasse mit
nicht statischen Variablen erstellen und den Instanzen "DatenErfassen"
und
"DatenSpeichern" über ihren Konstruktor einen Zeiger auf das Objekt
"oCDaten" übergeben? Über diesen Zeiger kann ebenso auf "oCDaten"
zugegriffen werden.
Für mich sind alle hier genanten Ansätze lauffähig, doch welches ist der
übliche Ansatz? Gibt es andere? Die Aufteilung auf die Beiden Prozesse
ist aber gesetzt.
fred schrieb:> Es geht mir um die Betrachtung der Daten.>> *Sollte ich eine Klasse "CDaten" erstellen mit statischen Variablen.
C wie "Chnittstelle"? Oder was soll das C bedeuten?
> Somit könnten beliebige Objekte in diesen beiden Prozessen auf diese> statischen "CDaten" Variablen zugreifen.
Wozu sind sie dann in einer Klasse?
> *Sollte ich im Prozess (DatenErfassen), noch vor dem endlosloop for{;;}> eine Instanz "oCDaten
o? Für "orfasst"? ;-)
> einer "CDaten" Klasse mit nun nicht statischen> Variablen erstellen und wenn Daten geschrieben werden sollen, der Queue> zum Prozess (DatenSpeichern) den Zeiger auf "oCDaten" übergeben?> Über diesen Zeiger kann dann aus dem Anderen Prozess auf "oCDaten"> zugegriffen werden.
Wozu dient dann die Queue? Würde da nicht jedesmal ein Zeiger auf das
selbe Objekt übergeben werden?
> *Sollte ich noch vor dem Starten der beiden Prozesse (DatenErfassen) und> (DatenSpeichern) eine Instanz "oCDaten" einer "CDaten" Klasse mit> nicht statischen Variablen erstellen und den Instanzen "DatenErfassen"> und> "DatenSpeichern" über ihren Konstruktor einen Zeiger auf das Objekt> "oCDaten" übergeben? Über diesen Zeiger kann ebenso auf "oCDaten"> zugegriffen werden.
Du brauchst dann aber auch noch eine Synchronisation.
> Für mich sind alle hier genanten Ansätze lauffähig, doch welches ist der> übliche Ansatz? Gibt es andere? Die Aufteilung auf die Beiden Prozesse> ist aber gesetzt.
Wozu überhaupt diese "CDaten"-Klasse? Mache eine Klasse oder Struct, die
ein einzelnes Datum enthält (sofern das wiederum aus mehreren Werten
besteht) und stecke das einfach in die Queue. Der Empfänger nimmt das
dann entgegen.
Du könntest deine "CDaten" auch um die Queue herum bauen, also so dass
die Queue Teil dieser Klasse ist, und dann greifen deine beiden Tasks
immer auf diese Klasse zu, und die kümmert sich im Hintergrund darum,
die Daten über die Queue zu schicken.
Es wird eine Klasse FiFo benötigt. Eine Task schreibt und die andere
liest. Ob die Daten selber eine Klasse sein müssen, hängt davon ab, ob
sie nur Werte enthalten, oder auch damit arbeiten: Konvertierung,
Runden, Linearisierung, ...
Gehört seine Queue nicht zum Objekt DatenSchreiben? Fragt er nicht nach
der Datenverwaltung, Zeiger, Werte, ...?
Die FiFo Klasse hat die Methoden Add und Get und kümmert sich selber um
die Speicherung und Freigabe. Die Thematik kann losgelöst von den
anderen Themen betrachtet werden und auf das Target zugeschnitten
werden.
Die Aufteilung der Problematik in kleine eigenständige Häppchen ist doch
ein Grundsatz der OOP!
Torsten R. schrieb:> einfach Klasse schrieb:>> Es wird eine Klasse FiFo benötigt.>> Hat der OP schon. Allerdings hat er das Ding Queue genannt.
Nein, er hat eine FreeRTOS-Queue.
http://www.freertos.org/a00018.htmleinfach Klasse schrieb:> Gehört seine Queue nicht zum Objekt DatenSchreiben?
Soweit ich das verstanden habe, hat die keine Zugehörigkeit.
> Die FiFo Klasse hat die Methoden Add und Get und kümmert sich selber um> die Speicherung und Freigabe. Die Thematik kann losgelöst von den> anderen Themen betrachtet werden und auf das Target zugeschnitten> werden.
Das war im wesentlichen mein Vorschlag, um die Queue herum eine Klasse
zu schreiben, die sich um alles kümmert, was für die Übertragung durch
die Queue nötig ist.
Rolf M. schrieb:> Das war im wesentlichen mein Vorschlag, um die Queue herum eine Klasse> zu schreiben, die sich um alles kümmert, was für die Übertragung durch> die Queue nötig ist.
Und warum schreibst du das dann nicht einfach? ;-)
Rolf M. schrieb:> Torsten R. schrieb:>> Hat der OP schon. Allerdings hat er das Ding Queue genannt.>> Nein, er hat eine FreeRTOS-Queue.
Äh, und was soll diese Spitzfindingkeit jetzt? Ist doch egal, ob das
Ding nun Queue oder FreeRTOS-Queue heißt! Egal ob das nun C oder C++
ist. Das Ding ist eine Queue, bleibt eine Queue und sollte man deswegen
auch Queue nennen.
Auf der einen Seite steckst Du was rein, auf der anderen Seite, kann der
Task sich da die Daten raus holen und drauf blocken, wenn keine Daten da
sind. -> Nennt man Queue.
Was um alles in der Welt wollt Ihr jetzt noch darum stricken? Messdaten
fallen an, werden auf die Queue geworfen, werden Empfangen und dann auf
die SSD-Karte geschrieben. <- Punkt
Ich würde das ganze so strukturieren.
Eine Klasse, die sich um die Queue kümmert und mir einfache
Zugriffsmethoden für meine Daten bietet. Diese Klasse verwendet dann
intern z.B. die FreeRTOS queue. Damit ließe sich z.B. auch die
Typsicherheit nach außen garantieren, wenn die FreeRTOS queue nur void*
unterstützt. Das ganze gecaste wäre dann in dieser Klasse gekapselt.
Wenn meine Daten eine Struktur sind, dann würde ich eine eigene
Datenklasse schreiben und diese dann durch die Queue senden.
Beim aufsetzen vor dem main loop würde ich dann eine Instanz meiner
Queue anlegen und jeweils eine Referenz an DatenErfassen und
DatenSpeichern übergeben.
Zu deinen Vorschlägen noch folgende Anmerkungen:
> *Sollte ich eine Klasse "CDaten" erstellen mit statischen Variablen.> Somit könnten beliebige Objekte in diesen beiden Prozessen auf diese> statischen "CDaten" Variablen zugreifen.
Würde ich nicht machen. Stell die vor du hast einen zweiten
DatenErfassen Prozess mit einer eigenen Queue, dann hast du mit den
statischen Variablen schon ein Problem.
> *Sollte ich im Prozess (DatenErfassen), noch vor dem endlosloop for{;;}> eine Instanz "oCDaten" einer "CDaten" Klasse mit nun nicht statischen> Variablen erstellen und wenn Daten geschrieben werden sollen, der Queue> zum Prozess (DatenSpeichern) den Zeiger auf "oCDaten" übergeben?> Über diesen Zeiger kann dann aus dem Anderen Prozess auf "oCDaten"> zugegriffen werden.
Wäre eine Lösung, ich würde aber trotzdem die nächste benutzen.
> *Sollte ich noch vor dem Starten der beiden Prozesse (DatenErfassen) und> (DatenSpeichern) eine Instanz "oCDaten" einer "CDaten" Klasse mit> nicht statischen Variablen erstellen und den Instanzen "DatenErfassen"> und> "DatenSpeichern" über ihren Konstruktor einen Zeiger auf das Objekt> "oCDaten" übergeben? Über diesen Zeiger kann ebenso auf "oCDaten"> zugegriffen werden.
Das wäre meine Lösung.
Wenn es mir um Flexibilität für die Zunkunft ginge würde ich sogar noch
weiter gehen.
Ich erstelle zwei Interfaceklassen.
1
classIPutData
2
{
3
public:
4
voidPut(Data*pData)=0;
5
};
6
classIGetData
7
{
8
public:
9
Data*Get()=0;
10
};
Die Queue implementiert nun beide Interfaces.
1
classCQueue:publicIPutData,publicIGetData
2
{
3
...
4
};
In main lege ich dann eine Klasse von CQueue an, übergebe aber an die
beiden Prozesse nur jeweils eine Referenz vom Typ IPutData bzw.
IGetData. Damit kann ich meine Queueklasse einfach durch eine andere
austauschen, die die entsprechenden Interfaces implementiert.