Re: writing value to pointer

On ARM with GCC 2.95.3:

> uint16 * ptr1 = ( uint16 * ) & buffer[1];

If you lie to a computer, it will get you. You are telling gcc that ptr1 is a valid pointer to uint16, which it isn't.

*ptr1 = 0x1234; // Error, writes into buffer[0-1]

You are lucky it doesn't crash. Writing to a multi-byte item through a mis-aligned pointer invokes undefined behaviour.

How can I force the compiler to generate code, that works correct?

By writing correct code, perhaps?

uint16 val = 0x1234; memcpy(&buffer[1], &val, sizeof(val));

Cheers,

--
In order to understand recursion you must first understand recursion.
Reply to
Paul Pluzhnikov
Loading thread data ...

But when I do this:

#pragma pack(1) typedef struct{ uint8 c uint16 v; // unaligned short }MyType; #pragma pack()

MyType * ptr = buffer; ptr->v = 0x1234;

It work perfectly. Why does this work and the pointer-cast not?

Frank

Reply to
Frank Benoit

You can't. One of the "limitations" of the arm processors (I believe it affects all of them) is data must be aligned correctly. That is 16 bit values aligned on 16 bit boundaries, 32 bit values on 32 bit boundaries. In the case above, the arm processor effectively rounds the pointer down to a "correct" boundary. If you absolutely have to do this, you will need to use memcpy() or something similar to copy a byte at a time.

Blane.

Reply to
Blane Bramble

If the compiler designer wanted (I'm not claiming this is the case in any extant C compiler), the packed structure members could be marked as "unalgned" so that when the code generator is called it's told to do byte-by-byte accesses.

AFAIK, gcc doesn't do this. It would be awfully nice for filling in those communication headers...

--
Grant Edwards                   grante             Yow!  TAILFINS!!...click...
                                  at               
                               visi.com
Reply to
Grant Edwards

I don't know about the ARM, but there are CPUs (e.g. 68332) that just can't write 16 Bit values to odd addresses. So even if the compiler does what you want (you may look at the compiled code to verify this), the CPU will not execute it.

-Michael

Reply to
Michael Schnell

The compiler code is OK - see the generated assembly code with gcc -S.

Your problem is that the ARM hardware does weird things if you access a halfword (16 bits) or a fullword (32 bits) on a non-natural boundary. The halfword accesses assume that least significant bit of the address is zero, the fullword accesses assume that two least significant bits of the address are zeroes.

If you have a __attribute__((__packed__)) structure with non-aligned members, the compiler splits and packs the data in software, so a single item is accessed in small enough pieces to be aligned. This may lead to a fullword accessed as four discrete bytes.

The ARM ARM

David Seal, ARM Achitecture Reference Manual, Addison-Wesley, ISBN

0-201-73719-1

explicitly states that the result of an unaligned data access is UNDEFINED.

For ARM7TDMI, such as Atmel AT91, the behaviour is described in the ARM7TDMI Data Sheet, available at .

HTH

Tauno Voipio tauno voipio @ iki fi

Reply to
Tauno Voipio

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.