mikrocontroller.net

Forum: Compiler & IDEs Endianess Umwandlung notwendig?


Autor: Le_Q (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

ich hätte mal eine Frage. Ich arbeite mit einem Cortex M3, dieser 
arbeitet im little endian. Jetzt bekomme ich aber externe Daten im Big 
endian in den Speicher gelegt. Wenn ich jetzt mit diesen Daten arbeiten 
möchte, muss ich die zuerst konvertieren, oder? Weil ansonsten 
interpretiert der Cortex einen falschen Wert. Es handelt sich um 16Bit 
Werte. So wie ich es verstehe muss ich quasi "nur" das erste mit dem 
zweiten Byte vertauschen um die Daten in den little endian zu bringen.

Also:
Der Wert 43707 wird im big endian gespeichert, also 0xAABB. Wenn ich 
diesen Wert jetzt vom Cortex interpretieren lasse würde der 0xBBAA also 
48042 lesen.

Ist dem so? Gibt es "standard" Funktionen dafür bzw. irgendwelche 
performanten implementierungen?

Wahrscheinlich lachen sich die meisten über die Frage kaputt... Deshalb 
möge man meine Unkenntnis entschuldigen.

Autor: Sven H. (dsb_sven)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst die Reihenfolge der Bytes umdrehen, vollkommen richtig. Die 
Frage ist, bekommst du auch mal 4 Byte Daten? Wenn ja wirds etwas 
komplexer, an sonsten einfach Bytes tauschen.

Da gibts verschiedene Lösungswege. Du könntest den int16_t mit 0xff 
"verUNDen" und in ein int8_t packen, den int16_t acht mal nach rechts 
schieben und dann den int8_t in den oberen Teil deines Wertes packen.

Was auch gehen würde, wäre ein union.
union byteToWord
{
 int8_t byte[2];
 int16_t word;
};

Oder so ;-) Bin grad nicht ganz Sattelfest mit unions.

Dann hättest du die Möglichkeit davon zwei zu erstellen und könntest mit
union2.word = DeinWertAusDemSpeicher;
union1.byte[1] = union2.byte[2];
union1.byte[2] = union2.byte[1];
DeineVariableZurVerarbeitung = union1.word;

Sicherlich gibt es noch viel viel bessere Varianten als meine hier ;)

Autor: Oliver (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sven H. schrieb:
> Sicherlich gibt es noch viel viel bessere Varianten als meine hier ;)

Eine Zwischenvariable wäre nicht schlecht ;-)

Oliver

Autor: Johann L. (gjlayde) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
GCC kennt ein __builtin_bswap32 für diesen Zweck

http://gcc.gnu.org/onlinedocs/gcc-4.4.4/gcc/Other-...

Autor: Marcus Harnisch (mharnisch) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Le_Q schrieb:
> Gibt es "standard" Funktionen dafür bzw. irgendwelche performanten
> implementierungen?

Assembler: REV16

Autor: Le_Q (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen herzlichen Dank an euch alle!

Ich werde die Varianten mal testen und schauen was für meinen Geschmack 
das beste ist. Aber ich denke es wird auf die REV16 Variante raus 
laufen. Damit ist der Code zwar nicht mehr CPU und Compiler independent, 
aber wenn man auf gute Performance aus ist, gestalltet sich das ohnehin 
schwer.

Nochmal Danke an alle. :o)

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> GCC kennt ein __builtin_bswap32 für diesen Zweck

Interessanterweise gibt es da eins für 32 und eins für 64 Bit, aber 
anscheinend keins für 16 Bit.

Autor: Le_Q (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sorry noch ne Frage. Ich habe mal geschaut wie die REV16 im Thumb2 
Instruction Set (Cortex-m3) implementiert ist.

Bytes in both halfwords
REV16 Rd, Rm
Rd[15:8] := Rm[7:0],
Rd[7:0] := Rm[15:8],
Rd[31:24] := Rm[23:16],
Rd[23:16] := Rm[31:24]

Der tauscht hier quasi alle 4 Byte eines 32 Bit Registers. Das macht 
insofern Sinn, also dass der Cortex 32Bit Register verwendet. Wieso 
heißt dann aber der Befehel REV16? Das Ergebnis stimmt natürlich wenn 
ich in beide Register 16 Bit Werte lade, allerdings werden hier 2 
Befehle ausgeführt, die man eigentlich nicht bräuchte. Oder bezieht sich 
das "16" hier allgemein auf die Vertauschung der 2 Bytes in den beiden 
16 bit Worten?

Nun gut, ich teste mal rum... ;)

Autor: A. K. (prx)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Le_Q schrieb:

> ich in beide Register 16 Bit Werte lade, allerdings werden hier 2
> Befehle ausgeführt, die man eigentlich nicht bräuchte.

Nö. Er macht zwar mehr als du für das Vertauschen der beiden unteren 
Bytes benötigst, aber das sind nicht 4 Befehle, sondern ist eine einzige 
Operation, die im Handbuch als 4 Operationen dargestellt wird.

In der gleichen Weise könntest du Shift-Operationen auch als
  d[31] = s[30]
  ...
  d[1] = s[0]
  d[0] = 0
darstellen und es wären dennoch keine 32 Befehle.

> das "16" hier allgemein auf die Vertauschung der 2 Bytes in den beiden
> 16 bit Worten?

Damit wird signalisiert, dass die Bytes innerhalb der 16-Bit Hälften 
vertauscht werden.

Autor: Le_Q (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ah ich verstehe. Ich dachte, dass REV16 ein Pseudo-OpCode ist, der in 
Wirklichkeit aus den 4 einzelnen besteht.

Danke für die Aufklärung.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.