Using __attribute__((aligned(4))) on data structs

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

So here is what happened....I have a project compiled to give about 180KB code (+32KB bootloader)...for a 256K ATSAM21 32 bit chip.

Surprisingly the compiler warned me that one of the strucs did not align properly. So I checked the map file, and sure enough the structure was placed at an odd number boundary (address end with 7). This was the ONLY struct that was showing this.

 

A lot of my other structs start with COMPILER_PACK(1) set which I think is equivalent to __attribute__((packed(1)))...? COMPILER_PACK() is a AtmelStudio macro.

Anyways so I then force this particular struct to be __attribute__((aligned(4))) by adding it at the end of it before the terminating ; mark.

 

And then I do this for a lot of the other structs that I had originally had COMPILER_PACK(1) set on. I must note that whenever I do structs on these ARM chips I make sure they are properly padded with bytes to make sure the full size is always a multiple of 32bits.

 

Then after changing a lot of my previous structs from COMPILER_PACK(1) to __attribute__((aligned(4))) I noticed something truly surprising... my application code went from 180KB to ~150KB. That's like 15% space saving??? What the??

 

Can anyone explain? I was always using optimise for size.

Last Edited: Thu. Jul 20, 2017 - 10:34 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You're using a 32bit processor, so to do byte aligned processing it needs some extra code. So using packed arrays save ram, you pay for it in flash.

Why post in Cortex A? You're using Cortex M

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I actually posted in avrfreaks general but they moved it...I thought the issue was generic enough. But no, they now moved it to Contex - A...it should go to Cortext M.

So if the struct is a mix of bytes and longs and function pointers (which most of my structs are), it should be packed or aligned (4) ? I got best code size after aligning to 4 bytes. I always size my structs to be a multiple of 4bytes as I said. I would go as far as putting padding bytes for this.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The compiler should pad by default, so there should be no need to align.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Well I am telling you by forcing alignment and putting pads I got better code optimization.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You can tell me pigs fly, but we're not dealing with magic here. There is a perfectly logical explanation but you have all the evidence.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am sure there is. But I compiled with the attribute aligned flag and then commented out the flag and recompiled and I got different code sizes. This happened with 50 or so structs I have in my code for different things.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If your structures contained unaligned data due to the "packed" setting, the compiler may generate extra code to access those fields without causing an alignment exception.
(Hmm.  4.8 does NOT seem to do this...)

It's not clear from your post whether you removed "packed" when you added "aligned", and it's not immediately obvious (to me, anyway) what would happen if both were present.  You have the code; look at the generated binary and check...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Here is an example of struct I am using for TMP100 sensor management:

typedef struct TMP100_Sensor TMP100_Sensor;
struct TMP100_Sensor
{
	float Temperature;									//Conversion value.
	
	//Communication variables.
#define TMP100_DATA_BUF_LEN				2
	unsigned char Data[TMP100_DATA_BUF_LEN];
	unsigned short DataLength;
	unsigned short Retry;
#define TMP100_READ_RETRY_MAX			10
	unsigned short Reserved;                            //Padding.
	
	TWI_Int *TWI;
	Task ManTask;
#define TMP100_TASK_INTERVAL			50				//In ms.
#define TMP100_TASK_READ_SLEEP			500				//In ms.
};

If I compile it just with above I get 1400328bytes. Then I compile it with  __attribute__((__aligned__(4))) inserted just before the ; sign, I get 140312. That is a difference of 16bytes from such a simple struct.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What exactly is the difference? What does the compiler do with the layout of the struct? How does this affect the code generation?its little details like this that are a good learning opportunity.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

luvocean1 wrote:
If I compile it just with above I get 1400328bytes. Then I compile it with  __attribute__((__aligned__(4))) inserted just before the ; sign, I get 140312. That is a difference of 16bytes from such a simple struct.

Instead of analysing just the size of the structs, figure out the actual offset and size of each element in the structure with the different packing/align options that you're playing with.  IOW write a program to execute on the target, and use the offsetof() macro and the sizeof() operator to print out the salient numbers of structure elements.