Forum: Mikrocontroller und Digitale Elektronik Speicherbelegung unterschiedlicher CPSs


von Anton (Gast)


Lesenswert?

Hallo,

mein Problem ist nicht ganz einfach zu erklären, darum hole ich etwas 
weiter aus:

Ich habe eine Struktur mit ganz einfachen Variablen, z.B. eine Byte, 
eine Word und eine long Variable. Die werden im Speicher abgelegt.
Jetzt will ich die Struktur auf der seriellen Schnittstelle übertragen, 
was auch nicht das Problem ist.
Ich lege also einen Char Zeiger auf den Anfang der Struktur und 
übertrage sizeof(Struktur) Daten.
Auf der anderen Seite der Schnittstelle saß bisher eine gleiche CPU 
Familie, also alles gut!
Jetzt habe ich eine PC-ähnliche CPU angeschlossen und folgendes gemacht 
wie immer.
Im Datenpuffer liegen neue Daten die ich wie geschildert 
herübergeschickt habe. Jetzt nehme ich wieder meine Struktur und will 
die Daten auslesen.
Jetzt habe ich aber bemerkt das die Daten verutscht sind. Auch die 
Ursache ist schnell(ok,hat gedauert) gefunden.
Mein Sender hat die Daten folgendermaßen angelegt. Erst 1Byte, dann ein 
Dummy Byte, dann die 16Bit Variable und die 32Bit Variable. Heißt also 
das der sizeof folgerichtig die Struktur 8Byte groß macht, und diese 
auch sendet. Die Emfangsseite erwartet aber nach der Byte Variable die 
16Bit Variable u.s.w., erwartet also 7Byte.
Natürlich kann man auf der Emfangsseite 1 Byte einfügen in deren 
Struktur sofern man das weiß, aber hier ist nur das Beispiel, meine 
Struktur hat zig Variablen unterschiedlicher Größe. Auch sortieren nach 
Größe oder schicker jeder Variable einzeln ist nicht wirklich eine 
Lösung.

Meine Frage also: Wie schickt ihr Daten aus dem Speicher der genau 
gespiegelt auf der Emfangsseite ankommen muss. Ich habe DMA und würde 
ungern jedes Byte einzeln überprüfen. Oder, wie macht ihr das, irgendwie 
müsste man vereinbaren das er die Daten schön hintereinander ablegt.
Wenn das so nicht möglich ist und ihr schon vor lachen nicht in den 
Schlaf kommt bin ich natürlich auch an einer anderen Lösung 
interessiert.

von holger (Gast)


Lesenswert?

>Meine Frage also: Wie schickt ihr Daten aus dem Speicher der genau
>gespiegelt auf der Emfangsseite ankommen muss.

Byteweise, dann gibts kein Problem mit Alignment.
Alternativ im ASCII Code. Braucht halt etwas länger.

von (prx) A. K. (prx)


Lesenswert?

Wenn die Bytereihenfolge gleich ist, also immer das unterste Byte einer 
Variablen vorangeht, dann musst du dafür sorgen, dass keine 
automatischen Füllbytes eingefügt werden. Dass also auch ohne diese alle 
Variablen an ihrer natürlichen Grenze anfangen.

Entweder du sortierst die Struktur entsprechend, so dass dies nicht 
vorkommt (Elemente der Grösse nach absteigend sortieren), oder du füllst 
die Füllbytes selber explizit in die Strukturdefinition ein.

Alternativ kannst du versuchen alle beteiligen Compiler dazu zu bringen, 
die Struktur dicht zu packen. Kann allerdings sein, dass nicht alle das 
können, und üblicherweise kostet das deutlich Performance beim Zugriff.

von Anton (Gast)


Lesenswert?

@holger
Byteweise schicke ich ja ohnehin, da ich aber nicht feststellen kann wo 
er jetzt Füllbytes einfügt habe ich ja das Henne ei Problem.

@A.K ok, habe ich ja auch herausgefunden, ist aber echt nicht schön, 
alles zu ordnen, da sich dann kein logischer zusammenhang mehr ergibt, 
zumindest nicht immer.
Selber Füllbytes einfügen ist zu kritisch, finde ich, hatte so ein 
bißchen auf einen Art Pflichtanweisung gehofft die es ermöglicht das 
immer richtig geordnet wird.

von (prx) A. K. (prx)


Lesenswert?

Anton schrieb:

> bißchen auf einen Art Pflichtanweisung gehofft die es ermöglicht das
> immer richtig geordnet wird.

Pflicht ist dies nicht, weil nicht im C Standard vorgesehen, aber 
entsprechende compilerabhängige Attribute/Pragmas/... finden sich in 
etlichen Compilern.

NB: Was ist für dich "richtig"? Gepackte Strukturen sind im Zugriff oft 
langsam und codeintensiv. x86 kann das zwar in HW, aber bremsen tut es 
dennoch.

von holger (Gast)


Lesenswert?

>@holger
>Byteweise schicke ich ja ohnehin, da ich aber nicht feststellen kann wo
>er jetzt Füllbytes einfügt habe ich ja das Henne ei Problem.

Nö.

uint16_t var1 = 0x1234;

Sendbyte((uint8_t) (var1)); // Lowbyte
Sendbyte((uint8_t) (var1 >> 8)); // Highbyte

uint32_t var2 = 0x12345678;

Sendbyte((uint8_t) (var2));
Sendbyte((uint8_t) (var2 >> 8));
Sendbyte((uint8_t) (var2 >> 16));
Sendbyte((uint8_t) (var2 >> 24));

Damit ist immer die Reihenfolge der Bytes klar.
Alignment ist so egal. Bigendian oder Littleendian
spielt keine Rolle mehr. Alles ist geregelt.
Kannst du so auch auf Members von Structs machen.

Wenn du ein Struct ohne Rücksicht auf Alignment
oder Endianness versendest dann hast du die Arschkarte
gezogen.

von (prx) A. K. (prx)


Lesenswert?

holger schrieb:

> Damit ist immer die Reihenfolge der Bytes klar.
> Alignment ist so egal. Bigendian oder Littleendian
> spielt keine Rolle mehr. Alles ist geregelt.
> Kannst du so auch auf Members von Structs machen.

Das ist zweifellos der portabelste und sicherste Weg. Ob er hier 
sinnvoll ist hängt vom geforderten Durchsatz ab, nicht immer ist das 
praktikabel.

von Anton (Gast)


Lesenswert?

WOW, wie gesagt, man kann natürlich alles einzeln übertragen, dann ist 
der Weg auch nicht weiter. Aber wenn man schon DMA hat und 20K in einer 
Wurst übertragen will ist dann nicht mehr so schon.

Das Fachwort ist Aligment, wenn man es kennt kann man ja auch danach 
such und sieht das andere auch selbiges Problem haben.

@A.K. Habe auf der Emfängerseite ein x86 Derivat, der Byteweise keine 
Probleme hat.

Überlege nun alles INTs zu nehmen statt der chars, aber bläht meine 
arrays ganz schön auf.

von holger (Gast)


Lesenswert?

>Das ist zweifellos der portabelste und sicherste Weg. Ob er hier
>sinnvoll ist hängt vom geforderten Durchsatz ab, nicht immer ist das
>praktikabel.

Klar, für GCC kann man das z.B. so machen

struct PartInfo {
} __attribute__((packed));


Visual C

#pragma pack(push)
#pragma pack(1)
struct WaveHeader {
                   };

#pragma pack(pop)


Die Frage ist nur: Was ist das kleinere Übel?

von (prx) A. K. (prx)


Lesenswert?

Anton schrieb:

> @A.K. Habe auf der Emfängerseite ein x86 Derivat, der Byteweise keine
> Probleme hat.

Rechne damit, dass Zugriffe auf eine gepackte Struktur auch bei x86 ein 
Vielfaches langsamer sind als auf eine ungepackte, ganz besonders wenn 
sehr zeitnah geschrieben und gelesen wird. Ob das für dich eine Rolle 
spielt hängt davon ab, wie intensiv sie so genutzt werden.

von Anton (Gast)


Lesenswert?

Hallo A.K.

Das ist OK, da der Prozessor "nur" so arbeitet wie in der Doku steht. 
Ich habe zum Glück genügend Zeit die Nachrichten zu verschicken. Der 
eigendliche Sendevorgang läuft über einen genügend großen Puffer.

Habe auf der gcc Seite nun "__attribute__((packed))" zugefügt und alles 
funktioniert. Schöne Sache wenn mans weiß.

Danke für die Antworten.

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.