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