Forum: Mikrocontroller und Digitale Elektronik ARM7 kopieren von 32bit-Zahlen


von Andy (Gast)


Lesenswert?

Hallo zusammen
ich bin hier langsam Bridget Jones - am Rande des Wahnsinns.  :(

Auf meinem ARM7 versuche ich einfach, einem unsigned long den Wert eines 
anderen zuzuweisen.
LocalIP ist eine globale Variable, msg->yiaddr ein unsigned long in 
einem Puffer. (Ihr seht schon, riecht nach DHCP...)
1
LocalIP = msg->yiaddr;
2
DEBUG("IP");
3
UART0_WriteByte(LocalIP==msg->yiaddr);
4
UART0_WriteBuffer((unsigned char*)&LocalIP, 4);
5
UART0_WriteBuffer((unsigned char*)&msg->yiaddr, 4);
Jedenfalls liefert die Vergleichsausgabe 1 (LocalIP==msg). Soweit 
korrekt.
Wenn ich aber die Werte über UART anzeigen lasse, dann fehlt 
(mindestens) das unterste Byte, das oberste Byte ist korrekt. Die beiden 
dazwischen sind vorher und hinterher korrekterweise 0.
Wenn ich die Zuweisung mit memcpy mache, ist das Ergebnis das gleiche. 
Alle Kombinationen mit volatile bringen auch nichts.
Die Ausgabe deckt sich übrigens mit dem Verkehr auf dem Netzwerk - alo 
kein Problem der UART-Funktionen. Sonst hätte ich mit dem Schmuß auch 
gar nicht erst angefangen.  ;)

Sieht jemand, wo mein Hirn aufhört und mein Fehler anfängt?  :(
Danke!
Andy

von Helmut L. (helmi1)


Lesenswert?

Versuch mal folgenden Code


unsigned char Buffer[4]

Buffer[0] = (unsigned char) LocalIP;
Buffer[1] = (unsigned char) (LocalIP >> 8);
Buffer[2] = (unsigned char) (LocalIP >> 16);
Buffer[3] = (unsigned char) (LocalIP >> 24);


UART0_WriteBuffer(Buffer, 4);


Gruss Helmi

von Andy (Gast)


Lesenswert?

Hallo Helmi,
Danke für die Antwort. Ich werde es nachher noch ausprobieren.
Allerdings ist es glaube ich etwas am Problem vorbei.

LocalIP und msg->yiaddr sind beides unsigned long. Wenn die UART-Routine 
da ein Problem hätte, müßte sie doch bei beiden etwas falsches ausgeben.
Außerdem hatte ich das nur zur Fehlersuche. Das "Original"-Problem 
war/ist, daß LocalIP später weiterverwendet wird und genau da der Fehler 
auftauscht. Außerdem stimt die UART-Ausgabe mit dem überein, was übers 
Netz geht.

N.B. Das ganze ist ähnlich schon gelaufen. Der DHCP lief die ganze Zeit 
unter uIP. Jetzt stelle ich gerade auf meinen eigenen Stack um. Und 
jetzt tritt der Fehler auf. Vorher var LocalIP vom Typ uip_ipaddr_t, 
daher auch das memcpy().

Interrupts schließe ich aus, da das ganze Zeug in einem IRQ läuft und es 
keine FIQs gibt. Stack-Problem eigentlich auch nicht, weil es 1. in 
allen anderen Sockets funktioniert, und 2. LocalValue mitten in den 
Daten steht. Davor und dahinter ist alles in Ordnung. Außerdem müßte der 
Stack jetzt sogar kleiner sein, weil mein eigener IP-Stack 2 Tiefen 
weniger braucht.

Habe probehalber auch mal den Bereich vor msg->yiaddr mit -1 gefüllt, um 
zu sehen, ob er vielleicht "in die falsche Richtung" kopiert vom Zeiger 
aus gesehen. Ist aber auch nicht so. Wenn ich LocalIP bei der 
Initialisierung fest beschreibe, dann funzt es.

Alles sehr strange - wer hätte gedacht, daß ich jetzt schon für a=b zu 
doof bin.  :(

von Tim S. (maxxie)


Lesenswert?

Ist msg->yiaddr (4Byte) aligned?
Sonst schlägt das lesen fehl, damit ist auch der compare true (weil der 
Fehler beidemale auftritt) aber der Wert ist eben nicht byteweise gleich 
mit dem was an der unaligned addresse steht.

von tuppes (Gast)


Lesenswert?

Ich habe nicht so genau verstanden, welche Bytes verfälscht werden. Aber 
ich kenne solche Mysterien. Ursache war immer misalignment in gepackten 
Strukturen. Also 32-Bit-Felder, die nicht auf 4-Byte-Grenzen 
ausgerichtet sind.

Könnte das bei dir der Fall sein?

von Andy (Gast)


Lesenswert?

Hallo Tim,
das ist noch eine gute Idee. Gleich mal nachschauen.
Ansonsten müßte ich byte-weise kopieren...

Oder ich habe woanders einen Fehler. Der Netzwerk-Puffer ist ja von Haus 
aus aligned, die Netzwerk-Geschichten sind von Haus aus auch ziemlich 
alle an 16bit(!) ausgerichtet.
Fragt sich nur, warum dann memcpy scheitert. Arbeitet das nicht 
byteweise?

Ich frage deshalb so blöd, weil ich den Fehler dann wahrscheinlich noch 
an anderer Stelle kriege.

von Andy (Gast)


Lesenswert?

So, kleiner Nachtrag.
&msg->yiaddr = 0x40001f3e, also wirklich im Puffer und an 16bit 
ausgerichtet.
Das wirds wohl sein.

Danke!

von Andy (Gast)


Lesenswert?

Anscheinend wurde der Fehler nicht von mir ge/erfunden:   ;)

http://gcc.gnu.org/ml/gcc-bugs/2000-03/msg00155.html

(falls nochmal jemand über diesen Thread stolpert)

von Helmut L. (helmi1)


Lesenswert?

>Fragt sich nur, warum dann memcpy scheitert. Arbeitet das nicht
>byteweise?

Wenns gut gemacht ist nicht. Dann werden nur die ersten nicht alignment 
Bytes einzeln kopiert dann gehts dann 32Bit mässig weiter.

von Andy (Gast)


Lesenswert?

Das läßt sich ziemlich gut austricksen, wenn man die (nicht-aligned) 
Struktur nach (char*) castet.
Dann funzt es auch mit memcpy().

Juju, es läuft!  freu
Genug Erfolg für heute. Danke Euch beiden und noch einen schönen Abend! 
;)

Andy

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.