Consider this typedef:
#pragma pack(4)
typedef struct
{
uint8 dataArea0[11];
uint8 dataArea1[12];
uint8 dataArea2[13];
uint8 dataArea3[14];
} myStruct;
I have some non-2^n sized arrays that I'd like to use from other libs. From those libs these dataAreas can be cast as e.g., structs or whatever i need. The problem occurs when one of these struct members land on a non 4-byte aligned address AND contain data types that are not happy about their address alignment.
Therefore I'd like to force the alignment with the pack pragma, but this does not help (at least in the IAR compiler -- from the manual: Use this pragma directive to specify the maximum alignment of struct and union members.). I also tried to use the data_alignment pragma, but this seems to be for variables and not struct members.
Does anyone know a nice compiler trick to force the alignment of the struct members?
Quicklink to compiler manual for those interested: IAR AVR32 Compiler Ref
Edit:
I ended up using this as an alternative
#define ROUND_UP_NEXT_FOUR(x) ((x + 3) & ~0x03)
typedef struct
{
uint8 dataArea0[ROUND_UP_NEXT_FOUR(11)];
uint8 dataArea1[ROUND_UP_NEXT_FOUR(12)];
uint8 dataArea2[ROUND_UP_NEXT_FOUR(13)];
uint8 dataArea3[ROUND_UP_NEXT_FOUR(14)];
} myStruct;
In this way I'm sure that the padding will take place at a 4-aligned address.
Edit2:
An example of how this can go wrong:
struct otherStruct
{
uint16 dataBuf0;
uint32 dataBuf1;
uint32 dataBuf2;
uint32 dataBuf3;
uint32 dataBuf4[10];
};
myStruct* myStructInstance = 0x00000000; //some address
//address of this is 0x0B
struct otherStruct* oS = (struct otherStruct*) myStructInstance.dataArea1;
//we assign to a 2 byte variable that is
//located at address that is not 2 byte aligned -> error!
os->dataBuf0 = 10;
In this case we get a runtime error (worst (or best?) case, crash).
Unfortunately the IAR AVR32 compiler does not support the _Alignas keyword. However, when IAR language extensions are enabled it supports anonymous unions and this can be used to force the alignment of individual fields of a struct. The trick is that the alignment of a union is the strictest (largest) alignment of any of its fields. Thus, by wrapping each field dataArea? in an anonymous union with a dummy field with 32-bit alignment it is possible to force the alignment of each dataArea? field to 32-bit. An example is shown below. It include both raw anonymous-union declarations as well as macro-magic to simplify declaration when the number of fields is large.
#include <stdint.h>
#define GLUE_B(x,y) x##y
#define GLUE(x,y) GLUE_B(x,y)
#define ALIGNED(FIELD, ALIGN_TYPE) union { FIELD; ALIGN_TYPE GLUE(a,__LINE__); }
#define ALIGNED32(FIELD) ALIGNED(FIELD, uint32_t)
typedef struct
{
ALIGNED(uint8_t dataArea0[11], uint32_t);
ALIGNED32(uint8_t dataArea1[12]);
union { uint8_t dataArea2[13]; uint32_t a2;};
union { uint8_t dataArea3[12]; uint32_t a3;};
} myStruct;
Related
I'm working with an USART device that send to my MCU a series of different commands (also different is size) and I want to try the best way to parse the commands.
I defined two packed structure (one for each command)
typedef ccport_PACKED( struct TASK_CommandStandard
{
UINT8 startByte;
UINT16 length;
UINT8 command;
UINT16 crc16;
}) TASK_CommandStandard_t;
typedef ccport_PACKED( struct TASK_CommandExitBootloader
{
UINT8 startByte;
UINT16 length;
UINT8 command;
UINT8 reserved;
UINT16 crc16;
}) TASK_CommandExitBootloader_t;
and one Union:
typedef union TASK_Command
{
TASK_CommandStandard_t standard;
TASK_CommandExitBootloader_t exitbootloader;
} TASK_Command_t;
My application receives the USART command inside a UINT8 buffer and after that, looking into the 4th byte I can detect the type of the command (standard or exitbootloader).
To parse the command, my idea is to use one pointer TASK_Command_t *newCommand and based on the command code, assign the address of instance.rxFrameBuffer to:
newCommand->exitbootloader = (TASK_CommandExitBootloader_t *)instance.rxFrameBuffer
or
newCommand->standard = (TASK_CommandStandard_t *)instance.rxFrameBuffer
This is my function:
static void TASK_FSM_FrameReceived( void )
{
UINT8 commandCode;
TASK_Command_t *newCommand;
commandCode = instance.rxFrameBuffer[TASK_COMMAND_CODE_INDEX];
if( commandCode == TASK_COMMAND_CODE_EXIT_BOOTLOADER )
{
newCommand->exitbootloader = (TASK_CommandExitBootloader_t *)instance.rxFrameBuffer;
}
else
{
newCommand->standard = (TASK_CommandStandard_t *)instance.rxFrameBuffer;
}
......
}
Unfortunately, the compiler returns this error:
incompatible types when assigning to type 'TASK_CommandExitBootloader_t' {aka 'struct TASK_CommandExitBootloader'} from type 'TASK_CommandExitBootloader_t *' {aka 'struct TASK_CommandExitBootloader *'}
Can someone give me a hint?
newCommand->exitbootloader isn't a pointer, it's a struct, thus if you want to copy data of instance.rxFrameBuffer to this struct, you need to use memcpy, or union. You could also dereference like so *((TASK_CommandExitBootloader_t *)instance.rxFrameBuffer) however this may be undefined behaviour depending the type of rxFrameBuffer, so I don't recommend it.
newCommand is an uninitialized pointer so it can't be used until you point at valid memory somewhere. The code will crash & burn when you attempt newCommand->exitbootloader.
You can't just wildly point into an UART rx buffer and merrily be on your way. Where is this data coming from, interrupts or DMA? How do you handle re-entrancy? Where are the actual volatile qualifier registers and how did you get the data from there?
Strict aliasing is real and it is nasty, particularly if using gcc. So you can't point into a pre-declared uint8_t array buffer for that reason. You can cast between those two different struct types if the union containing them both is present, but better to avoid all such conversions.
I'd also strongly recommend dropping "my local garage standard" types UINT8 or whatever in favour for internationally standardized, well-known C standard types uint8_t etc from stdint.h.
Also regarding hard copy of raw UART buffers on low-end microcontroller systems, that's a very common beginner mistake. See this answer for an example of how to do it properly.
I had to do something similar (pointer to raw data to save memory)
I did something like this :
typedef struct TASK_CommandStandard
{
volatile UINT8 startByte;
volatile UINT16 length;
volatile UINT8 command;
volatile UINT16 crc16;
} TASK_CommandStandard_t;
typedef struct TASK_CommandExitBootloader
{
volatile UINT8 startByte;
volatile UINT16 length;
volatile UINT8 command;
volatile UINT8 reserved;
volatile UINT16 crc16;
} TASK_CommandExitBootloader_t;
#define USART_Foo_Address 0x0F00000
#define USART_cmd ((TASK_CommandStandard_t*) USART_Foo_Address)
#define USART_exit ((TASK_CommandExitBootloader_t*) USART_Foo_Address)
Don't forget to check padding/alignment, it was working fine on my MCU
You use it like this :
static void TASK_FSM_FrameReceived( void )
{
if( instance.rxFrameBuffer[TASK_COMMAND_CODE_INDEX] == TASK_COMMAND_CODE_EXIT_BOOTLOADER )
{
USART_exit->length;
....
}
else
{
USART_cmd->length;
....
}
......
}
I solved modifing the union:
typedef union TASK_Command
{
TASK_CommandStandard_t *standard;
TASK_CommandExitBootloader_t *exitbootloader;
} TASK_Command_t;
and in my function insted using a
TASK_Command_t *newCommand;
I used
TASK_Command_t newCommand;
In this way I can use the same variable to cast my different messages without make any buffer copy.
I can access to the UART buffer with
newCommand.standard = (TASK_CommandStandard_t *)instance.rxFrameBuffer;
I'm trying to combine two typedef unions of a GPIO port of an ARM SoC into one, and address pointers into one. Currently, I have something which looks like this:
.h file:
//GPIO00 port
typedef union {
struct {
uint32_t GPIO000:1;
uint32_t GPIO001:1;
...
uint32_t GPIO0017:1;
};
struct {
uint32_t w:18;
};
} __GPIO00portbits_t;
volatile __GPIO00portbits_t * PTR_GPIO00portbits;
#define GPIO00portbits (*PTR_GPIO00portbits)
//GPIO01 port
typedef union {
struct {
uint32_t GPIO010:1;
uint32_t GPIO011:1;
...
uint32_t GPIO0117:1;
};
struct {
uint32_t w:18;
};
} __GPIO01portbits_t;
volatile __GPIO01portbits_t * PTR_GPIO01portbits;
#define GPIO01portbits (*PTR_GPIO01portbits)
.c file:
//GPIO 00 port
volatile __GPIO00portbits_t * PTR_GPIO00portbits = (__GPIO00portbits_t *) (AXIBRIDGE_BASE_ADDR + GPIO_00_BASE);
//GPIO 01 port
volatile __GPIO01portbits_t * PTR_GPIO01portbits = (__GPIO01portbits_t *) (AXIBRIDGE_BASE_ADDR + GPIO_01_BASE);
}
I can use this to control GPIO ports of the ARM SoC. I.e. I can control a single pin of GPIO00 by changing GPIO00portbits.GPIO00x. It works the same for GPIO01.
In reality, GPIO00 and GPIO01 are actually one port called GPIO0, where GPIO00 is pin 0-17 and GPIO01 is pin 18-35, so I would also like to combine GPIO00 and GPIO01 into one stuct which can be controlled by changing GPIO0portbits.GPIO0x.
So I would like to have something like this:
typedef union {
struct {
uint64_t GPIO00:1 = GPIO00portbits.GPIO000;
uint64_t GPIO01:1 = GPIO00portbits.GPIO001;
...
uint64_t GPIO035:1 = GPIO01portbits.GPIO0117;
};
struct {
uint32_t w:36;
};
} __GPIO0portbits_t;
How can I do this?
Thank you in advance.
Data types generally
You have defined two distinct types, __GPIO00portbits_t and __GPIO01portbits_t, with identical structure and closely related use. This is pointless, and it may even get in your way. I would probably do this, instead:
typedef union {
struct {
uint32_t GPIO0:1;
uint32_t GPIO1:1;
...
uint32_t GPIO17:1;
};
uint32_t w:18;
} __GPIOhalfportbits_t;
extern volatile __GPIOhalfportbits_t *PTR_GPIO00portbits;
#define GPIO00portbits (*PTR_GPIO00portbits)
extern volatile __GPIOhalfportbits_t * PTR_GPIO01portbits;
#define GPIO01portbits (*PTR_GPIO01portbits)
Note, by the way, that you need the externs if the header is going to be used in more than one .c file, and that in that case exactly one of those .c files should contain definitions you show.
Your specific request
I would also like to combine GPIO00 and GPIO01 into one stuct which can be controlled by changing GPIO0portbits.GPIO0x
It seems like you may not be maintaining the appropriate mental distinction between objects and their data types. That would explain your odd duplication of data types, and also the way you describe what you're looking for. If you want to be able to have the option to treat the data as either a full 36 bits or two 18-bit halves, then you could imagine continuing the above with something like this:
// XXX: see below
typedef union {
struct {
__GPIOhalfportbits_t group0;
__GPIOhalfportbits_t group1;
};
struct {
uint32_t GPIO0:1;
uint32_t GPIO1:1;
...
uint32_t GPIO35:1;
};
uint64_t w:36; // uint32_t isn't wide enough
} __GPIOportbits_t;
In principle, then, you might access an object of that type either by directly accessing the bits ...
__GPIOportbits_t portbits;
// ...
if (portbits.GPIO23) {
// ...
}
... or via the half-port pieces ...
if (portbits.group1.GPIO5) {
// ...
}
Something like that might work under different circumstances, but in your case, this will not work. The problem is that the number of bits in your half-port pieces is not a multiple of the number of bits in a char (8 on your hardware). The size of char is the unit in which object sizes are measured, and, accordingly, the finest possible granularity for addresses.
That means that the size of my __GPIOhalfportbits_t and your __GPIO00portbits_t and __GPIO01portbits_t is at least 24 bits, not 18 bits. Therefore, if you lay two of them out one after the other then the bitfields cannot be laid out as a contiguous 36-bit range starting at the beginning of the object. There are at least 6 (padding) bits of the first object that need to go somewhere before the bits of the second half-port object.
For substantially the same reason, there are no pointer tricks that can accomplish what you're after, either. If you have a region of 36 contiguous bits then the second half does not start on an addressible boundary, so you cannot form a pointer to it.
On the other hand, if the two halves are not contiguous in the first place, then you might be able to go with something like this:
typedef struct {
__GPIOhalfportbits_t group0;
__GPIOhalfportbits_t group1;
} __GPIOportbits_t;
You would have to pay attention to alignment of the two half-port pieces, but there is probably an implementation-specific way to get that right. Given that the underlying data (we have now assumed) is not presented as a contiguous span of 36 bits in the first place, forming a union with a 36-bit bitfield does not make sense. It might nevertheless be possible to use a union to map individual single-bit bitfields on top of that pair of structures by inserting explicit padding of the appropriate size, but you need to consider whether any of this is actually worth doing. In particular, see below.
Important other considerations
Bitfields are a tricky business in general, and C makes very few guarantees about their behavior -- many fewer than a lot of people suppose or expect. It is a particularly poor idea to use bitfields to write to hardware ports, because you cannot write fewer than CHAR_BIT bits at once, and if you're writing via a bitfield whose size is not a power-of-two multiple of CHAR_BIT then you will be writing additional bits as well, whose values are unspecified.
I generally recommend avoiding bitfields altogether, except possibly for usage of bitfields in C-language programming interfaces provided by the relevant hardware manufacturer, in a manner consistent with those interfaces' documentation.
Alternatives
You could conceivably come up with some wrapper macros for accessing the GPIO port in terms of two half ports, and even in terms of individual bits within those ports. But this answer is already long, and such a macro-centric approach would be a whole other story.
You can't do that as they live under different addresses in memory.
Using objects to access hardware registers is very inefficient. On this level of programming, you need to optimize code as much as possible.
https://godbolt.org/z/ncbr8o
YOu can only "combine" them by having additional object where you will read the data from that actual registers, and after changes save it to registers.
#include <stdint.h>
#define AXIBRIDGE_BASE_ADDR 0x12340000
#define GPIO_00_BASE 0x400
#define GPIO_01_BASE 0x800
//GPIO00 port
typedef union {
struct {
uint32_t GPIO000:1;
uint32_t GPIO001:1;
uint32_t GPIO002:1;
uint32_t GPIO003:1;
uint32_t GPIO004:1;
uint32_t GPIO005:1;
uint32_t GPIO006:1;
uint32_t GPIO007:1;
uint32_t GPIO008:1;
uint32_t GPIO009:1;
uint32_t GPIO010:1;
uint32_t GPIO011:1;
uint32_t GPIO012:1;
uint32_t GPIO013:1;
uint32_t GPIO014:1;
uint32_t GPIO015:1;
uint32_t GPIO016:1;
uint32_t GPIO017:1;
};
struct {
uint32_t w:18;
};
} __GPIO00portbits_t;
typedef union {
struct {
uint32_t GPIO000:1;
uint32_t GPIO001:1;
uint32_t GPIO002:1;
uint32_t GPIO003:1;
uint32_t GPIO004:1;
uint32_t GPIO005:1;
uint32_t GPIO006:1;
uint32_t GPIO007:1;
uint32_t GPIO008:1;
uint32_t GPIO009:1;
uint32_t GPIO010:1;
uint32_t GPIO011:1;
uint32_t GPIO012:1;
uint32_t GPIO013:1;
uint32_t GPIO014:1;
uint32_t GPIO015:1;
uint32_t GPIO016:1;
uint32_t GPIO017:1;
uint32_t GPIO100:1;
uint32_t GPIO101:1;
uint32_t GPIO102:1;
uint32_t GPIO103:1;
uint32_t GPIO104:1;
uint32_t GPIO105:1;
uint32_t GPIO106:1;
uint32_t GPIO107:1;
uint32_t GPIO108:1;
uint32_t GPIO109:1;
uint32_t GPIO110:1;
uint32_t GPIO111:1;
uint32_t GPIO112:1;
uint32_t GPIO113:1;
uint32_t GPIO114:1;
uint32_t GPIO115:1;
uint32_t GPIO116:1;
uint32_t GPIO117:1;
};
struct {
uint64_t GPIO1w:18;
uint64_t GPIO2w:18;
};
} __GPIO12portbits_t;
#define GPIO1 ((volatile __GPIO00portbits_t *)(AXIBRIDGE_BASE_ADDR + GPIO_00_BASE))
#define GPIO2 ((volatile __GPIO00portbits_t *)(AXIBRIDGE_BASE_ADDR + GPIO_01_BASE))
#define COMBINE() (&(__GPIO12portbits_t){.GPIO1w = GPIO1 -> w, .GPIO2w = GPIO2 -> w})
#define UPDATEGPIO(ptr) do{GPIO1 -> w = ptr -> GPIO1w; GPIO2 -> w = ptr -> GPIO2w;}while(0)
void foo()
{
__GPIO12portbits_t *ptr = COMBINE();
ptr -> GPIO014 = 1;
ptr -> GPIO110 = 1;
UPDATEGPIO(ptr);
}
void bar()
{
GPIO1 -> GPIO014 = 1;
GPIO2 -> GPIO010 = 1;
}
But it is very inefficient https://godbolt.org/z/jMsc7j
FYI: This is my first question using stackoverflow!
The code is as follows:
uint8_t TestVar1;
uint8_t TestVar2;
typedef struct
{
uint8_t member1;
uint32_t member2;
}Test1;
typedef struct
{
uint8_t member1;
uint8_t member2[4];
}Test2;
Test1 TestStruct1;
Test2 TestStruct2;
TestVar1 = sizeof(TestStruct1); /*size is 8*/
TestVar2 = sizeof(TestStruct2); /*size is 5*/
I thought I understood padding but I can't explain TestVar2. I can explain TestVar1 being 8 bytes because there is 3 padding bytes as part of uint8_t member1.
However, with struct test2 are there no padding bytes? (Apparently not) Could someone provide some insight as to what is happening in struct test2 case?
As a side note, I am aiming for 5 bytes but I don't know why the second case works. Is the array breaking down to a pointer or something? Is this safe(standard practice) to do?
Thanks!
uint8_t has no specific alignment requirements and thus does not require any padding to align it while uint32_t, being a multi-byte type, will want to be aligned on a 4-byte boundary. If you absolutely must have a struct with a uint8_t and uint32_t that takes only 5 bytes, you can use __attribute__((packed)) to tell the compiler to forego the padding (which I would carefully consider whether the space saved is worth misalignment):
typedef struct __attribute__((packed)) {
uint8_t member1;
uint32_t member2;
}test;
Another thing to consider is the ordering of the struct members. To keep a reduced struct size, put the largest members at the beginning of the struct as they will have the strictest alignment needs. Consider the following:
typedef struct {
uint8_t w;
uint32_t x;
uint8_t y;
uint32_t z;
}test2;
typedef struct {
uint32_t x;
uint32_t z;
uint8_t w;
uint8_t y;
}test3;
In order to keep the uint32_t members aligned, test2 will put padding after w and y, while test3 will already have the uint32_t members aligned and only put enough padding at the end of the struct so that the next free memory segment aligns with a 4-bytes boundary (as that is the strictest boundary of any of the struct's members). Therefore test2 will have a size of 16 bytes while test3 will have a size of 12 bytes.
Note: I have not seen where, if at all, this is defined in the C specs, but the results hold true for both gcc and clang in my tests.
below code snippet,How can we make below struct define as 4 bytes aligned?
I have tried pragma pack to aligned Explicitly.But It's does NOT work as we want...
#pragma pack(push)
#pragma pack(4)
//..struct devine here.
#pragma pack(pop);
I have tried __attribute__ to aligned Explicitly.It's also does NOT work as well..
struct device_info {
//
}__attribute__(packed);
//struct device_info dev_info;
sizeof (struct device_info)=211
I have tried __attribute__ to aligned Explicitly.It's also does NOT work as well..
struct device_info {
//
};
typedef struct device_info deice_info __attribute__(packed)
device_info dev_info;
sizeof (dev_info)=211
Question1:
How can I aligned struct device_info Explicitly,and offsetof output like below:
offsetof magic=0
offsetof is_unlocked=16
offsetof is_tampered=20
offsetof is_unlock_critical=24
offsetof charger_screen_enabled=28
offsetof display_panel=32
offsetof booloader_version=96
offsetof radio_version=160
offsetof verity_mode=224
offsetof is_origin=228
code snippet:
#define DEVICE_MAGIC_SIZE 13
#define MAX_PANEL_ID_LEN 64
#define MAX_VERSION_LEN 64
struct device_info{
unsigned char magic[DEVICE_MAGIC_SIZE];
bool is_unlocked;
bool is_tampered;
bool is_unlock_critical;
bool charger_screen_enabled;
char display_panel[MAX_PANEL_ID_LEN];
char booloader_version[MAX_VERSION_LEN];
char radio_version[MAX_VERSION_LEN;
bool verity_mode;
bool is_origin;
};
Update 1
I have tried below snippet
struct device_info{
__attribute__((__aligned(4))) bool is_unlock;
//...
};
It's same that work well.
Question two:
What's difference between
struct device_info{
__attribute__((__aligned(4))) bool is_unlock;
//...
};
and
struct device_info{
bool is_unlock;
//..
}__attribute__((__aligned(4))) ;
Question 3
How can we dump during source code compiled to execute binary or library?(preprocessing->Compile->link) objdump?or others?
Since C11 you can use the standard alignas specifier.
This should solve your question.
It would appear that in your implementation, sizeof(bool) is equal to 1. In that case, the padding rules are being correctly adhered to, so is_unlocked can appear precisely after magic with no additional padding.
The other thing is that bool is implementation-defined. Please read this post: Is sizeof(bool) defined?
What you might benefit more from, is to use proper types from <ctype.h> when you are laying out a structure with absolute sizes. If you want your bool values to be 32-bit integers, then use int32_t or uint32_t instead.
I want the compiler to generate warning for me if structure declared without __attribute__(align(8)) .
For example, if a structure is declared like this:
struct my_float {
float number;
} __attribute__((aligned(8)));
It will not generate any warning. But if I declare another struct like this:
struct my_float {
float number;
};
the compiler will generate a warning for me.
My working enveronment is linux/GCC.
I don't think you can automatically check this an ALL your structure, but you still can check your alignment manually with something like:
// x % 16 <=> x & (16-1) (avoid using modulo operator)
#define MODULO_16_MASK 0xFU
ASSERT_COMPILE((sizeof(my_float) & MODULO_16_MASK) == 0);
This should trigger a warning at compiling if your structure is not aligned.
From experience, it is not possible to do.
This attribute specifies a minimum alignment (in bytes) for variables of the specified type.
struct S { short f[3]; } __attribute__ ((aligned (8)));
typedef int more_aligned_int __attribute__ ((aligned (8)));
force the compiler that each variable whose type is struct S or more_aligned_int is allocated and aligned at least on a 8-byte boundary.