Hallo!
Ich habe einen AVR Microcontroller, der etwas steuert und die dafür
nötigen Laufzeitvariablen in einem Struct vorhält. Daneben hat er auch
eine USB Schnittstelle und über diese kann eine Linux oder Windows
Software die Laufzeitvariablen abfragen. Dazu sende ich das ganze Struct
einfach als Block über den USB an den PC und empfange es dort.
Ameinfachsten wäre es natürlich gleich das so zu gestalten:
1 | typedef struct {
|
2 | uint8_t status; /* Status of fan */
|
3 | int32_t esum; /* PI esum */
|
4 | uint16_t pwm; /* PWM factor [0..255] */
|
5 | uint16_t rpm; /* RPM [1/min] */
|
6 | uint16_t speed; /* actual speed of fan */
|
7 | uint8_t man; /* Manual Setpoint [0..100%] */
|
8 | uint8_t down; /* Countdown for error */
|
9 | uint8_t timer; /* Timer for fan stop */
|
10 | } fan_t;
|
11 |
|
12 | fan_t fanvar[3]; // es gibt 3 Lüfter
|
13 | usb_send_buffer( (U8*)fanvar, sizeof( fanvar));
|
Der PC hat nun das identische Struct und liest dieses über
1 | fan_t fans[3];
|
2 |
|
3 | ret = usb_bulk_read( udev, IN_ENDPOINT, (char*)&fans, sizeof(fans), TIMEOUT);
|
ein.
Leider scheitert die Einfachheit an zwei Dingen.
1. Die Variablen scheinen unterschiedlich im MSB/LSB Ordering zu sein.
2. Ein PC hat andere Vorstellungen von der Länge eines bytes, als ein
AVR.
1) lässt sich mit MSB/LSB defines eventuell noch ganz brauchbar lösen.
2) Hier ist mein Problem. Wärend der AVR bei einem sizeof( fanvar) 14
zurück gibt, sind es beimi PC 42... Wenn ich mir jedoch mal die
verschiedenen sizeof(uint8_t) oder sizeof(uint16_t) ausgeben lasse, so
stimmen diese mit 1 resprektive 2 sauber mit dem vom AVR überein. Also
scheint der gcc diese bei der Ablage im struct zu optimieren oder er
füllt irgendwo etwas auf. Wenn er mit 32 Bit Breite ablegen würde,
müsste aber schon das struct fan_t alleine 64 Bytes belegen. Ein
sizeof(fans) ergibt aber 60 Bytes Größe, also 20 Bytes für das struct (
welches ich drei mal brauche).
Wie kann ich auf der PC Seite den gcc dazu überreden, das Struct
byte-aligned abzulegen? Leider führt ein -fpack-struct zu einem
unerwünschten Nebenefekt: libusb stürzt mit einem Segmentation fault ab.
Kann man das Packen eines Structs im Code angeben, also conditional?
Gibt es elegante Funktionen um das LSB/MSB Problem zu lösen?
Danke schon mal für Tips, Links ...
Ulrich