Forum: Mikrocontroller und Digitale Elektronik struct größer als erwartet


von Robert Zelder (Gast)


Lesenswert?

Hallo,

ich versuche die Konfigurationsparameter für einen externen Baustein, 
der über eine serielle Schnittstele an meinen Controller angeschlossen 
ist, in eine struct zu packen. Das mache ich, weil das Protokoll die 
Daten in einer bestimmten Reihenfolge verlangt. Vor der struct wird ein 
Header gesendet, dahinter eine Checksumme.
1
struct
2
{
3
  uint8_t  flags;
4
  uint32_t baudrate;
5
  uint8_t  mode;
6
} com_config_t;

Leider funktioniert das nicht. Komischerweise liefert 
sizeof(com_config_t) auch mehr als die erwarteten 6 Bytes zurück.

Was macht der Compiler da? Könnte das damit zusammenhängen, dass ich auf 
einem 32bit-System bin und er alles in 32 bit Schritten zusammenbaut?

Wenn ja, wie kriege ich dann meine struct implementiert, so dass ich sie 
direkt über die Schnittstelle senden kann?

Grüße und frohe Weihnachten,
der Rob

von Sebastian Hepp (Gast)


Lesenswert?

Versuch es mit
1
struct xyz {
2
3
} __attribute__((packed));

von Roland H. (batchman)


Lesenswert?

Robert Zelder schrieb:
> Was macht der Compiler da?

Er "alignt"

Robert Zelder schrieb:
> Wenn ja, wie kriege ich dann meine struct implementiert, so dass ich sie
> direkt über die Schnittstelle senden kann?

Du bist auf einem 32-Bitter mit vermutlich vielen MHz und Flash 
unterwegs. Unabhängig davon würde ich die Felder einzeln rausschreiben.

"packed" löst das Problem, aber wenn das mal aus Versehen gelöscht wird 
... anders formuliert hängt die logische Korrektheit Deiner Applikation 
von einer relativ technischen Einstellung ab, die man eher aus 
RAM-Mangel wählt.

Beim Portieren von 8-Bit-Code auf 32-Bit habe ich damit viel "Spass" 
gehabt.

von chinesenüberwacher (Gast)


Lesenswert?

Robert Zelder schrieb:
> Was macht der Compiler da? Könnte das damit zusammenhängen, dass ich auf
> einem 32bit-System bin und er alles in 32 bit Schritten zusammenbaut?
Genau, Stichwort padding. Lösung steht oben.

von Rolf M. (rmagnus)


Lesenswert?

Roland H. schrieb:
> "packed" löst das Problem, aber wenn das mal aus Versehen gelöscht wird
> ... anders formuliert hängt die logische Korrektheit Deiner Applikation
> von einer relativ technischen Einstellung ab, die man eher aus
> RAM-Mangel wählt.

Davon abgesehen gibt es durchaus Architekturen, die den Zugriff auf 
solche Strukturen gar nicht unterstützen. Andere können es, aber 
brauchen dann mehr Zeit für den Zugriff.

von Roland H. (batchman)


Lesenswert?

Rolf Magnus schrieb:
> Davon abgesehen gibt es durchaus Architekturen, die den Zugriff auf
> solche Strukturen gar nicht unterstützen.

Welche Architekturen sind das?

von DirkB (Gast)


Lesenswert?

Kannst du die Reihenfolge der Elemente ändern?
Dann mach erst die  uint32_t, dann die  uint8_t.
Dann brauchst du das packed nicht.

von (prx) A. K. (prx)


Lesenswert?

Rolf Magnus schrieb:

> Davon abgesehen gibt es durchaus Architekturen, die den Zugriff auf
> solche Strukturen gar nicht unterstützen. Andere können es, aber
> brauchen dann mehr Zeit für den Zugriff.

Das ist eher eine Frage des Compilers. Denn ein Compiler kann - wenn er 
will - auch bei Architekturen, die keinen unaligned access unterstützen, 
einen Code erzeugen, der mit gepackten Strukturen umgehen kann. Die 
Effizienz ist dabei natürlich nicht berauschend.

von (prx) A. K. (prx)


Lesenswert?

Roland H. schrieb:

> Welche Architekturen sind das?

Hardwareseitig können beispielsweise diverse ARMs keinen unaligned 
access, jedenfalls nicht so wie man ihn sich vorstellt. Das sind u.A. 
die klassischen ARM7/9 und Cortex M0. GCC unterstützt allerdings 
trotzdem gepackte Strukturen und wählte den erzeugten Code entsprechend 
des Zielsystems aus.

von Karl H. (kbuchegg)


Lesenswert?

Gabs nicht auch bei den 68000 derartige Restriktionen? Ich meine mich zu 
erinnern, dass A0 da gar nicht am Adressbus verfügbar war.

von Simon K. (simon) Benutzerseite


Lesenswert?

"packed" ist keine Lösung.

Die Lösung ist es für Binäre Protokolle keine Structs zu verwenden, 
sondern alles per Hand zusammenzubauen. Das steht hier vielfach im Forum 
und wird durch Profis wie Karl-Heinz Buchegger (hoffe keinen Unsinn zu 
erzählen ;-)) u.Ä. auch so unterstützt.

Genau so bei Bitfelder im Ürbrigen. Die Anordnung der Bits ist von 
mehreren Parameter abhängig (Endianess z.B.).

von Karl H. (kbuchegg)


Lesenswert?

Simon K. schrieb:
> "packed" ist keine Lösung.

Vor allen Dingen auch, weil das ja nicht das einzige Problem sein kann. 
Byte-Order bei mehrbytigen Dingen ist das andere.

von (prx) A. K. (prx)


Lesenswert?

Karl Heinz Buchegger schrieb:

> Gabs nicht auch bei den 68000 derartige Restriktionen? Ich meine mich zu
> erinnern, dass A0 da gar nicht am Adressbus verfügbar war.

Ob man die Leitungen für die Byteselektion nun LDS/UDS (68000) oder 
A0/HBE (8086) nennt ist dafür irrelevant. Krass war nur TI 9900, denn 
der hatte überhaupt keine, d.h. konnte nicht einmal byteweise schreiben, 
musst bei Byteoperationen vorher lesen.

Es ist aber richtig, dass 68000 Code und 16/32-Bit Daten an ungeraden 
Adressen nicht zuliess.

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.