2021-08-19 05:02 PM
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?
Solved! Go to Solution.
2021-08-20 09:21 AM
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.
2021-08-19 05:11 PM
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?
2021-08-19 05:18 PM
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.
2021-08-19 07:12 PM
From gcc manual:
An attribute specifier is of the form
__attribute__ ((attribute-list)).
i.e. here, __attribute__((packed)).
JW
2021-08-20 06:59 AM
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
2021-08-20 09:21 AM
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.
2022-12-04 04:16 AM
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`.
2022-12-04 04:16 AM
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`.
2022-12-05 10:59 AM
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