问题
在低级裸机嵌入式上下文中,我想在内存中创建一个空白空间,在 C++ 结构中并且没有任何名称,以禁止用户访问这样的内存位置.
现在,我通过放置一个丑陋的 uint32_t :96;
来实现它bitfield 可以方便地代替三个单词,但它会从 GCC 发出警告(Bitfield too large to fit in uint32_t),这是非常合法的。
虽然它工作正常,但当您想要分发包含数百个此类警告的库时,它不是很干净......
我该如何正确地做到这一点?
首先为什么会出现问题?
我正在进行的项目包括定义整个微 Controller 系列 (STMicroelectronics STM32) 的不同外设的内存结构。为此,结果是一个包含多个结构 union 的类,这些结构定义了所有寄存器,具体取决于目标微 Controller 。
一个非常简单的外围设备的简单示例如下:通用输入/输出 (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;
};
};
所有GPIO_MAPx_YYY
是一个宏,定义为 uint32_t :32
或寄存器类型(专用结构)。
在这里您可以看到 uint32_t :192;
效果很好,但会触发警告。
到目前为止我所考虑的:
我可能已经用几个 uint32_t :32;
替换了它(此处为 6),但我有一些极端情况,我有 uint32_t :1344;
(42) (除其他外)。因此,即使结构生成是脚本化的,我也不愿在 8k 其他行之上添加大约 100 行。
确切的警告信息类似于:
width of 'sool::ll::GPIO::<anonymous union>::<anonymous struct>::<anonymous>' exceeds its type
(我就是喜欢它的阴暗面)。
我宁愿不通过简单地删除警告来解决这个问题,而是使用
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-WTheRightFlag"
/* My code */
#pragma GCC diagnostic pop
可能是一个解决方案...如果我找到 TheRightFlag
.但是,正如 this thread 中指出的那样, gcc/cp/class.c
用这个悲伤的代码部分:
warning_at (DECL_SOURCE_LOCATION (field), 0,
"width of %qD exceeds its type", field);
这告诉我们没有 -Wxxx
标记以删除此警告...
最佳答案
C++ 方式怎么样?
namespace GPIO {
static volatile uint32_t &MAP0_MODER = *reinterpret_cast<uint32_t*>(0x4000);
static volatile uint32_t &MAP0_OTYPER = *reinterpret_cast<uint32_t*>(0x4004);
}
int main() {
GPIO::MAP0_MODER = 42;
}
由于 GPIO
命名空间,您可以自动完成,并且不需要虚拟填充。甚至,更清楚发生了什么,因为您可以看到每个寄存器的地址,您根本不必依赖编译器的填充行为。
关于c++ - 如何在 C++ 类内存结构中创建 "spacer"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53109888/