EmbDev.net

Forum: ARM programming with GCC/GNU tools Size of structures with gcc arm elf 4.1.0?


von Adrianes D. (adentoom)


Rate this post
useful
not useful
Hi,

I trapped in with the following:

#pragma pack(1)
typedef unsigned char uc_String[21];

typedef struct
{ unsinged char uc_MsgCmd;

}

von Adrianes D. (adentoom)


Rate this post
useful
not useful
Sorry, the mail was incomplete, here I go again...

Can anybody tell me if I'm going wrong or maybe trapped into a compiler
error?

I trapped in with the following:

//------------ Header File ---------------
#pragma pack(1)
typedef unsigned char tauc_String[21];

typedef struct
{
    unsinged char uc_MsgCmd;
    tauc_String   auc_String;
}tst_PackedStruct;

typedef tst_PackedStruct tast_PackedStructArray[2];
#pragma pack()


//------------ C-Source ------------------

#include "Header File.h"

tast_PackedStructArray ast_PackedStructArray = {0};

void TestFunc (void)
{
    // the result in i will be 24 -> WRONG
    int i = sizeof(tst_PackedStruct);

    // the result in i will be 24 as well,
    // don't care to much but to me this seems to be wrong to.
    i =  (unsigned char *) &PackedStructArray[1]
       - (unsigned char *) &PackedStructArray[0];

}

von Martin Thomas (Guest)


Rate this post
useful
not useful
Adrianes den Toom wrote:
>...
> #pragma pack(1)
>...
> #pragma pack()

As far as I know gcc does not support a pack pragma.

Did you read the gcc-Documentation about variable-attributes (
_attribute_ ((packed)) )?

Martin Thomas

von Clifford S. (clifford)


Rate this post
useful
not useful
#pragma directives are always compiler specific (I imagine that you wuld
have got at least an unsupported pragma warning at compilation).
Moreover the devlopers of GCC have made a concious decision to avoid
implementing any #pragma directives where possible.

Refer to
http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Function-Attributes.html#index-g_t_0040code_007b_0023pragma_007d_002c-reason-for-not-using-1835
for the justification, and
http://gcc.gnu.org/onlinedocs/gcc-4.1.0/gcc/Variable-Attributes.html#index-g_t_0040code_007bpacked_007d-attribute-1860
for the solution.

Clifford

von Adrianes D. (adentoom)


Rate this post
useful
not useful
Clifford Slocombe wrote:
> #pragma directives are always compiler specific (I imagine that you wuld
> have got at least an unsupported pragma warning at compilation).
> Moreover the devlopers of GCC have made a concious decision to avoid
> implementing any #pragma directives where possible.
>
> Refer to ...

Hi Clifford,

thanks for your info.

But:

1. There are no warnings about the #pragma pack(1) / #pragma pack()
directives.

2. If it had no effect the structure being affected the following:

   typedef unsigned char tauc_String[21];

   typedef struct
   {
      unsinged char uc_MsgCmd;
      tauc_String   auc_String;
   }tst_PackedStruct;

   ought result in a structure of 4 + 24 Bytes -> 28 Bytes, due to the
alignment
   of both elements...

3. _attribute_ ((packed)) will result in gcc-arm-elf 4.1 telling you
that it is ignoring the attribute when applied to typedefs or variable
declaration. Of course this only makes 'real' sense if it is applicable
to typedefs as well.

The structures are used for communication with other machines and being
sent over different interfaces...
I need them packed to make the communication modules work at all, if not
the MSG format of Arm systems is incompatible with existing systems,
although structures are the same... (big Endian / little endian is
annother issue of course...)

regards,
   A. den Toom

von Adrianes D. (adentoom)


Rate this post
useful
not useful
Adrianes den Toom wrote:


> 3. _attribute_ ((packed)) will result in gcc-arm-elf 4.1 telling you
> that it is ignoring the attribute when applied to typedefs or variable
> declaration. Of course this only makes 'real' sense if it is applicable
> to typedefs as well.

OK,- it should look like this:

typedef struct _attribute_ ((_packed_))
{
   ...
} tst_SomeStruct;


THIS does work with WINARM 4.0.2 and probably with 4.1.0, too.

regards.

A. den Toom

von Clifford S. (clifford)


Rate this post
useful
not useful
> 1. There are no warnings about the #pragma pack(1) / #pragma pack()
> directives.
Yes, sorry, I checked the manual you need the -Wunknown-pragmas option,
this is not set by -Wall.

> 2. If it had no effect the structure being affected the following:
> ...
> 3. _attribute_ ((packed)) will result in gcc-arm-elf 4.1 telling you
> ...
It perhaps would have been useful if you had posted the code with your
attempt at using __attrubute((packed)), rather than the original code.
However perhaps Mr. den Toom has solved it for you.

> The structures are used for communication with other machines and being
> sent over different interfaces...
> I need them packed to make the communication modules work at all, if not
> the MSG format of Arm systems is incompatible with existing systems,
> although structures are the same... (big Endian / little endian is
> annother issue of course...)

You may solve the packing problem in this way, but you will find that
the endianness solution is less straightforward, and renders the packing
solution irrelevent. To solve both the endian and packing issue, it is
normal to use a serialiser/deserializer routine, so that you send each
field byte-by-byte in your chosen order rather than sending whole
structures which may not match between different platforms. It may seem
a lot of work, but it is much more portable and robust under
maintenance; so it pays dividends in the end. C++ is particularly suited
to this approach because the serialise/deserialise routines can be
member functions of the data class you want to transmit (and you can
loose all that typedef nonsense ;-) ). The same routines are useful for
saving objects to disk also.

Clifford

von Adrianes D. (adentoom)


Rate this post
useful
not useful
Clifford Slocombe wrote:
>> 1. There are no warnings about the #pragma pack(1) / #pragma pack()
>> directives.
> Yes, sorry, I checked the manual you need the -Wunknown-pragmas option,
> this is not set by -Wall.

yes, maybe, but why does it evaluate to 24 instead of 28 with the Winarm
gcc 4.0.2?
Remember, both - the unsigned char and the unsigned char[21] should then
be aligned to 4 Byte boundary. Resulting in 4 bytes for the uchar and 24
Bytes for the uchar[].

I spoke to a colleague who compiled the 4.0.2 himself and he gave me the
executables,- they seemed to work out of the box with the #pragma
pack(1) directive and evaluated the size to 22 ...
He claimed to have it taken right from the gnu archive and swore not to
have modified anything.


> It perhaps would have been useful if you had posted the code with your
> attempt at using __attrubute((packed)), rather than the original code.
> However perhaps Mr. den Toom has solved it for you.

well, thats me in both cases :-).

> You may solve the packing problem in this way, but you will find that
> the endianness solution is less straightforward, and renders the packing
> solution irrelevent.

yes, you're dammned right :-).

> To solve both the endian and packing issue, it is
> normal to use a serialiser/deserializer routine, so that you send each
> field byte-by-byte in your chosen order rather than sending whole
> structures which may not match between different platforms.

I agree, but I have to code in C...
Still this does not mean that in C it is impossible to write clean
serializer and deserialisers.
But I'm also bound to the directives given to me,- not to touch the old
code if there is any chance to avoid it.

Furthermore I just have to code a rather small subset of messages, so I
decided
to go for the structured version and put it on top of the existing code.

Anyway, thanks for your hints, they put me on the right track to solve
my issue.

regards,
   A. den Toom

von Clifford S. (clifford)


Rate this post
useful
not useful
Adrianes den Toom wrote:
> Clifford Slocombe wrote:
>>> 1. There are no warnings about the #pragma pack(1) / #pragma pack()
>>> directives.
>> Yes, sorry, I checked the manual you need the -Wunknown-pragmas option,
>> this is not set by -Wall.
>
> yes, maybe, but why does it evaluate to 24 instead of 28 with the Winarm
> gcc 4.0.2?
> Remember, both - the unsigned char and the unsigned char[21] should then
> be aligned to 4 Byte boundary. Resulting in 4 bytes for the uchar and 24
> Bytes for the uchar[].
You cannot maks such assumptions about byte alignment unless you have
explicitly specified a particular alignment. The compiler is free to
align data in any way it chooses - to suggest the alignment was
'incorrect' is itself incorrect. Typically alignment is used to achieve
optimal code generation for performance. The actual alignment will
depend on the compiler, the target, and the compiler options. For
example setting the ARM architecture, and/or thumb mode options makes
different instructions available. If the processor can perform 16bit
writes as efficiently as 32, then the likley alignment will be 2. I once
wrote some FLASH memory managment that failed to work - it turned out
that in ARM7 mode, the compiler generated 16bit writes from two 8bit
instructions, which resulted an invalid programming sequence, setting it
corretly to ARM9 fixed the problem.

>
> I spoke to a colleague who compiled the 4.0.2 himself and he gave me the
> executables,- they seemed to work out of the box with the #pragma
> pack(1) directive and evaluated the size to 22 ...
> He claimed to have it taken right from the gnu archive and swore not to
> have modified anything.
There may be many reasons for this as explained, but #pragma pack(1) was
not one of them. More by luck than judgement I would suggest.

>> It perhaps would have been useful if you had posted the code with your
>> attempt at using __attrubute((packed)), rather than the original code.
>> However perhaps Mr. den Toom has solved it for you.
>
> well, thats me in both cases :-).
>
Oh, yes, sorry. You only latterly started signing at the bottom, and you
seemed to be answering your own question!



Good luck. And remember anyone that tells you that C++ is unsuitable for
embedded systems is wrong! ;-)

Clifford

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.