Hey Zusammen :)
Es ist spät, ich habe mir lang den Kopf zerbrochen und nun hoffe ich von
Euch auf nen kleinen Tip :)
Ich habe ein Array data[8]. Dies ist gefüllt mit ( 0x01, 0x00, 0x0,
0x50, 0x00, 0x00, 0x00, 0x00).
data[0] ist also 0x01, data[3] ist 0x50.
In einem Fall stellt data[0...3] den Inhalt eines uint32_t dar.
Mein Gedanke: Die Daten liegen ja im RAM hintereinander, sollte doch ein
leichtes sein.
uint32_t test;
test = data[0]; ->> warn versucht, klappt natürlich nicht
test = (uint32_t){data[0]}; ->> auch nicht
uint32_t* ptr = data[0];
test = *prt --> test wird mit (0x75, 0x01, 0x00, 0x00) geladen.
uint32_t* ptr = data[1];
test = *prt --> test wird endlich mit (0x01, 0x00, 0x00, 0x50)
geladen. Dann resetet der µC
uint32_t* ptr = &data[0];
test = *prt --> test ist nun (0x50, 0x00, 0x00, 0x01) und ab diesem
Moment bin ich total durcheinander... evt ist es auch einfach zu spät...
Aber evt habt Ihr nen Rat/Vorschlag für mich?
Danke und Gruß
Danny
Integers werden auf dem von dir benutzten Prozessor little-endian, d.h.
beginnend mit dem niederwertigsten Byte im Speicher abgelegt. 0x01 wird
somit als das niedrigstwertige und 0x50 als das höchstwertige Byte
betrachtet, so das die gelesene uint32_t-Wert 0x50000001 ist.
Vielen Dank für die schnellen Antworten!
Ich bin grad völlig verblüfft, bislang war für mich "big-endian" die
einzig denkbarer Art und ich bin jahrelang damit in kein Problem
gelaufen...
Das muss ich mir ausgeruht morgen früh nochmal selbst verdeutlichen :)
Danny schrieb im Beitrag #3367193:
> Ich bin grad völlig verblüfft, bislang war für mich "big-endian" die> einzig denkbarer Art und ich bin jahrelang damit in kein Problem> gelaufen...
Was für Exoten-Prozessoren hast du denn jahrelang benutzt?
Oliver
Oliver S. schrieb:> Was für Exoten-Prozessoren hast du denn jahrelang benutzt?
Also, vor 20 Jahren war mal der Motorola 68000 (Atari, Amiga, Mac usw.)
sehr populär (grad bei Assembler Programmierer). Der hatte Big-Endian.
Oliver S. schrieb:> Was für Exoten-Prozessoren hast du denn jahrelang benutzt?
Sehr gebräuchliche Prozessoren mit Big Endian sind:
- 68000
- PowerPC
- SPARC
Viele ARM-Prozessorkerne lassen sich wahlweise als Big oder Little
Endian konfigurieren, teilweise per externem Endianess-Pin. Beispiel
Alcatel MTC-20285. Auch StrongARM- und Xscale-Prozessoren werden oft in
Big Endian verwendet, gerade in Netzwerkkomponenten, da die Header von
TCP/IP-Paketen auch in Big Endian (sog. Network Byte Order) spezifiziert
sind.
Bei einigen MIPS-Prozessoren kann die Endianess sogar für jeden Prozess
separat eingestellt werden, z.B. Toshiba TX39.
Nachtrag: Auch aktuelle ARM-Kerne beherrschen beide Betriebsarten,
exemplarisch für den Cortex-A9:
http://infocenter.arm.com/help/topic/com.arm.doc.ddi0407e/BABCIEHF.html
Weil noch keiner darauf eingegangen ist: DirkB hat hier völlig recht.
Ganz unabhängig davon ob der TE einen kleinen oder großen Indianer
programmiert, hat er auch Daten und Adressen durcheinandergewürfelt.
So hat er z.B. hier:
Danny schrieb:> uint32_t* ptr = data[1];> test = *prt
den Inhalt von data[1] (also vermutlich ein uint_8t) als Adresse
eines uint32_t interpretiert. Und das geht in jedem Fall in die Hose.
Wenn es das erwartete Ergebnis geliefert hat, dann auf jeden Fall nur
zufällig.
XL
Mensch, da habe ich ja etwas losgetreten :)
Obwohl ich mir fest vornahm den Ziel-µC zu nennen, hab' ich's doch
vergessen... Es ging/geht um einen Atmel AVR (Mega8 / Mega 128)...
Und tatsächlich hatte ich diese Probleme in den ganzen letzten Jahren
nicht, aber meiner Recherche nach kann das auch gut sein, denn Probleme
treten ja nur auf wenn Daten zwischen zwei Unterschiedlichen Systemen
getauscht werden.
Auch dieses Mal wäre ich sicher nicht darüber gefallen, wenn ich mich
nicht zu Testzwecken einmal als "fremdes System (big-endian-denkend)"
eingemischt hätte :)
einmal noch für mein Verständnis Dirk's Lösung:
uint32_t test;
test = *(uint32_t*)(&data[0]);
mit (uint32_t*)(&data[0]); lade ich einen pointer auf einen uint32_t mit
der Startadresse von data[0]. Durch den * vor dem ganzen wird der
Ausdruck zum 32 Bit breiten Inhalt, auf den der Pointer zeigt. Um das
big/little-endian muss ich mich dann zu Fuß kümmern.
Hab ich das soweit richtig verstanden?
Danke nochmal
Danny schrieb:> uint8_t
Dann wirst du wohl mindestens ein Warning bekommen. Und dann wird sich
das ganze nicht so verhalten, wie du dir das (wahrscheinlich)
vorstellst. Benutze doch einen Pointer vom selben Typ.
Danny schrieb:> dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden> 8bit-Werten
Ah ja, mein Fehler. Klar, deshalb ja auch die Frage nach Endianess.
Ziehe meinen Klugschiss zurück :)
Ro B. schrieb:> Danny schrieb:>> dann liest er aber kein 32bit-Wert aus 4 hintereinander liegenden>> 8bit-Werten>> Ah ja, mein Fehler. Klar, deshalb ja auch die Frage nach Endianess.> Ziehe meinen Klugschiss zurück :)
Würds dann aber eher sauber coden und dann shiften/adden. Oder siehst du
deine Vorgehensweise als optimiert?
Danny schrieb:> in einer Zeile, richtig?
Ja.
Mehr wollte ich auch nicht machen.
Damit änderst du noch nichts an der Bytereihenfolge.
Wenn du zwischen verschiedenen Systemen die Werte austauschen willst,
solltest du dir mal die Funktionen wie htonl oder ntohl ansehen.
@Dirk: danke für den Tip, da werde ich mal vor dem schlafen gehen nach
schauen :)
für den Moment habe ich mir geholfen, indem ich nicht die Bytes selbst
"errechnet" habe sondern per (uint32_t[]){ 200 } eingefügt...