cancel
Showing results for 
Search instead for 
Did you mean: 

How can I get __packed attribute to work in the GCC compiler used in the STM32CubeIDE?

KiptonM
Lead

I have a structure, that came from the hardware manufacturer for an encoder.

The data is in most cases 16-bit words. Some times it is a 16-bit word with a bit field, sometimes it is a 32-bit variable and sometimes it is a 48-bit variable or a 64-bit variable.

So I built the structure, it should be 44 16-bit words or 88 bytes. When I checked the size it was 100 bytes. That indicated it was inserting bytes in the structure. Fortunately there is such a thing as __packed attribute.

I inserted the __packed attribute and I got warnings that the packed attribute was being ignored.

Then I realized I had to say packed everywhere. So I put it everywhere I could think of, and I got no more warnings!

Unfortunately that did nothing. The structure is still 100 bytes not 88 bytes.

So I concentrated on the first place it gets off.

Here is what the code looks like:

typedef __packed union
{
	uint8_t byte;
	__packed struct
	{
		uint8_t start_address:4;
		uint8_t end_address:4;
	};
} OEM_COMP_MEMORY_STRUCT;
 
 
typedef __packed union
{
	uint16_t word[4];
	uint32_t dword[2];
	uint8_t  byte[8];
	OEM_COMP_MEMORY_STRUCT addresses[8];
} MEMORY_ALLOCATION_STRUCT;
typedef __packed union
{
	uint8_t  byte[88];
	uint16_t word[44];
	__packed struct {
		uint16_t MASK0;  	// 4
		uint16_t MASK1;		// 5
		uint16_t MASK2;		// 6
		uint16_t MASK3;		// 7
		uint16_t EnDat_version;	// 8
		MEMORY_ALLOCATION_STRUCT OEM;	// 9, 10, 11, 12
		uint16_t transfer_format_position;	// 13
		uint16_t Encoder_type;	// 14
		uint32_t Signal_period;	// 15, 16
		uint16_t Number_of_revolutions;	// 17
		uint16_t Distance_of_reference_marks;	// 18
		uint16_t Position_first_reference_mark;	// 19
		uint32_t Measuring_step;	// 20 21
		uint32_t Datum_shift;		// 22 23
		ID_NUMBER_STRUCT id_number;	// 24, 25, 26
		SERIAL_NUMBER_STRUCT serial_number;	// 27, 28, 29
		DIRECTION_ROTATION_STRUCT direction_of_rotation; // 30
		EXTERNAL_COMMISSIONING_DIAG_STRUCT external_commissioning_diagnostics; // 31
		uint16_t  Maximum_velocity;	// 32
		VELOCITY_RANGE_STRUCT Velocity_range1;	// 33
		VELOCITY_RANGE_STRUCT Velocity_range2;	// 34
		ERROR_MESSAGE_STRUCT Support_of_error_message1;// 35
		WARNINGS_STRUCT Support_of_warnings; // 36
		ENDAT_COMMAND_SET_STRUCT EnDat_command_set; // 37
		VALUE_UNITS_STRUCT measuring_length; // 38
		VALUE_UNITS_STRUCT maximum_processing_time; // 39
		TWO_BYTES_STRUCT EnDat_ordering; // 40
		uint16_t word41;
		uint16_t word42;
		uint16_t word43;
		uint16_t word44;
		uint16_t word45;
		uint16_t word46;
		uint16_t checksum; // simple sum of the bytes in the structure word[43] = sum(word[0]...word[42] & 0xFFFF
	};
 
} PARM_ENCODER_MANUFACTURER_STRUCT;  // *PEM
 
PARM_ENCODER_MANUFACTURER_STRUCT *PEM = ((PARM_ENCODER_MANUFACTURER_STRUCT *) &EMEM.NVMword[4]);
 
void check_PEM(void)
{
	char buf[100];
	uint16_t i;
	for (i=0;i<44;i++)
	{
		PEM->word[i] = i + 4;
	}
 
	write_debug_str("In check_PEM\r\n");
 
	sprintf(buf,"MASK0: %u, 0x%04X, should be 4\r\n", PEM->MASK0, PEM->MASK0);
    write_debug_str(buf);
 
    sprintf(buf,"EnDat_version: %u, 0x%04X, should be 8\r\n", PEM->EnDat_version, PEM->EnDat_version);
    write_debug_str(buf);
 
    sprintf(buf,"OEM.word[0]: %u, 0x%04X, should be 9\r\n", PEM->OEM.word[0], PEM->OEM.word[0]);
	write_debug_str(buf);
 
    sprintf(buf,"OEM.word[1]: %u, 0x%04X, should be 10\r\n", PEM->OEM.word[1], PEM->OEM.word[1]);
	write_debug_str(buf);
 
    sprintf(buf,"OEM.word[2]: %u, 0x%04X, should be 11\r\n", PEM->OEM.word[2], PEM->OEM.word[2]);
	write_debug_str(buf);
 
    sprintf(buf,"OEM.word[3]: %u, 0x%04X, should be 12\r\n", PEM->OEM.word[3], PEM->OEM.word[3]);
	write_debug_str(buf);
 
	sprintf(buf,"transfer_format_position: %u, 0x%04X, should be 13\r\n", PEM->transfer_format_position, PEM->transfer_format_position);
    write_debug_str(buf);
 
	sprintf(buf,"Datum_shift: %lu, 0x%08lX, should be 22 23\r\n", PEM->Datum_shift, PEM->Datum_shift);
    write_debug_str(buf);
 
}
 
 

Running the subroutine it prints

In check_PEM

MASK0: 4, 0x0004, should be 4

EnDat_version: 8, 0x0008, should be 8

OEM.word[0]: 10, 0x000A, should be 9

OEM.word[1]: 11, 0x000B, should be 10

OEM.word[2]: 12, 0x000C, should be 11

OEM.word[3]: 13, 0x000D, should be 12

transfer_format_position: 14, 0x000E, should be 13

Datum_shift: 1638424, 0x00190018, should be 22 23

It realigns for the MEMORY_ALLOCATION_STRUCT OEM;

That is what the __PACKED attribute is supposed to fix...

How do I fix this?

Where do I find the documentation or reference manual on the compiler to see if there is a switch I am missing?

1 ACCEPTED SOLUTION

Accepted Solutions
KiptonM
Lead

https://developer.arm.com/documentation/100748/0616/Writing-Optimized-Code/Packing-data-structures

gave me the answer.

#pragma pack (2) fixed 4 of the 5 and #pragma pack (1) fixed all of them.

View solution in original post

8 REPLIES 8
KiptonM
Lead

I was mistaken. The compiler warnings for the packed attribute being ignored did not go away. It did not compile the module that had them.

Do I have to move to a 16-bit processor for this to work?

KiptonM
Lead

The data comes in a block. (Like a DMA transfer) And I was trying to build a structure for the data block. I did not want to have to move the data around to read it correctly. I wanted to pull it in place.

From gcc manual:

An attribute specifier is of the form 

__attribute__ ((attribute-list)).

i.e. here, __attribute__((packed)).

JW

Same warnings as with just using __packed

In file included from ../Core/Src/Encoder_Memory.c:14:

../Core/Inc/Encoder_Memory.h:115:1: warning: 'packed' attribute ignored [-Wattributes]

 115 | } OEM_COMP_MEMORY_STRUCT;

     | ^

../Core/Inc/Encoder_Memory.h:125:1: warning: 'packed' attribute ignored [-Wattributes]

 125 | } MEMORY_ALLOCATION_STRUCT;

     | ^

../Core/Inc/Encoder_Memory.h:257:1: warning: 'packed' attribute ignored [-Wattributes]

 257 | } PARM_ENCODER_MANUFACTURER_STRUCT; // *PEM

     | ^

In file included from ../Core/Src/main.c:31:

../Core/Inc/Encoder_Memory.h:115:1: warning: 'packed' attribute ignored [-Wattributes]

 115 | } OEM_COMP_MEMORY_STRUCT;

     | ^

../Core/Inc/Encoder_Memory.h:125:1: warning: 'packed' attribute ignored [-Wattributes]

 125 | } MEMORY_ALLOCATION_STRUCT;

     | ^

../Core/Inc/Encoder_Memory.h:257:1: warning: 'packed' attribute ignored [-Wattributes]

 257 | } PARM_ENCODER_MANUFACTURER_STRUCT; // *PEM

     | ^

In file included from ../Core/Src/Encoder.c:17:

../Core/Inc/Encoder_Memory.h:115:1: warning: 'packed' attribute ignored [-Wattributes]

 115 | } OEM_COMP_MEMORY_STRUCT;

     | ^

../Core/Inc/Encoder_Memory.h:125:1: warning: 'packed' attribute ignored [-Wattributes]

 125 | } MEMORY_ALLOCATION_STRUCT;

     | ^

../Core/Inc/Encoder_Memory.h:257:1: warning: 'packed' attribute ignored [-Wattributes]

 257 | } PARM_ENCODER_MANUFACTURER_STRUCT; // *PEM

KiptonM
Lead

https://developer.arm.com/documentation/100748/0616/Writing-Optimized-Code/Packing-data-structures

gave me the answer.

#pragma pack (2) fixed 4 of the 5 and #pragma pack (1) fixed all of them.

BZ.1
Associate

You have mistaken the position of keyword `struct` or `union` with the position of `__packed` or `__attribute__((packed))`.

Even with `typedef`, you should still write like `typedef struct __packed`.

BZ.1
Associate

You have mistaken the position of keyword `struct` or `union` with the position of `__packed` or `__attribute__((packed))`.

Even with `typedef`, you should still write like `typedef struct __packed`.

KiptonM
Lead

I am way past that program. That was many projects ago. I will have to see if that works next time I need it.

Fortunately, the #pragma worked, and I was able to move on.

Thanks,

Kip