Das Thema
In einem Bare-Metal-Embedded- Kontext auf niedriger Ebene möchte ich einen leeren Bereich im Speicher innerhalb einer C ++ - Struktur und ohne Namen erstellen, um dem Benutzer den Zugriff auf diesen Speicherort zu verbieten.
Im Moment habe ich es erreicht, indem ich ein hässliches uint32_t :96;
Bitfeld eingefügt habe, das bequemerweise drei Wörter ersetzt, aber eine Warnung von GCC auslöst (Bitfeld zu groß, um in uint32_t zu passen), was ziemlich legitim ist.
Es funktioniert zwar einwandfrei, ist aber nicht sehr sauber, wenn Sie eine Bibliothek mit mehreren Hundert dieser Warnungen verteilen möchten ...
Wie mache ich das richtig?
Warum gibt es überhaupt ein Problem?
Das Projekt, an dem ich arbeite, besteht darin, die Speicherstruktur verschiedener Peripheriegeräte einer gesamten Mikrocontrollerleitung (STMicroelectronics STM32) zu definieren. Das Ergebnis ist eine Klasse, die eine Vereinigung mehrerer Strukturen enthält, die abhängig vom Ziel-Mikrocontroller alle Register definieren.
Ein einfaches Beispiel für ein ziemlich einfaches Peripheriegerät ist das folgende: ein GPIO (General Purpose Input / Output)
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;
};
};
Wobei alles GPIO_MAPx_YYY
ein Makro ist, das entweder als uint32_t :32
oder als Registertyp definiert ist (eine dedizierte Struktur).
Hier sehen Sie, uint32_t :192;
was gut funktioniert, aber es löst eine Warnung aus.
Was ich bisher bedacht habe:
Ich hätte es vielleicht durch mehrere ersetzen können uint32_t :32;
(6 hier), aber ich habe einige extreme Fälle, in denen ich uint32_t :1344;
(42) (unter anderem) habe. Daher möchte ich lieber nicht etwa hundert Zeilen über 8.000 Zeilen hinzufügen, obwohl die Strukturgenerierung in Skripten ausgeführt ist.
Die genaue Warnmeldung ist ungefähr so:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type
(Ich liebe es einfach, wie schattig es ist).
Ich würde dies lieber nicht lösen, indem ich einfach die Warnung entferne, sondern die Verwendung von
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop
kann eine Lösung sein ... wenn ich finde TheRightFlag
. Wie in diesem Thread erwähnt , gcc/cp/class.c
mit diesem traurigen Codeteil:
warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);
Was uns sagt, dass es keine -Wxxx
Flagge gibt, um diese Warnung zu entfernen ...
uint32_t :192;
.
:42*32
anstelle von:1344
char unused[12];
und so weiter?