Forum: Compiler & IDEs Alignment gcc und avr-gcc


von Mathias S. (mps)


Lesenswert?

Hi,

hab ein Problem mit dem Alignment von int32_t zwischen gcc (Unter Linux, 
Intel) und avr-gcc. Und zwar möchte ich über die RS232 Daten zwischen uC 
und PC austauschen. U.a. int32_t Datentypen.

Nun hab ich mal etwas rumprobiert:
gcc:
  uint32_t dummy;
  dummy = 0x12345678;

  printf("%i %i %i %i", *((uint8_t*)&dummy), *((uint8_t*)&dummy+1), 
*((uint8_t*)&dummy+2), *((uint8_t*)&dummy+3) );

Das gibt mir auf der Konsole folgendes aus: 120 86 52 18

Ok, daher entnehme ich, dass gcc (bzw. Intel Prozessoren) auf dem 1. 
Byte das MSB speichert.



avr-gcc:
  int32_t dummy=0x12345678;

aus der main.lst:
81 0008 88E7          ldi r24,lo8(305419896)
  82 000a 96E5          ldi r25,hi8(305419896)
  83 000c A4E3          ldi r26,hlo8(305419896)
  84 000e B2E1          ldi r27,hhi8(305419896)
  85 0010 8D87          std Y+13,r24
  86 0012 9E87          std Y+14,r25
  87 0014 AF87          std Y+15,r26
  88 0016 B88B          std Y+16,r27

Daher entnehme ich, dass hier auf dem 1. Byte das LSB liegt.

Stimmt alles soweit?

Also wenn ich die Daten im uC nun in ein struct packen würde und das 
byteweise an den PC übertragen würde, wären doch meine int32_t 
Datentypen alle falsch. Gibt es hierfür eine einfache Lösung oder muss 
ich in einem von beiden Systemen das Alignment per Hand rumdrehen? Ich 
hab in der manpage von avr-gcc gesehen, dass es auch Optionen für align 
gibt. Allerdings habe ich hier, meineserachtens, nicht die richtige 
Option gefunden.

In der Praxis konnte ich es noch nicht ausprobieren, da die Platinen 
noch beim Ätzen sind und deshalb nicht verfügbar.

Weißt hier jemand genaueres?
Wäre nett, wenn mir jemand n Tipp geben könnte.

Danke im Voraus,
Gruß
Matze

von Jörg X. (Gast)


Lesenswert?

sende deine Binärdaten doch so
1
int32_t data= 0x12345678;
2
int8_t i;
3
for(i=3;i>=0;i--){
4
  Usart_putc(data & 0xFF);
5
  data >>= 8;
6
}
oder zumindest so ähnlich, dadurch ist das alignment egal...

hth. Jörg

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ich glaube du meinst eher die Endianess
http://www.mikrocontroller.net/articles/Digitaltechnik#Endianness

Die hat erstmal nichts mit dem Compiler zu tun, sondern mit der Maschine 
für die Code produziert wird bzw. worauf der Code rennt.

Die Lösung von Jörg ist besser (universeller), als deine printf-Methode, 
die eine bestimmte (hier falsche) Anordnung der Bytes im Speicher 
annimmt.

von yalu (Gast)


Lesenswert?

> Stimmt alles soweit?

Nein.

> Ok, daher entnehme ich, dass gcc (bzw. Intel Prozessoren) auf dem 1.
> Byte das MSB speichert.

Gerade nicht. Das erste Byte ist 120 = 0x78, und das ist das LSB,
nicht das MSB.

Sowohl x86 als auch AVR sind Kleinendianer, d.h. man kann
Integerzahlen ohne Änderung der Bytereihenfolge mit beiden lesen.

von Mathias S. (mps)


Lesenswert?

@Jörg:
Ja, so geht es. Allerdings wenn ich die Daten in einem struct hätte, 
müsste ich das struct ja wieder aufteilen und die int32_t einzeln 
senden. Wobei sich mein ganzes Problem in Luft aufgelöst hat. Siehe 
Beitrag von yalu.

@Stefan:
Ja, du hast natürlich recht. Ich meinte die Endians. Weiß auch nicht wie 
ich auf Alignments gekommen bin. :-O. Dass die Endians vom Prozessor 
abhängen war mir schon klar. Deswegen hab ich in meiner Fragestellung 
auch Intel angegeben. Ich war mir nicht sicher, ob AMD und Intel gleiche 
Endians verwenden...

@yalu:
Oh, jaja. Damit hab ich wohl den größten Bock geschossen. Irgendwie 
dachte ich wohl, dass 0x12 das LSB sei. Keine Ahnung wie ich darauf 
gekommen bin. Aber nun isses ja geklärt ;)
Allerdings hätte ich dann noch eine Frage. Du hast ja geschrieben, dass 
AVR's Little Endians verwenden. Kann man das überhaupt bei einem 8 Bit 
Prozessor sagen(Ich hab das für den ATMega32 kompiliert)? Für mich sieht 
der Assemblercode so aus, wie wenn das Endian Format allein vom avr-gcc 
festgelegt wird. Das inkremtieren um 1 führt der ATMega32 auch in 
mehreren Schritten aus(adiw und adc). Nicht so wie der Intel mit einem 
addl-Befehl.

Danke,

Matze

von Mathias S. (mps)


Lesenswert?

nochmal @Stefan:
Meine printf Konstruktion diente nur um festzustellen, welche Endian Typ 
die Intels sind. So wollte ich das nicht in das spätere Programm 
implementieren...

von yalu (Gast)


Lesenswert?

> Du hast ja geschrieben, dass AVR's Little Endians verwenden. Kann
> man das überhaupt bei einem 8 Bit Prozessor sagen(Ich hab das für
> den ATMega32 kompiliert)? Für mich sieht der Assemblercode so aus,
> wie wenn das Endian Format allein vom avr-gcc festgelegt wird.

Im Prinzip hast du recht, beim AVR ist das primär eine Sache des
Compilers, da der Controller keine Befehle hat, die auf 16-Bit-Werten
des Datenspeichers operieren.

Es gibt aber einige Befehle, die auf Registerpaaren arbeiten (ADIW,
MUL, usw.). Bei diesen liegt das niederwertige Byte immer in dem
Register mit der kleineren Nummer. Da die 32 Register in den
Datenadressraum eingeblendet werden, liegt das LSB auch an der
niedrigeren Adresse.

Ähnlich verhält es sich mit dem Programmspeicher. Er enthält
16-Bit-Werte bspw. in Form von JMP-Adressen. Da seine kleinste
adressierbare Einheit aber 16 Bits sind, hat er zunächst ebenfalls
keine Endianess. Allerdings gibt es mit dem LPM-Befehl einen
Pseudo-8-Bit-Lesezugriff. Bei der Adresse, die im 16-Bit-Registerpaar
Z steht, entscheidet das letzte Bit darüber, welche Hälfte des
Programmspeicherworts geliefert wird: 0 liefert das LSB, 1 das MSB.
Das sieht wiederum nach Little-Endian aus.

Da man so gut wie nie über Datenspeicheradressen auf die Register
zugreift und der LPM-Befehl nur den Programmspeicher betrifft, wäre es
wahrscheinlich kein großer Nachteil, wenn der Compiler 16-Bit-Werte im
RAM andersherum ablegen würde. Aber Little-Endian ist aus den o.g.
Gründen einfach natürlicher.

von Mathias S. (mps)


Lesenswert?

Ok, damit wären alle fragen geklärt.

Danke an alle Beantworter.

Matze

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.