You cannot cast an intialization expression to another type in a way that would achieve what you want, but you can use an union and initialize a variable of that union type using whichever member you want. Then, you can use the preprocessor to mangle the name seen by userspace, into a reference of a member of that union.
So, if you have an existing codebase that accesses the EEPROM data through gEEPersistentData but you want to embed it in an union or a structure (or a combination):
union {
Tpwm selectedPwm;
uint8_t data[_EEPROMSIZE];
} eeConfig = { .selectedPwm = { .period = 40, .duty = 20, .phase = 20 } };
#define gEEPersistentData (eeConfig.data)
Here, sizeof gEEPersistentData == _EEPROMSIZE, and the type of gEEPersistentata is an array of uint8_t. It is perfectly okay to grab its address, for example.
If the structure is declared and initialized in user code, but accessed in your/library code, you can put in a header file used by both user and library code:
typedef union {
Tpwm selectedPwm;
uint8_t data[_EEPROMSIZE];
} TEEConfig;
#define DECLARE_EEPROM_PWM(spec...) \
TEEConfig eeConfig = { .selectedPwm = { spec } };
#define DECLARE_EEPROM_DATA(spec...) \
TEEConfig eeConfig = { .data = { spec } };
#define gEEPersistentData (eeConfig.data)
extern TEEConfig eeConfig;
and library code can happily access the _EEPROMSIZE bytes in array gEEPersistentData, as long as one of the source objects declares the EEPROM, using e.g.
DECLARE_EEPROM_PWM(.period=40, .duty=20, .phase=20);
or (equivalently if those Tpwm fields are all just bytes in that order)
DECLARE_EEPROM_DATA(40, 20, 20);
This is pure ANSI C/ISO C89, and should work even with slightly limited or wonky C compilers just fine. In case you wonder, yes, it is legal to have extern Type Var; and then define Type Var = ...; you do not need to have separate header files for "user code" and "library code".