Forum: Mikrocontroller und Digitale Elektronik IAR (MSP430): ByteArray -> Struktur hat Probs mit Integern?


von Philipp B. (philipp_burch)


Lesenswert?

Hallo zusammen,

ich hab' da ein Problem mit der IAR Embedded Workbench for MSP430
Kickstart Version (Was für ein Name...). Ich hab' ein ByteArray und
möchte dessen Inhalt einer Struktur zuweisen. Nun scheint es aber so,
als hätte der Compiler Probleme mit 16 Bit Integern in der Struktur.
Die Struktur sieht so aus:
1
struct BootSec
2
{
3
  U08 BS_jmpBoot[3];      //3 bytes
4
  U08 BS_OEMName[8];      //8 bytes
5
  U16 BPB_BytesPerSec;   //2 bytes
6
  U08  BPB_SecPerClus;     //1 byte
7
  U08  BPB_RsvdSecCntL;    //2 bytes
8
    U08  BPB_RsvdSecCntH;
9
  U08  BPB_NumFATs;        //1 byte
10
  U08  BPB_RootEntCntL;    //2 bytes
11
    U08  BPB_RootEntCntH;
12
  U08  BPB_TotSec16L;      //2 bytes
13
    U08  BPB_TotSec16H;
14
  U08  BPB_Media;          //1 byte
15
  U08  BPB_FATSz16L;       //2 bytes
16
    U08  BPB_FATSz16H;
17
  U16  BPB_SecPerTrk;      //2 bytes
18
  U16  BPB_NumHeads;       //2 bytes
19
  U32  BPB_HiddSec;        //4 bytes
20
  U32  BPB_TotSec32;       //4 bytes
21
};

Einige Werte hab' ich bereits testweise durch zwei 8 Bit Werte
ersetzt, damit funktioniert's. Sobald ich aber an einen 16 Bit Wert
komme, scheint es so, als würde der Compiler die Offsets verdrehen.
Mein ByteArray hat z.B. folgenden Inhalt (Ist nur der Anfang davon):
eb 3c 90 4d 53 44 4f 53 35 2e 30 00 02 04 04 00
oder als Zeichen
ë<MSDOS5.0......
Das ist korrekt so. Weise ich dieses Array nun der Struktur zu
1
    struct BootSec *BootSector = (struct BootSec *)Buffer;
so habe ich in BS_jmpBoot sowie BS_OEMName die richtigen Werte
(0xEB3C90 bzw. "MSDOS5.0"). Aber im ersten 16 Bit Wert
(BPB_BytesPerSec) einen Wert von 1026 bzw. 0x0402 anstatt 512 (0x0200).
Der lässt da also aus irgendeinem mir unerklärlichen Grund das Nullbyte
nach 0x30 aus. Aber WIESO? Ich hab's auch schon mit einem DummyByte
vor BPB_BytesPerSec versucht. Das ist dann auch wirklich 0x00. Der
folgende Int beinhaltet dann aber nicht etwa 0x0404 sonder wieder
0x0402, was ja auch stimmt. Ich versteh's nimmer. Woran kann es
liegen, dass der mir da die Werte irgendwie
verschiebt/verdreht/verändert? Ersetze ich alle 16 Bit Ints durch Char
(8 Bit) so funktioniert's tadellos! Aber das kann's ja wohl nicht
sein...

Langsam beginne ich IAR zu hassen...

Ich hoffe jemand kann mir helfen und bedanke mich schonmal für
Antworten.
Grüsse
Philipp

von szimmi (Gast)


Lesenswert?

Hiho,
meines Wissens sind auch beim IAR/MSP430 Wort-Zugriffe auf ungerade
Adressen nicht erlaubt. Deshalb füllt der Compiler Deine Struktur nach
U08 BS_OEMName[8] mit einem Dummy-Byte auf, damit das naechste
16-Bit-Wort auf einer geraden Adresse liegt (Alignment).
Wenn Du also Byte-weise in die Struktur reinschreibst, aber dann über
die Struktur-Member selbst darauf zugreifst, greift er da halt "eins
daneben" durch das Dummy-Byte.
Wenn das Array unveränderlich ist und Deine Struktur auch, musst Du
wohl oder übel eine Konvertierungsfunktion schreiben, die Stück für
Stück Dein Array in die Struktur rueberhebelt. Mit dem einfachen
Abbilden ist da leider nix. Zumindest ist mir keine IAR-Option bekannt.

von Philipp B. (philipp_burch)


Lesenswert?

Ach du sch***... Irgendwie hab' ich's doch noch fast befürchtet...
Naja, muss ich wohl doch mit meinen Byte-Werten vorlieb nehmen. Wär'
aber schon nicht schlecht, wenn der Compiler dann wenigstens eine
Warnung ausspucken würde >:(

Aber danke dir für die Antwort, dann muss ich wohl nimmer nach einem
Fehler meinerseits suchen, geht halt einfach nicht.

von szimmi (Gast)


Lesenswert?

Oerks,
wer lesen kann, ist klar im Vorteil, hast ja das Dummy-Byte schon
probiert... muss ich nochmal neu ueberdenken...

von Karl H. (kbuchegg)


Lesenswert?

> wer lesen kann, ist klar im Vorteil, hast ja das Dummy-Byte schon
> probiert... muss ich nochmal neu ueberdenken...

Deine Analyse war schon richtig.
Der Compiler fügt ein padding Byte in die Struktur ein.
Ist also quasi so als ob er geschrieben hätte:

struct BootSec{
  U08 BS_jmpBoot[3];      //3 bytes
  U08 BS_OEMName[8];      //8 bytes
  U08 Dummy_Padding_Byte;
  U16 BPB_BytesPerSec;   //2 bytes
  ...

Ob er jetzt explizit dieses Byte einfügt, oder ob der Compiler
das macht, macht keinen Unterschied für den Wert von BPB_BytesPerSec.

Der einzige Unterschied ist:
Das explizite Padding Byte kann man rausnehmen woraufhin der Compiler
stillschweigend sein eigenes rein macht.

@Phillip
Durchsuche die Compiler Doku, wie du das Padding entweder abschalten
oder auf 1 setzen kannst. Bei vielen Compilen geht das mit einem
#pragma
Geht das nichts, dann bleibt dir nur der Weg über Einzelzuweisungen
wie szimmi bereits gesagt hat.

Und: Der Compiler braucht nicht davor warnen. Ja er könnte es
nicht mal tun, denn woher soll er den wissen, dass in dem Arry
das Padding Byte nicht enthalten ist?
Ìm Übrigen: In dem Moment wo du Pointer auf andere Datentypen
zurecht castest, bist du sowieso alleine. Es obliegt dann deiner
Verantwortung ob da das Richtige raus kommt oder nicht. Offiziell
ist das 'undefined behaviour': Alles Mögliche kann passieren.

von Philipp B. (philipp_burch)


Lesenswert?

@szimmi:

Nur keine Angst, du  hast das Problem richtig erkannt und mir zur
Lösung verholfen :) Thx

@Karl:

Danke für den Hinweis, werde mal schauen ob ich die entsprechende
Anweisung finde. Weisst du zufälligerweise, wonach ich da suchen
sollte? Die Hilfe ist relativ gross und doch findet man nicht recht was
man sucht...

von Philipp B. (philipp_burch)


Lesenswert?

Ok, hab's gefunden. Es ist
#pragma pack(1):
1
#pragma pack(1) 
2
 
3
struct FirstPacked 
4
{ 
5
  char alpha; 
6
  short beta; 
7
}; 
8
 
9
#pragma pack()

Allerdings steht da, dass es grösseren und langsameren Code erzeugt...
Ich lass' es mal für's Erste, möglicherweise brauche ich das noch
woanders.
Aber danke euch beiden!

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.