The goal is to create a structure that contains 3 fields. One of those fields needs to be a uint32_t union
but the flags will be different for each element. I believe the best way to do this is to create a separate union
for each peripheral and assign it to a void pointer in the parent struct (somehow).
The Current Plan:
//--------------Register for AAA
typedef union
{
struct
{
uint32_t spare : 32; //< Bits 0-31 not used
}Bits;
uint32_t FullData;
}ABC_EMPTY_DATA;
ABC_EMPTY_DATA AAA_Data;
//--------------Register for BBB
typedef union
{
struct
{
uint32_t use32BitColor : 1; //< Bit0
uint32_t enableTimer : 1; //< Bit1
uint32_t fooTheBar : 1; //< Bit2
uint32_t spare : 29; //< Bits 3-31 not used
}Bits;
uint32_t FullData;
}ABC_BBB_DATA;
ABC_EMPTY_DATA BBB_Data;
//--------------Register for CCC
typedef union
{
struct
{
uint32_t useInternalFrameTick : 1; //< Bit0
uint32_t useExternalFrameTick : 1; //< Bit1
uint32_t spare : 30; //< Bits 2-31 not used
}Bits;
uint32_t FullData;
}ABC_CCC_DATA;
ABC_CCC_DATA CCC_Data;
//-------The Peripherals with register element
typedef struct
{
char *Name;
unsigned int HexCmd;
void *Data; //Connect to corasponding XXXX_Data
}ABC_dataStructs;
//----- Initializing Peripherals
typedef struct
{
ABC_dataStructs AAA = {.Name = "AAA", .HexCmd = 0x00, .Data = (void*) &AAA_Data};
ABC_dataStructs BBB = {.Name = "BBB", .HexCmd = 0x00, .Data = (void*) &BBB_Data};
ABC_dataStructs CCC = {.Name = "CCC", .HexCmd = 0x00, .Data = (void*) &CCC_Data};
}ABC_CommandList;
void main(){
ABC_CommandList everything;
everything.CCC.FullData = 0x000F;
everything.BBB.use32BitColor = 0;
int myint = everything.AAA.HexCmd;
}
Currently, I am having initializeing the values within the struct
ABC_dataStructs AAA = {.Name = "AAA", .HexCmd = 0x00, .Data = (void*) &AAA_Data};
is invalid
Also and more importantly the assigning of the union is not working as intended. The current result only allows for everything.AAA.Data
without being able to assign/read individual bits.
I also tried to explain the intent of the SW in order to avoid an "XY problem" and if I am approaching this wrong or you think of something better let me know. Thank You.
Note: C struct, union pointer to struct has another approach of putting structs
in the unions
instead of unions
to the structs
, but it doesn't help with my main issue of assigning these to a void*
The problem you're having with the initialization is that you're defining a type and attempting to initialize it as if it's a variable at the same time. You need to first define the struct, then initialize an instance of it:
typedef struct
{
ABC_dataStructs AAA;
ABC_dataStructs BBB;
ABC_dataStructs CCC;
}ABC_CommandList;
void main(){
ABC_CommandList everything = {
.AAA = {.Name = "AAA", .HexCmd = 0x00, .Data = &AAA_Data},
.BBB = {.Name = "BBB", .HexCmd = 0x00, .Data = &BBB_Data},
.CCC = {.Name = "CCC", .HexCmd = 0x00, .Data = &CCC_Data},
};
...
Note also that it's not required to cast to/from a void *
.
Then the problem here:
everything.CCC.FullData = 0x000F;
everything.BBB.use32BitColor = 0;
Is that CCC
and BBB
are of type ABC_dataStructs
, and that type does not have fields named FullData
or use32BitColor
. You would need to cast the Data
member to the proper pointer type, then dereference that:
((ABC_CCC_DATA *)everything.CCC.Data)->FullData = 0x000F;
((ABC_BBB_DATA *)everything.BBB.Data)->use32BitColor = 0;
All that being said, there's a better way of modeling this data. What you really want is a union of the 3 register types. Then ABC_dataStructs
would contain that union along with a separate field which flags which union to use.
typedef struct
{
uint32_t spare : 32; //< Bits 0-31 not used
} ABC_EMPTY_DATA;
typedef struct
{
uint32_t use32BitColor : 1; //< Bit0
uint32_t enableTimer : 1; //< Bit1
uint32_t fooTheBar : 1; //< Bit2
uint32_t spare : 29; //< Bits 3-31 not used
} ABC_BBB_DATA;
typedef struct
{
uint32_t useInternalFrameTick : 1; //< Bit0
uint32_t useExternalFrameTick : 1; //< Bit1
uint32_t spare : 30; //< Bits 2-31 not used
} ABC_CCC_DATA;
typedef struct
{
char *Name;
unsigned int HexCmd;
union {
ABC_EMPTY_DATA AAA;
ABC_BBB_DATA BBB;
ABC_CCC_DATA CCC;
uint32_t FullData;
};
}ABC_dataStructs;
Then you can define the following:
ABC_CommandList everything = {
.AAA = {.Name = "AAA", .HexCmd = 0x00, .AAA = {}},
.BBB = {.Name = "BBB", .HexCmd = 0x00, .BBB = { .use32BitColor = 0 }},
.CCC = {.Name = "CCC", .HexCmd = 0x00, .FullData = 0x000F },
};