Mikrocontroller: Probleme mit char Buffer

Gast #4825216
Lesenswert?
• ▲
▼
Guten Morgen,

auf einem Mikrocontroller soll ein Empfangspuffer vom Typ char in 
entsprechende Variablen kopiert werden.
1
uint8_t TestPuffer[256]
2

3
uint16_t Length;
4
uint32_t IpAddr;
5
uint8_t *Data;

In den ersten beiden char Elementen befindet sich die Länge in den 
nächsten 4 Elementen eine Ip Addresse. Die Daten befinden sich ab dem 
Element 6.

WIe kann man die Daten am Besten in die entsprechenden Variablen 
kopieren?
Gast #4825263
Lesenswert?
• ▲
▼
zoe schrieb:
> Mit memcpy könnte man sowas machen. Gibt es da eine bessere
> Alternative?

Was spricht gegen memcpy?

Alternativ könntest du dir natürlich eine Union aus einer Struktur mit 
den Daten drin und dem Buffer deklarieren. Bei den Unions bin ich mir 
nicht zu 100% sicher, ob jeder Compiler die Elemente des Struct im 
Buffer gleich anodnen muss.

Oder du machst das mit Pointern. Also immer auf den Typ casten und dann 
den offset addieren oder so.

Der Aufwand für den µC dürfte aber immer relativ gleich sein.

Ich persönlich würde die memcpy oder pointer Variante nehmen.
Gast #4826193
Lesenswert?
• ▲
▼
zoe schrieb:
> In den ersten beiden char Elementen befindet sich die Länge in den
> nächsten 4 Elementen eine Ip Addresse. Die Daten befinden sich ab dem
> Element 6.
>
> WIe kann man die Daten am Besten in die entsprechenden Variablen
> kopieren?

Sowas regt mich auf. Wie - bittesehr - stehen Länge un IP-Adresse denn 
dort drin? Bigendian oder Littleendian? Du müßtest sowas schon 
dazusagen.

Ansonsten ist sowas doch kinderleicht - sofern ich dich wenigstens 
halbwegs verstanden habe:
long L;
 L = Testpuffer[0];
 L = (L << 8) | Testpuffer[1];
 Laenge = L;

Und sinngemäß dasselbe für die IP-Adr. Du solltest es aber für deine 
Endianess anpassen - gelle?

W.S.
Gast #4826357
Lesenswert?
• ▲
▼
typedef struct {
   uint16_t Length;
   uint32_t IpAddr;
   uint8_t TestPuffer[256]
} __attribute__((packed)) uart_t;

uart_t uart;



Pointer auf das erste Element
uint8_t *buffer_ptr = (unsigned char*) &uart
Gast #4826650
Lesenswert?
• ▲
▼
Hallo,

müsste auch so gehen:
1
typedef struct {
2
   uint16_t Length;
3
   uint32_t IpAddr;
4
   uint8_t Data[250];
5
} message_t;
6

7
......
8

9
message_t *message = (message_t *) TestPuffer;
10
uint32_t ip = message->IpAddr;
11

12
......

ms
Gast #4826998
Lesenswert?
• ▲
▼
PittyJ schrieb:
> Sobald man portabel programmieren möchte holt man sich die Bytes einzeln
> raus, shiftet diese passend und odert sie zum Gesamtwert.

Ja, eben! Damit hast du als so ziemlich einziger in dieser ganzen Runde 
den Nagel auf den Kopf getroffen - aber es hört dir keiner zu.

Stattdessen wird ganz gewiß ab hier noch ellenlang über weitere structs 
und unions schwadroniert werden.

W.S.
#4827337
Lesenswert?
• ▲
▼
ms schrieb:
> Walter S. schrieb:
>> aber nur mit etwas Glück, bei Pechvögeln funktioniert das nicht
>
> ja muss ich dir recht geben. Sobald man das Gesamtsystem (Programm)
> nicht im griff hat ist der misserfolg vorprogrammiert.

Man kann solche Hinweise auch mal ernst nehmen...
(Aber eigentlich soll dem TO geholfen werden.)

Mir fallen dazu ein:
- Alignment nicht beachtet (zusätzliche Füllbytes, welche im char-Buffer 
nicht sind)
- Wenn message an einer ungünstigen Adresse liegt (weil ja ein 
char-Buffer das darf) geht bei verschiedenen Umgebungen der Zugriff auf 
32bit schief message->IpAddr
Gast #4827435
Lesenswert?
• ▲
▼
Mampf F. schrieb:
> Rolf M. schrieb:
>> Doch.
>
> Erklärung?

Hab ich doch im Anschluss geschrieben.

> Wofür bräuchte ein 8Bit-Controller Padding in einem Struct?

Vielleicht hab ich dich missverstanden. Ich dachte mit "niemals" 
meintest du "auf keinem µC in keiner Situation". Wenn die Aussage aber 
auf den AVR beschränkt zu verstehen ist, dann ist das was anderes.
Gast #4827904
Lesenswert?
• ▲
▼
Hallo Steffen,

Steffen R. schrieb:
> - Alignment nicht beachtet (zusätzliche Füllbytes, welche im char-Buffer
> nicht sind)
> - Wenn message an einer ungünstigen Adresse liegt (weil ja ein
> char-Buffer das darf) geht bei verschiedenen Umgebungen der Zugriff auf
> 32bit schief message->IpAddr

kannst Du mir da mal ein Beispiel geben.Ich würde das gerne mal bei mir 
im Labor Testen lassen an verschieden DEV-Systemen.

ms
#4829839
Lesenswert?
• ▲
▼
ms schrieb:
> Hallo Steffen,
>
> Steffen R. schrieb:
>> - Alignment nicht beachtet (zusätzliche Füllbytes, welche im char-Buffer
>> nicht sind)
>> - Wenn message an einer ungünstigen Adresse liegt (weil ja ein
>> char-Buffer das darf) geht bei verschiedenen Umgebungen der Zugriff auf
>> 32bit schief message->IpAddr
>
> kannst Du mir da mal ein Beispiel geben.Ich würde das gerne mal bei mir
> im Labor Testen lassen an verschieden DEV-Systemen.

Der erste Punkt ist einfach. Man nehme ein System mit Alignment 4 oder 8 
(z.B. arm-gcc)

Es entsteht
1
typedef struct {
2
   uint16_t Length;
3
-- 2 Füllbytes --
4
   uint32_t IpAddr;
5
   uint8_t Data[250];
6
} message_t;

Für den zweiten Fall habe ich kein Beispiel zu Hand. Das char Array 
erfordert ein Alignment von 1 und kann somit z.B. auch an ungeraden 
Adressen anfangen. Häufig beginnen die Linker aber an eine ihrem max. 
Alignment passenden Stelle. Daher wird es in vielen Fällen nicht 
crashen, solange man die Struktur genau an den Anfang des Arrays legt.

Nur für die, die nicht kennen, dass man manche Zugriffe nicht auf 
beliebige Adressen durchführen darf:

Z.B. beim C166 würde ein modifiziertes Beispiel crashen:
1
message_t *message = (message_t *) &TestPuffer[1];
2
uint32_t ip = message->IpAddr
#4830590
Lesenswert?
• ▲
▼
ms schrieb:
> Walter S. schrieb:
>> aber nur mit etwas Glück, bei Pechvögeln funktioniert das nicht
>
> ja muss ich dir recht geben. Sobald man das Gesamtsystem (Programm)
> nicht im griff hat ist der misserfolg vorprogrammiert.
>
> ms

ich meinte damit was anderes, nämlich dass das nur funktioniert wenn die 
Bytes des 16 bzw. 32-Bit Wortes in der passenden Reihenfolge abgelegt 
sind,
Stichwort: Endianess

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