Il problema
In un contesto embedded bare-metal di basso livello , vorrei creare uno spazio vuoto nella memoria, all'interno di una struttura C ++ e senza alcun nome, per impedire all'utente di accedere a tale posizione di memoria.
In questo momento, l'ho ottenuto inserendo un brutto uint32_t :96;
bitfield che prenderà opportunamente il posto di tre parole, ma solleverà un avviso da GCC (Bitfield troppo grande per adattarsi a uint32_t), che è abbastanza legittimo.
Anche se funziona bene, non è molto pulito quando si desidera distribuire una libreria con diverse centinaia di questi avvisi ...
Come posso farlo correttamente?
Perché c'è un problema in primo luogo?
Il progetto a cui sto lavorando consiste nel definire la struttura della memoria di diverse periferiche di un'intera linea di microcontrollori (STMicroelectronics STM32). Per fare ciò, il risultato è una classe che contiene un'unione di diverse strutture che definiscono tutti i registri, a seconda del microcontrollore di destinazione.
Un semplice esempio per una periferica piuttosto semplice è il seguente: un General Purpose Input / Output (GPIO)
union
{
struct
{
GPIO_MAP0_MODER;
GPIO_MAP0_OTYPER;
GPIO_MAP0_OSPEEDR;
GPIO_MAP0_PUPDR;
GPIO_MAP0_IDR;
GPIO_MAP0_ODR;
GPIO_MAP0_BSRR;
GPIO_MAP0_LCKR;
GPIO_MAP0_AFR;
GPIO_MAP0_BRR;
GPIO_MAP0_ASCR;
};
struct
{
GPIO_MAP1_CRL;
GPIO_MAP1_CRH;
GPIO_MAP1_IDR;
GPIO_MAP1_ODR;
GPIO_MAP1_BSRR;
GPIO_MAP1_BRR;
GPIO_MAP1_LCKR;
uint32_t :32;
GPIO_MAP1_AFRL;
GPIO_MAP1_AFRH;
uint32_t :64;
};
struct
{
uint32_t :192;
GPIO_MAP2_BSRRL;
GPIO_MAP2_BSRRH;
uint32_t :160;
};
};
Dove all GPIO_MAPx_YYY
è una macro, definita come uint32_t :32
o il tipo di registro (una struttura dedicata).
Qui vedi il uint32_t :192;
che funziona bene, ma fa scattare un avviso.
Quello che ho considerato finora:
Potrei averlo sostituito con diversi uint32_t :32;
(6 qui), ma ho alcuni casi estremi in cui houint32_t :1344;
(42) (tra gli altri). Quindi preferirei non aggiungere un centinaio di righe in cima ad altre 8k, anche se la generazione della struttura è scriptata.
L'esatto messaggio di avvertimento è qualcosa del tipo:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type
(Adoro quanto sia ombroso).
Preferirei non risolverlo semplicemente rimuovendo l'avviso, ma l'uso di
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop
potrebbe essere una soluzione ... se trovo TheRightFlag
. Tuttavia, come sottolineato in questo thread , gcc/cp/class.c
con questa triste parte di codice:
warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);
Il che ci dice che non esiste un -Wxxx
flag per rimuovere questo avviso ...
uint32_t :192;
.
:42*32
posto di:1344
char unused[12];
e così via?