Forum: Mikrocontroller und Digitale Elektronik void pointer cast führt zu "hard fault"


von Marcel (Gast)


Lesenswert?

Hallo zusammen,

ich möchte gerade eine SW von einem AVR auf einen ARM (LPC1114) 
portieren. Soweit so klar. Jetzt wird aber ein void Pointer mehrfach 
geachtet z.B. von uint8 auf uint16 oder auch uint32. Beim ersten cast 
passiert nicht und alles ist gut. der 2. cast geht aber in die Hose und 
der uC wirft einen "hard fault" Irq. Klar jetzt kann ich durch den code 
gehen und jeden cast raus werfen....aber vielleicht hat ja jemand hier 
ne Idee wie es besser geht.

Gruß Marcel

von Frickelfritze (Gast)


Lesenswert?

Marcel schrieb:
> aber vielleicht hat ja jemand hier
> ne Idee wie es besser geht.

Bei Prosa-Coding wie hier

Marcel schrieb:
> Jetzt wird aber ein void Pointer mehrfach
> geachtet z.B. von uint8 auf uint16 oder auch uint32.

sicherlich nicht.

von Nase (Gast)


Lesenswert?

Klingt nach einem Problem mit dem Alignment..

von PittyJ (Gast)


Lesenswert?

Der Unterschied zwischen geraden und ungerade Adressen ist bekannt?

von Rolf M. (rmagnus)


Lesenswert?

Die Beschreibung ist etwas wirr.

Marcel schrieb:
> Jetzt wird aber ein void Pointer mehrfach geachtet z.B. von uint8 auf
> uint16 oder auch uint32.

Wird wirklich der Pointer in uint8 gecastet oder doch eher in einen 
Pointer auf uint8?

> Beim ersten cast passiert nicht und alles ist gut. der 2. cast geht aber
> in die Hose und der uC wirft einen "hard fault" Irq.

Warum wird der Zeiger denn überhaupt mehrmals gecastet? Tritt der Fehler 
wirklich beim Cast auf oder erst danach beim Zugriff? Klingt für mich 
nach einem Misaslignment-Problem.

> Klar jetzt kann ich durch den code gehen und jeden cast raus
> werfen....

Ja? Kannst du? Warum sind die Casts dann überhaupt drin, wenn die 
einfach so rausgeworfen werden können? Wenn die wirklich unnötigerweise 
drin sind, wäre es unabhängig von der Portierung sinnvoll, sie zu 
entfernen.

von Marcel (Gast)


Lesenswert?

Erstmal danke für die Hilfe, also die SW die zu probieren ist  ist nicht 
von mir. Ich hätte das mit Union und struct und entsprechendem Zugriff 
gelöst.
Rauswerfen ist möglich erfordert aber viel bit geschupse....
Naja das mit dem missaligment ist mir jetzt nicht ganz klar. Kann mir da 
einer kurz auf die Sprünge helfen.

Danke und Gruß Marcel

von klausr (Gast)


Lesenswert?


von Tassilo H. (tassilo_h)


Lesenswert?

Du hast einen Cortex M0 Prozessorkern, der kann keine unaligned Zugriffe 
auf Words oder DWords. Aligned heißt, ein word (2 bytes) muß an einer 
durch 2 teilbaren Adresse liegen und ein dword (4 bytes) an einer durch 
4 teilbaren Adresse.
Ein 32-Bit Prozessorkern holt sich ja immer 32 bit parallel. Ein 
unaligned-Zugriff auf ein word oder dword könnte also je nach Adresse 
bedeuten, daß die Daten aligned sind (d.h. ein 32-bit Zugriff reicht) 
oder auch nicht (d.h. 2 32-bit Zugriffe nötig). Die Extra-Logik zum 
Zusammenbauen der Daten im zweiten Fall fehlt beim Cortex M0.

Normalerweise sorgt der Compiler dafür, daß die Adressen von Variablen 
passend aligned sind. Wenn du aber mehrere Byte-Variablen in den 
Speicher legst, weiß der Compiler von keinem nötigen Alignment und legt 
die an irgendeine Adresse. Wenn du dann auf word/uint16_t oder 
dword/uint32_t castest, kann der Zugriff fehlschlagen mit einem hard 
fault.

: Bearbeitet durch User
von PittyJ (Gast)


Lesenswert?

Mach es einfach richtig und trickse nicht herum. Dann ist das Problem 
gelöst und es kommt nicht 5 Jahren dein Nachfolger und jammert hier 
wieder.

Benutze richtige Datenstrukturen und überlasse dem Compiler den Zugriff. 
Ein Cast ist Tabu.

von PittyJ (Gast)


Lesenswert?

Noch eine Info: die Exception bei unaligntem Zugriff gab es bereits vor 
30 Jahren bei z.B. dem 68000 (Atari ST, Amiga). Das ist keine Erfindung 
von heute.
Ein erfahrener Programmierer hätte also im Originalcode wohl auch schon 
darauf verzichtet. Anscheinend war dein Vorgänger nicht so erfahren.

von Marcel (Gast)


Lesenswert?

Ah danke für den Hinweis...das der Vortex M0 das nicht kann war mir echt 
nicht bewußt! Ist mein erster ARM den ich nutze. Habe beruflich nur mit 
anderen Rechnern zu tun (SPC58xx,V850,...) UND da macht keiner so scheiß 
mit void pointern 10fach hin und herbiegen!
Ne mein Nachfolger wird da mit 100%iger Sicherheit keine Probleme 
bekommen, ist ne private bastelei :). Wie auch immer ich bau es jetzt so 
um

uint8_t *pointr_pt8;

pointr_pt8 = &DaWoDatenHinSollen;

*pointr_pt8 = (Data32Bit & 0x000000ff);
pointr_pt8++;
*pointr_pt8 = (Data32Bit & 0x0000ff00) >> 8;

usw....

Erstmal Vielen dank.
Marcel

von at nur (Gast)


Lesenswert?

>*pointr_pt8 = (Data32Bit & 0x000000ff);
>pointr_pt8++;
>*pointr_pt8 = (Data32Bit & 0x0000ff00) >> 8;
>
>usw....

Aber nur, wen Endianness gleich!

von Jim M. (turboj)


Lesenswert?

Einfacher ist die Verwendung von memcpy() oder memmove().

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.