Struct little endian

OP #7813291
Lesenswert?

Hallo Leute, ich komme nicht weiter.

Ich empfange hier auf meinem PC ein Packet welches im Payload ein String (Char array enthält, ein INT, FLOAT, BOOL).

1
54 
2
00 00 38 00 2f 40 40 a0 20 08 00 a0 20 08 00 00 
3
66 59 f9 e5 01 00 00 00 10 02 6c 09 a0 00 d3 00 
4
00 00 00 00 00 00 00 00 a6 58 f9 e5 00 00 00 00 
5
16 00 11 03 d3 00 a8 01 d0 00 00 00 ff ff ff ff 
6
ff ff c4 4f 33 0f fe 71 ff ff ff ff ff ff 20 76 
7
7f 18 fe 34 de b1 42 00 dd 31 18 fe 34 04 01 54 
8
48 49 53 20 49 53 20 41 20 43 48 41 52 00 00 00 
9
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 
10
ff 00 00 00 00 59 42 01 00 00 00 3f f1 01 0e

Die Daten werden vom Sender und Empfänger 1:1 aufgebaut:

1
typedef struct struct_message 
2
{
3
    uint8_t header[95];
4
    char a[32]; 
5
    int b;
6
    float c;
7
    bool d;
8
} struct_message;
9

10
struct_message myData;

Damit ich den Anfang erwische, habe ich den Header als Dummy im Struct angelegt (uint8_t header[95];).

Auf der Empgfängerseite kopiere ich mir das mit memcpy in das Struct. Soweit so gut, die Zeichenkette wird korrekt ausgegeben aber INT, FLOAT,BOOL nicht. Die Werte scheinen als little Endian abgelegt.

Wie gehe ich damit um?

1
    memcpy(&myData, data, sizeof(myData));
2

3
                        printf("char:%s\n", myData.a);
4
                        printf("int:%d\n", myData.b);
5
                        printf("float:%f\n", myData.c);
6
                        printf("bool:%d\n", myData.d);

Auf der Senderseite werden die Daten wie folgt erzeugt:

1
    // Set values to send
2
    strcpy(myData.a, "THIS IS A CHAR");
3
    myData.b = 65535;
4
    myData.c = 54.25;
5
    myData.d = true;

Auf dem Bild im Anhang ist das Char Array markiert, die Nullen nach den Werten entsprechen (char a[32]) den 32 byte. Danach steht der INT Wert (65535) in Hex FF FF, dann Float (54.25) in Hex 00 00 59 42. Zum schluss Bool (1) in Hex 01. Alles 4 byte lang.

Angehängte Dateien:
OP #7813332
Lesenswert?

J. S. schrieb:

Gib doch mal ein sizeof(myData) aus. Debugger hilft auch…

Mach ich ...

1
-------------------------------------------------------------------------
2

3
00 00 38 00 2f 40 40 a0 20 08 00 a0 20 08 00 00 
4
cf 1f 18 dd 02 00 00 00 10 02 6c 09 a0 00 d3 00 
5
00 00 00 00 00 00 00 00 0f 1f 18 dd 00 00 00 00 
6
16 00 11 03 d3 00 a7 01 d0 00 00 00 ff ff ff ff 
7
ff ff c4 4f 33 0f fe 71 ff ff ff ff ff ff 40 79 
8
7f 18 fe 34 18 b8 5f c2 dd 31 18 fe 34 04 01 54 
9
48 49 53 20 49 53 20 41 20 43 48 41 52 00 00 00 
10
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff 
11
ff 00 00 00 00 59 42 01 00 00 00 1b 60 f5 a6 
12
-------------------------------------------------------------------------
13

14
Packet length:143
15
myData:140
16
char:THIS IS A CHAR
17
int:255
18
float:0.000000
19
bool:0
OP #7813349
Lesenswert?

J. S. schrieb:

140 passt nicht, alignment problem. Auf 1 Byte alignment stellen für die Struktur, das ist Compilerabhängig.

Hallo Jojos, wie macht man das?

Ich habe letzens bei meiner Streifzügen das hier gefunden: attribute((packed))

1
typedef struct struct_message 
2
{
3
    uint8_t header[93];
4
    char a[32]; 
5
    int b;
6
    float c;
7
    bool d;
8
} __attribute__((aligned(4))) struct_message;

Wenn ich das benutze bekomme ich:

1
Packet length:140
2
Packet length:140
3
myData:140
4
char:THIS IS A CHAR
5
int:255
6
float:0.000000
7
bool:123

???

OP #7813371
Lesenswert?

J. S. schrieb:

140 passt nicht, alignment problem. Auf 1 Byte alignment stellen für die Struktur, das ist Compilerabhängig.

Ok, habe ich gemacht ...

1
typedef struct struct_message 
2
{
3
    uint8_t header[93];     // 2 Byte
4
    char a[32];             // 2 Byte
5
    int b;                  // 4 Byte
6
    float c;                // 4 byte
7
    bool d;                 // 4 Byte
8
}__attribute__((packed, aligned(1))) struct_message; struct_message myData;

https://stackoverflow.com/questions/11770451/what-is-the-meaning-of-attribute-packed-aligned4

https://gcc.gnu.org/onlinedocs/gcc/Common-Type-Attributes.html

Aber kein Erfolg:

1
Packet length:143
2
Struct size of myData:140
3
Struct size of myTest:8
4
char:THIS IS A CHAR
5
int:39
6
float:0.000000
7
bool:0

MyTest war ein Test:

1
typedef struct teststruct
2
{
3
     char Data1;
4
     int Data2;
5
     unsigned short Data3;
6
     char Data4;
7

8
}__attribute__((packed, aligned(1))) teststruct; teststruct myTest;

Hmm ...

OP #7813375
Lesenswert?

ENTWARNUNG! Ich habe nochmal die Packete (Wshark) durchgezählt ...

Siehe da:

1
typedef struct struct_message 
2
{
3
    uint8_t header[56];       // 2 Byte
4
    uint8_t action[24];       // 2 Byte
5
    uint8_t vendor[1];        // 2 Byte
6
    uint8_t oui[3];           // 2 Byte
7
    uint8_t noidea[11];       // 2 Byte
8
    char a[32];               // 2 Byte
9
    int b;                    // 4 Byte
10
    float c;                  // 4 byte
11
    bool d;                   // 4 Byte
12
}__attribute__((packed, aligned(1))) struct_message; struct_message myData;
1
Packet length:143
2
Struct size of myData:136
3
char:THIS IS A CHAR
4
int:9999
5
float:54.250000
6
bool:1

Bingo!

#7813376
Lesenswert?

Die headersize stimmt noch nicht. Der Header ist doch im Espressif IDK definiert. Das mit der String Ausgabe ist keine sichere Methode den Anfang zu finden, da sind zwei nicht druckbare Zeichen vor die du auch treffen kannst. Also printf("%x/n", myData[0]);

Und wieso ständig andere Strukturen? Da blickt doch keiner mehr durch.

OP #7818264
Lesenswert?

Ich habe jetzt aus faulheit die Radiotapdaten rausgepopelt. Spannend ist, am Ende das FCS Packet. Das muss ich mir noch erarbeiten.

1
typedef struct struct_message 
2
{
3
  uint8_t radio_tap_header[95];
4
  int b;
5
  float c;
6
  bool d;
7
  uint8_t pad_for_bool[3];
8
  float e;
9
  int fcs;
10
}__attribute__((packed, aligned(1))) struct_message; 
11
struct_message myData;
12

13
    
14
void print_packet(uint8_t *data, int len)
15
{ 
16
  memcpy(&myData, data, len);  
17

18
    printf("packet laenge: %d\n",len);
19
    printf("sizeof(myData): %ld\n",sizeof(myData));
20
    printf("antenna signal:%d\n", myData.radio_tap_header[30]);
21
    printf("int:%d\n", myData.b);
22
    printf("float:%.3f\n", myData.c); 
23
    printf("bool:%d\n", myData.d);
24
    printf("float:%.3f\n", myData.e);
25

26
printf("\n");
27
}
OP #7818275
Lesenswert?

Welle 🧐 S. schrieb:

1
> typedef struct struct_message
2
> {
3
>     uint8_t header[56];       // 2 Byte
4
>     uint8_t action[24];       // 2 Byte
5
>     uint8_t vendor[1];        // 2 Byte
6
>     uint8_t oui[3];           // 2 Byte
7
>     uint8_t noidea[11];       // 2 Byte
8
>     char a[32];               // 2 Byte
9
>     int b;                    // 4 Byte
10
>     float c;                  // 4 byte
11
>     bool d;                   // 4 Byte
12
> }__attribute__((packed, aligned(1))) struct_message; struct_message 
13
> myData;
14
>

Falls das hier mal jemand findet, BOOL ist nur EIN Byte und muss mit einem Pad[3] aufgefüllt werden ... es hatt nur funktioniert weil es am Ende stand.

#7818459
Lesenswert?

Welle 🧐 S. schrieb:

Falls das hier mal jemand findet, BOOL ist nur EIN Byte und muss mit einem Pad[3] aufgefüllt werden ... es hatt nur funktioniert weil es am Ende stand.

Aber das weiß man doch. Das ist doch schon seit Jahrzehnten so. Spätestens mit der breiten Einführung dem M68000 Mitte der 80er wurde das so gemacht.

"68000 und 68010 können nur byteweise auf ungerade Adressen zugreifen. Diese Exception wird ausgelöst, wenn man dennoch einen Wort- oder Langwort-Zugriff versucht (auch Programmzähler oder Stack-Pointer dürfen keine ungeraden Adressen enthalten)." https://freemint.github.io/tos.hyp/de/the_system_vectors.html

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren