O problema
Em um contexto embarcado bare-metal de baixo nível , gostaria de criar um espaço em branco na memória, dentro de uma estrutura C ++ e sem nenhum nome, para proibir o usuário de acessar esse local de memória.
No momento, consegui colocar um campo de uint32_t :96;
bits feio que ocupará convenientemente o lugar de três palavras, mas gerará um aviso do GCC (Bitfield muito grande para caber em uint32_t), o que é bastante legítimo.
Embora funcione bem, não é muito claro quando você deseja distribuir uma biblioteca com várias centenas desses avisos ...
Como faço isso corretamente?
Por que existe um problema em primeiro lugar?
O projeto no qual estou trabalhando consiste em definir a estrutura de memória de diferentes periféricos de uma linha inteira de microcontroladores (STMicroelectronics STM32). Para fazer isso, o resultado é uma classe que contém uma união de várias estruturas que definem todos os registros, dependendo do microcontrolador alvo.
Um exemplo simples para um periférico bastante simples é o seguinte: um 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;
};
};
Onde tudo GPIO_MAPx_YYY
é uma macro, definida como uint32_t :32
ou o tipo de registro (uma estrutura dedicada).
Aqui você vê o uint32_t :192;
que funciona bem, mas dispara um aviso.
O que eu considerei até agora:
Eu posso ter substituído por vários uint32_t :32;
(6 aqui), mas tenho alguns casos extremos em que o fiz uint32_t :1344;
(42) (entre outros). Portanto, prefiro não adicionar cerca de cem linhas em cima de outras 8k, embora a geração da estrutura seja feita por script.
A mensagem de aviso exata é algo como:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type
(Eu adoro o quão sombrio é).
Prefiro não resolver isso simplesmente removendo o aviso, mas usando
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop
pode ser uma solução ... se eu encontrar TheRightFlag
. No entanto, como apontado neste tópico , gcc/cp/class.c
com esta triste parte do código:
warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);
O que nos diz que não há -Wxxx
sinalização para remover este aviso ...
uint32_t :192;
.
:42*32
vez de:1344
char unused[12];
e assim por diante?