Forum: Mikrocontroller und Digitale Elektronik Little oder Big Endian im mega64?


von Christian (Gast)


Lesenswert?

Hallo Leute,

wo finde ich Informationen darüber, ob der atmega64 (bzw. die Familie) 
Little oder Big Endian verwendet?
Das Gleiche für den H8S/2367 von Hitachi...?

Grüße

Christian

von Falk B. (falk)


Lesenswert?

@ Christian (Gast)

>wo finde ich Informationen darüber, ob der atmega64 (bzw. die Familie)
>Little oder Big Endian verwendet?

AFAIK Little Endian. Sieht man an den merkwürdigen HEX-Dumps.

http://www.mikrocontroller.net/articles/Digitaltechnik#Endianness

Spielt aber kaum eine Rolle. In ASM machst du das sowieso alles "per 
Hand", in C macht es der Compiler.

MFG
Falk

von Andreas K. (a-k)


Lesenswert?

Es gibt nicht viele Stellen, wo man das beim AVR überhaupt mitkriegt:
- Anordnung der Bytes im Flash bei Zugriff per LPM,
- Reihenfolge der Return-Adresse auf dem Stack,
- 16bit-Werten in benachbarten Registern.

Wenn man das zusammenrechnet, ist AVR zu zwei Dritteln little-endian, zu 
einem Drittel big-endian.

von Christian (Gast)


Lesenswert?

Naja, ich arbeite viel auf der Bitebene. Und da muss ich schon wissen, 
ob ich Little oder Big-Endian verwende, wenn ich mit meinen Masken 
arbeite...

Ich habe nämlich die gleichen Masken auf einem PC genutzt um die vom µC 
generierten Daten auszuwerten, und bin da ganz schön auf die Sch*** 
gestürtzt, bis ich mein Problem fand:

mein damaliger µC verwendete Big Endian... (MSB first), und im PC war 
dann leider das LSB first... Dumm, dass die Maske nicht automatisch mit 
gedreht wurde ;)

Worum es mir eigentlich geht: Ich muss doch irgendwo auf den 
Herstellerseiten eine Info darüber finden... Sowas kann doch nicht mit 
Try & Error herausgefunden werden, oder?

Grüße

Christian

von Andreas K. (a-k)


Lesenswert?

Klar findet man das. Die Doku zum LPM Befehl klärt 2 der 3 erwähnten 
Fragen, nur die Return-Adresse ist undokumentiert.

von chris (Gast)


Lesenswert?

Das hängt vom C compiler ab, nicht vom Mikrocontroller, auch wenn die 
Registerstructur eines Micros da sehrwohl einen Einfluß hat, LSB mit 
niederer
oder höherer Addresse bei 16bit Timern usw.

von Andreas K. (a-k)


Lesenswert?

Warum du keine klare Antwort " ... ist little-endian" von Atmel erwarten 
darfst: Das Problem stellt sich überwiegend nicht, weil es bei AVRs 
keinen einzigen Befehl gibt, der im SRAM mit Werten grösser als 8 Bit 
arbeitet, wenn man von der erwähnten Return-Adresse mal absieht. In 
diesem Sinne sind AVRs also ist-mir-egal-mach-es-wie-du-willst-endian.

von Falk B. (falk)


Lesenswert?

@ Christian (Gast)

>Naja, ich arbeite viel auf der Bitebene. Und da muss ich schon wissen,
>ob ich Little oder Big-Endian verwende, wenn ich mit meinen Masken
>arbeite...

Nööö. Man muss nur bei Daten mit mehr als ein Byte RICHTIG drauf 
zugreifen. Ein Compiler macht das automatisch, in ASM muss man halt 
aupassen.

>mein damaliger µC verwendete Big Endian... (MSB first), und im PC war
>dann leider das LSB first... Dumm, dass die Maske nicht automatisch mit
>gedreht wurde ;)

Hat dennoch nix mit den Masken zu tun, sondern mit dem Datenzugriff.

0xABCD ist immer 0xABCD, egal ob Little oder Big Endian.

>Worum es mir eigentlich geht: Ich muss doch irgendwo auf den
>Herstellerseiten eine Info darüber finden... Sowas kann doch nicht mit
>Try & Error herausgefunden werden, oder?

Der AVR ist ein 8-Bitter, da stellt sich die Frage so gut wie gar nicht.
Aussnahmen wurden genannt.

MFG
Falk

von Christian (Gast)


Lesenswert?

"ist-mir-egal-mach-es-wie-du-willst-endian"
Das ist ja nett formuliert.

Na mal schauen. Ich muss es irgendwie in der Doku begründen, warum ich 
die Bitmasken auf dem PC drehen musste. Ich wollte halt vorher nur 
sicher gehen, dass der µC auch Big Endian hat, damit ich in der Doku 
keinen Mist zusammen-begründe ;)

Grüße

Christian

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Für Daten hat er aber gerade kein Big Endian von Haus aus, sondern
nur für die Returnadressen auf dem Stack.

von Peter D. (peda)


Lesenswert?

Christian wrote:

> Worum es mir eigentlich geht: Ich muss doch irgendwo auf den
> Herstellerseiten eine Info darüber finden...

Nein.
Der AVR ist ein 8-Bitter und damit ein No-endian.

Wie nun ein C-Compiler aus 2 Bytes einen 16Bit-Wert zusammenbastelt, ist 
seine persönliche Freiheit.
Der AVR-Hersteller kann das also garnicht festlegen.


In der Regel ist eine Datenübertragung (UART, CAN) auch 8Bittig und 
damit No-Endian.
Man muß also im Protokoll festlegen, in welcher Reihenfolge die Bytes 
übertragen werden.

Auf PC- und AVR-Seite verwende ich zur Übertragung Code, der endian 
unabhängig ist und schon gibts nie Probleme:
1
int8_t hi;
2
int8_t lo;
3
int16_t word;
4
...
5
hi = word>>8;
6
lo = word;
7
...
8
word = lo | (hi>>8);


Peter

von Christian (Gast)


Lesenswert?

Ok, weil die Frage mit den Masken aufkam:

so sieht meine Maske im Mikrocontroller aus:
1
typedef struct
2
{
3
  union                        /* Status des Telegramms            */
4
  {
5
    unsigned char Byte;                /* Byte-Zugriff                  */
6
    struct                      /* Bit-Zugriff                  */
7
    {
8
      unsigned char BELEGT:    1;        /* 1: Speicher ist belegt            */
9
                            /* 0: Speicher ist nicht belegt          */
10
      unsigned char SENDEN:    1;        /* 1: Telegramm kann gesendet werden      */
11
                            /* 0: Telegramm kann noch nicht gesendet werden  */
12
      unsigned char RESERVIERT5:  1;
13
      unsigned char RESERVIERT4:  1;
14
      unsigned char RESERVIERT3:  1;
15
      unsigned char FILTERBEREIT:  1;        /* 1: Telegramm vollständig            */
16
                            /* 0: Telegramm unvollständig          */
17
      unsigned char RICHTUNG:    1;        /* 0: Telegramm vom BC              */
18
                            /* 1: Telegramm vom FM              */
19
      unsigned char KANAL:    1;        /* 0: Telegramm vom FM_A            */
20
                            /* 1: Telegramm vom FM_B            */
21
        }Bit;
22
    }Status;
23
}maske_uC;

und so muss die Maske für den PC aussehen:
1
typedef struct
2
{
3
  bool inUse;
4
  union
5
  {
6
    unsigned char BYTE;              //  Byte-Zugriff
7
    struct
8
    {
9
      unsigned char KANAL:    1;      //  0 == Kanal A, 1 == Kanal B
10
      unsigned char RICHTUNG:    1;      //  0 == Master, 1 == Slave
11
      unsigned char RESERVIERT2:  1;        
12
      unsigned char RESERVIERT3:  1;
13
      unsigned char RESERVIERT4:  1;
14
      unsigned char RESERVIERT5:  1;
15
      unsigned char SENDEN:    1;      //  0 == nicht Senden, 1 == Senden (in der PC-Software ohne Bedeutung)
16
      unsigned char RESERVIERT7:  1;
17
    }Bit;                    //  Bit-Zugriff
18
  }Status;
19
}maske_PC;

Ich musste die Reihenfolge der Bits der Maske ändern, da die Maske sonst 
bei dem gleichen Byte-Wert andere Ergebnisse ausgespuckt hat...

Beide Codeabschnitte werden vom Gcc kompiliert... Jedoch einmal für den 
x86 und einmal für den µC.

Vielleicht ist nun meine Frage nachvollziehbar ;)

Grüße

Christian

von Andreas K. (a-k)


Lesenswert?

Peter Dannegger wrote:

> Der AVR ist ein 8-Bitter und damit ein No-endian.

Er ist ziemlich no-endian, ja, aber viele 8-Bitter sind das nicht und 
fast alle haben irgendwo 16bit Werte verbuddelt, meist im Code. 8051 
kennst du selber, 65xx/68xx,8080/Z80,Z8 haben das querdurch in Code und 
Daten. Völlig frei von jeder hardwareseitigen Vorgabe war m.W. nur 
SC/MP.

von Andreas K. (a-k)


Lesenswert?

@Christian: Und genau solche Mätzchen vermeidet man elegant mit der 
Danegger'schen Methode, indem man die Daten in einer definierten 
Reihenfolge überträgt, unabhängig von der maschinell bevorzugten 
Reihenfolge.

Das mag etwas aufwendiger sein, erspart aber einigen Ärger.

Und bei Bitfeldern begiebt man sich voll in Abhängigkeit vom Compiler. 
Das darf der nämlich in weiten Grenzen machen wie er will.

von Peter D. (peda)


Lesenswert?

Berichtigung:

Das High-Byte muß natürlich nach links geschoben werden:
1
int8_t hi;
2
int8_t lo;
3
int16_t word;
4
...
5
hi = word>>8;
6
lo = word;
7
...
8
word = lo | (hi<<8);


Peter

von Jörg W. (dl8dtl) (Moderator) Benutzerseite


Lesenswert?

Andreas Kaiser wrote:

>> Der AVR ist ein 8-Bitter und damit ein No-endian.
>
> Er ist ziemlich no-endian, ja, ...

...und die Stellen, an denen er selbst eine Endianess vorgibt, hast
du ja bereits im dritten Posting ganz oben genannt.  Will wohl bloß
keiner wahr haben.

von Michael Wilhelm (Gast)


Lesenswert?

Kann man, da es hier ja um Bitfelder geht, das beim GCC evtl. 
einstellen? beim IAR habe ich eine Pragma-Direktive, die mir das Bitfeld 
"umdreht".

MW

von Andreas K. (a-k)


Lesenswert?

Michael Wilhelm wrote:

> Kann man, da es hier ja um Bitfelder geht, das beim GCC evtl.
> einstellen?

Gewissermassen. Da der GCC quelloffen ist, bleibt es dir unbenommen, 
eine eigene Version zu erstellen, die deinen Wünschen entspricht. ;-)

von Falk B. (falk)


Lesenswert?

@ Christian (Gast)

>Ok, weil die Frage mit den Masken aufkam:

>so sieht meine Maske im Mikrocontroller aus:

Also innerhalb eines BYTES wird gar nichts gedreht, weder bei Big noch 
Little Endian. ABER, da nicht festgelegt ist, WO im Byte der Compiler 
die Bits hinlegen soll, kann er das ad libidum machen. Was zwei 
verschiedene Compiler auch tun.

-> Solche Unions und Bitfummelein manch man anders. Über #defines und 
Bitmasken.

>Beide Codeabschnitte werden vom Gcc kompiliert... Jedoch einmal für den
>x86 und einmal für den µC.

Naja, die haben zwar den gleichen Namen aber unter der Haube 
verschiedene Back ends.

MFG
Falk

von Peter D. (peda)


Lesenswert?

Jörg Wunsch wrote:

> ...und die Stellen, an denen er selbst eine Endianess vorgibt, hast
> du ja bereits im dritten Posting ganz oben genannt.  Will wohl bloß
> keiner wahr haben.

Es gibt Stellen, z.B. in den 4 Registerpaaren oder wie ein Call Adressen 
pusht, die indirekt nen Endian haben.

Es kostet aber kein einziges Byte mehr, wenn der Compiler für 
SRAM-Variablen den Endian andersrum festlegt, da die immer nur byteweise 
gelesen werden können.

Daher bin ich der Meinung, der Endian des AVR ist nirgends in Stein 
gemeißelt, sondern der Compiler kann ihn nach belieben festlegen.


Peter

von Peter D. (peda)


Lesenswert?

Christian wrote:

> Ich musste die Reihenfolge der Bits der Maske ändern, da die Maske sonst
> bei dem gleichen Byte-Wert andere Ergebnisse ausgespuckt hat...

Ja, das ist die persönliche Freiheit des Compilers.

Aber auch dafür gibt es eine Lösung.
Man definiert die Variablen nicht direkt in einer Union, sondern als 
Elemente einer vorher definierten struct.

Dann muß man nur für jeden Compiler einmal die Elemente in dieser struct 
umdefinieren, fertig.


Ein Beispiel (in sbit.h) findest Du hier:

Beitrag "LCD Treiber Routine 4*40"


Wenn mans ganz sauber machen will, definiert man diese Struct in 
Abhängigkeit vom Compilernamen.


Peter

von Kai G. (runtimeterror)


Lesenswert?

Gibt noch ein paar 16-Bit-Befehle, bei denen das Endianesisch zumindest 
für die Assemblerprogrammierung meiner Meinung nach relevant ist:

Bei der Multiplikation gilt:
R0 = Product Low
R1 = Product High
[R1:R0] also Little Endian

Bei ADIW und SBIW gilt ebenfalls:
Rd+1:Rd := Rd+1:Rd +- K
ist Little Endian

Und die Doppelregister
X = [R27:R26]
Y = [R29:R28]
Z = [R31:R30]
auch Little Endian

Da die Register auch im globalen Adressraum eingeblendet werden, kann 
hier meiner Meinung nach schon von einer little endian-Architektur 
gesprochen werden.

Ob man die Stackreihenfolge dann big endian nennt sei mal dahingestellt.

Gruß

Kai

von Falk B. (falk)


Lesenswert?

@ Peter Dannegger (peda)

>Wenn mans ganz sauber machen will, definiert man diese Struct in
>Abhängigkeit vom Compilernamen.

Wäre es nicht sinnvoller, mit #defines und Bitmasken zu arbeiten?

MFG
Falk

MFG
Falk

von Christian (Gast)


Lesenswert?

Sorry, dass ich das jetzt grad noch nicht ganz gerallt
Aber vielleich stehe ich zum Nachmittag auch auf meiner Leitung...

Ich kann doch nicht dem Compiler überlassen, wie rum er meine Bits im 
Speicher hinterlegt?!?

Grüße

Christian

von Karl H. (kbuchegg)


Lesenswert?

Christian wrote:

> Ich kann doch nicht dem Compiler überlassen, wie rum er meine Bits im
> Speicher hinterlegt?!?

Gegenfrage: Warum nicht?

Solange du dich immr nur auf ein und derselben Maschine
tummelst und immer denselben Compiler verwendest, ist es
doch (weitgehend) egal. C enthält viele solche Dinge, die
im Ermessen des Compilers bzw. des Compilerbauers liegen.
Das hat sein Gutes denn dadurch bleibt die Sprache von
Besonderheiten einer bestimmten Architektur frei und der
Compilerbauer kann sich für eine bestimmte Architektur
eine optimale Strategie überlegen.
Das hat aber auch sein weniger Gutes, indem man einen Teil
der Kontrolle als Programmierer abgeben muss.

In dem Moment, in dem Datenübertragung auf eine andere
Maschine ansteht, und man die unbedingt binär machen
will, hat man dann meist sowieso das eine oder andere
kleine Problem.

von Stefanie B. (sbs)


Lesenswert?

>>persönliche Freiheit des Compilers.


Aha!

Schützt die Compiler!
Gebt ihnen Wahlrecht ab 18!
Gleichheit für alle!!

;-)

[duck & wech]


-stef

von Karl H. (kbuchegg)


Lesenswert?

Stefan B. wrote:
>>>persönliche Freiheit des Compilers.
>
>
> Aha!
>
> Schützt die Compiler!
> Gebt ihnen Wahlrecht ab 18!
> Gleichheit für alle!!

Weils gerade in einem anderen Fred angesprcohen wurde
(und ich der Übeltäter war).

Es muss CompilerInnen heissen :-)

> [duck & wech]

[noch mehr duck aber dafür nicht mehr ganz so schnell wech]

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.