Forum: Compiler & IDEs Probleme mit Code-Portierung von AVR nach ARM--> Zeigerumwandlung


von Stefan H. (stefan_h16)


Lesenswert?

Hallo zusammen,

Ich versuche gerade den OpenMCP Code von AVR auf Cortex-M0 (LPC1115 um 
genau zu sein) zu portieren.

Dabei habe ich folgendes Problem:
Die Daten werden als char * buffer angeliefert (im einem konkreten 
Experiment Länge 149). Der Buffer ist auch in Ordnung ich kann in der 
Routine einen Dump davon ausgeben. Im IP Handler wird er dann 
konvertiert und macht Probleme:
1
//Zur Info
2
#define ETHERNET_HEADER_LENGTH    14
3
struct IP_header {
4
  uint8_t IP_Version_Headerlen;
5
  uint8_t IP_TOS;
6
  uint16_t IP_Totallenght;
7
  uint16_t IP_Identification;
8
  uint16_t IP_Flags_Fragmentoffset;
9
  uint8_t IP_TTL;
10
  uint8_t IP_Protocol;
11
  uint16_t IP_Headerchecksum;
12
  uint32_t IP_SourceIP;
13
  uint32_t IP_DestinationIP;
14
};
15
//Problemstelle
16
void ip( int packet_lenght ,  char *buffer )
17
  {
18
#ifdef PRINTF_DEBUG
19
int i;
20
printf("Ethernet buffer dump (size %d bytes):", packet_lenght);
21
for(i = 0;i<packet_lenght;i++)
22
  printf(" %d", buffer[i]);
23
printf("\n");
24
#endif
25
26
struct IP_header *IP_packet;
27
IP_packet = ( struct IP_header *)&buffer[ETHERNET_HEADER_LENGTH];
28
if ( IP_packet->IP_DestinationIP != myIP) //<-- Hier steigt das Programm reproduzierbar mit einem HardFault_Handler() aus
29
{
30
  #ifdef PRINTF_DEBUG
31
  printf("void ip (int, char *): Not for my IP\n");
32
  #endif
33
}
34
}

Kann mir jemand einen Hinweis geben woran das den liegt?

von Peter II (Gast)


Lesenswert?

Stefan H. schrieb:
> IP_packet = ( struct IP_header *)&buffer[ETHERNET_HEADER_LENGTH];

das ergibt doch keinen sinn? Warum sollte der Header nach der 
ETHERNET_HEADER_LENGTH beginnen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Deine Struktur ist nicht gepackt (#pragma pack), das aber ist bei 
Prozessorarchitekturen mit Wortbreiten > 8 Bit erforderlich, um ein 
bitgenaues Abbild Deiner Struktur zu erhalten.

Lass Dir mal sizeof (struct IP_header) ausgeben.

von Thomas S. (daimonion)


Lesenswert?

Versuch mal
1
IP_packet = ( struct IP_header *)buffer;

Oder liegt der Start von dem Struct im Buffer an der 14. Stelle im 
Array?

Passen die Zielspeicherstellen von buffer und von IP_packet?

von Oliver S. (oliverso)


Lesenswert?

Ich werf mal das Stichwort "alignment" in die Runde...

Oliver

von Stefan H. (stefan_h16)


Lesenswert?

Rufus Τ. Firefly schrieb:
> Deine Struktur ist nicht gepackt (#pragma pack), das aber ist bei
> Prozessorarchitekturen mit Wortbreiten > 8 Bit erforderlich, um ein
> bitgenaues Abbild Deiner Struktur zu erhalten.
>
> Lass Dir mal sizeof (struct IP_header) ausgeben.

Vielen Dank. Das scheint das Problem ersteinmal gelöst zu haben.
Btw:
1
printf("IP Header size: %d \n", sizeof(struct IP_header)); //<-- gibt 28 aus

von Rolf M. (rmagnus)


Lesenswert?

Peter II schrieb:
> Stefan H. schrieb:
>> IP_packet = ( struct IP_header *)&buffer[ETHERNET_HEADER_LENGTH];
>
> das ergibt doch keinen sinn? Warum sollte der Header nach der
> ETHERNET_HEADER_LENGTH beginnen?

Weil es sich um einen IP_header handelt, und der IP-Header halt nach 
dem Ethernet-Header kommt.

Rufus Τ. Firefly schrieb:
> Deine Struktur ist nicht gepackt (#pragma pack), das aber ist bei
> Prozessorarchitekturen mit Wortbreiten > 8 Bit erforderlich, um ein
> bitgenaues Abbild Deiner Struktur zu erhalten.

Man beachte, daß nicht jeder Prozessor mit Zugriffen auf Variablen mit 
falschem Alignment zurecht kommt.

von ... (Gast)


Lesenswert?

>printf("IP Header size: %d \n", sizeof(struct IP_header)); //<-- gibt 28 aus

siehste, und die struktur ist eigentlich nur 20Bytres groß. Das sind die 
zusätzlichen Padding-Bytes.. und die haben das Problem verursacht.


>Man beachte, daß nicht jeder Prozessor mit Zugriffen auf Variablen
>mit falschem Alignment zurecht kommt.
Mit so einem Kommentar macht man sich zwar wichtig, aber...... aach 
herje.
Bei ordnungsgemäßer Struktur-deklaration (packed) weiß der Compiler was 
er tut. Das missalginment ist dem Compiler doch bekannt....... und er 
kennt auch die Zielplatform...

von Rolf M. (rmagnus)


Lesenswert?

... schrieb:
> Bei ordnungsgemäßer Struktur-deklaration (packed) weiß der Compiler was
> er tut. Das missalginment ist dem Compiler doch bekannt....... und er
> kennt auch die Zielplatform...

In diesem speziellen Fall ist es dem Compiler vielleicht bekannt, aber 
allgemein gilt das erstmal nicht. Daß der Compiler jetzt extra für ein 
paar Spezialfälle entsprechenden Code generiert, darauf würde ich mich 
nicht verlassen. Ich hatte jedenfalls schon auf ARM-Prozessoren 
entsprechende Exceptions beim Versuch von Zugriffen mit falschem 
Alignment.

von Daniel A. (daniel-a)


Lesenswert?

Rolf Magnus schrieb:
> Ich hatte jedenfalls schon auf ARM-Prozessoren
> entsprechende Exceptions beim Versuch von Zugriffen mit falschem
> Alignment.

Der compiler weiss, was er tut. Das kann nur pasieren wenn man einen 
structmember mit falschem alignement referenziert, da dann die info des 
falschen alignements verloren geht.

Beim struct IP_header, wo und warum sind dort diese 6 bytes padding? Ich 
sehe nicht wo diese notwendig werden...

von Peter II (Gast)


Lesenswert?

Daniel A. schrieb:
> Beim struct IP_header, wo und warum sind dort diese 6 bytes padding? Ich
> sehe nicht wo diese notwendig werden...

 uint8_t IP_Version_Headerlen;
 uint8_t IP_TOS;

nach jeden Byte, wenn die CPU nur auf Gerade Adresse zugreifen kann.

von (prx) A. K. (prx)


Lesenswert?

... schrieb:
>>Man beachte, daß nicht jeder Prozessor mit Zugriffen auf Variablen
>>mit falschem Alignment zurecht kommt.
> Mit so einem Kommentar macht man sich zwar wichtig, aber...... aach
> herje.

Der Kommentar war zutreffend, da ...

> Bei ordnungsgemäßer Struktur-deklaration (packed)

... dies nicht erfolgte und der Cortex M0 bei misalignten Zugriffen 
aussteigt ...

> Das missalginment ist dem Compiler doch bekannt.......

... weil es dem Compiler ohne "packed" eben nicht bekannt ist. Ganz zu 
schweigen von der falschen Adresse.

Erschwerend kommt hinzu, dass auch "packed" nicht in jedem Fall hilft. 
Das sorgt nämlich nur dafür, dass er bei Inhalten, die ihm nun innerhalb 
der Structur als misaligned bekannt sind, entsprechend vorgeht. Auf 
innerhalb der Struktur korrekt alignte Komponenten kann auch bei 
"packed" normal zugegriffen werden.

Wenn also die gesamte Struktur schon misaligned ist, dann hilft auch 
"packed" nicht unbedingt. Und genau das kann hier der Fall sein, da ein 
Ethernet-Header kein Vielfaches von 4 lang ist und die Struktur per Cast 
aus einem Byte-Array an Offset 14 gefischt wird.

Manche Leute platzieren den Ethernet-Frame deshalb so, dass er bei
  (addr % 4) == 2
beginnt, weil dann die TCP/IP Header aligned sind. Bei PC-Prozessoren 
kann das sogar einen beträchtlichen Unterschied in der Performance 
ausmachen, da denen das Alignment zwar formal egal ist, aber misalingte 
Schreibzugriffe aufgrund der Arbeitsweise der CPU sehr langsam sein 
können.

: Bearbeitet durch User
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.