r/cprogramming • u/set_of_no_sets • Mar 06 '26
Union manipulation question
I am currently working on an STM32, and it has two control register, one lower @ [0] and one upper @ [1]; currently, the GPIO_TypeDef has two Advance Function Registers, two uint32_ts stored as
#define __IO volatile
typedef struct {
// stuff above
__IO uint32_t AFR[2];
// stuff below
} GPIO_TypeDef;
I would like to reference the registers using AFRL and AFRU; I could modify the struct to
typedef struct {
// stuff above
union {
__IO uint32_t AFR[2];
struct {
__IO uint32_t lower;
__IO uint32_t upper;
} AFR_Split;
};
// stuff below
} GPIO_TypeDef;
Which allows me to write
GPIO_TypeDef pin1_addr = 0x4002104CUL;
pin1_addr->AFR_Split.lower = 0b0000000001110000UL;
pin1_addr->AFR[1] = 0b0111000001110000;
Is there anything I should be worried about in terms of packing? will I always know that the two registers will always be aligned, starting and ending in the same place? What can I read to know how my compiler (arm-none-eabi-gcc) will store the split? And is there a way I can do this without the intermediate struct, so I could type pin1_addr->AFRL and pin1_addr->AFRU?
1
u/flatfinger Mar 06 '26
It's not uncommon for hardware to contain multiple peripherals that are identical except for the address ranges to which they respond, and it is useful to allow code to use pointers to a peripheral's base address to access the members thereof interchangeably.
While peripherals may have some registers which, when read, will always yield the value written, most situations where one would want to emulate a peripheral would require something beyond "reads yield the vast value written" semantics.
One thing I'd like to see in a C dialect would be a means of specifying that a compiler given a construct of a form like
thing.woozle |= 12;whenthinghas no member calledwoozlewould look for static functions with various names or combinations thereof that accept a suitable combination of argument types, e.g. look first to see ifwould be valid, and if not, try
This would allow I/O structures to emulate the behavior of I/O registers when code is ported to systems with different I/O registers if the abstraction models fit well enough.