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
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
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.
> 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.
@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
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...
> 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.