Le problème
Dans un contexte embarqué bare-metal de bas niveau , je voudrais créer un espace vide dans la mémoire, dans une structure C ++ et sans aucun nom, pour interdire à l'utilisateur d'accéder à un tel emplacement mémoire.
Pour le moment, je l'ai réalisé en mettant un vilain uint32_t :96;
champ de bits qui remplacera commodément trois mots, mais cela soulèvera un avertissement de GCC (Bitfield trop grand pour tenir dans uint32_t), ce qui est assez légitime.
Bien que cela fonctionne bien, ce n'est pas très propre lorsque vous souhaitez distribuer une bibliothèque avec plusieurs centaines de ces avertissements ...
Comment faire ça correctement?
Pourquoi y a-t-il un problème en premier lieu?
Le projet sur lequel je travaille consiste à définir la structure mémoire des différents périphériques de toute une ligne de microcontrôleurs (STMicroelectronics STM32). Pour ce faire, le résultat est une classe qui contient une union de plusieurs structures qui définissent tous les registres, en fonction du microcontrôleur ciblé.
Voici un exemple simple de périphérique assez simple: une entrée / sortie à usage général (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;
};
};
Où tout GPIO_MAPx_YYY
est une macro, définie soit comme uint32_t :32
soit le type de registre (une structure dédiée).
Ici, vous voyez uint32_t :192;
qui fonctionne bien, mais cela déclenche un avertissement.
Ce que j'ai considéré jusqu'à présent:
J'aurais pu le remplacer par plusieurs uint32_t :32;
(6 ici), mais j'ai quelques cas extrêmes où j'ai uint32_t :1344;
(42) (entre autres). Je préférerais donc ne pas ajouter une centaine de lignes sur 8k autres, même si la génération de structure est scriptée.
Le message d'avertissement exact est quelque chose comme:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type
(J'adore à quel point c'est louche).
Je préfère ne pas résoudre ce problème en supprimant simplement l'avertissement, mais en utilisant
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop
peut être une solution ... si je trouve TheRightFlag
. Cependant, comme indiqué dans ce fil , gcc/cp/class.c
avec cette triste partie de code:
warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);
Ce qui nous indique qu'il n'y a pas de -Wxxx
drapeau pour supprimer cet avertissement ...
uint32_t :192;
.
:42*32
place de:1344
char unused[12];
et ainsi de suite?