如何在不违反严格的混叠规则的情况下访问内存映射的多字节寄存器



我正在使用Xilinx Zynq (ARM)平台的嵌入式linux项目上工作,该项目需要将一些物理FPGA地址映射到虚拟地址空间中,以便我可以访问一些32位寄存器。是否有一种方法可以让我调用mmap(),然后在映射地址上覆盖一个32位数组,以便对这些寄存器进行单操作访问?

我目前使用memcpy()来遵守严格的混叠规则,但这显示为对FPGA的4次单独访问(每字节1次)。编译时指定-fno-strict-aliasing是我唯一安全的选择吗?

你误解了严格的混叠规则

关于类型的规则不是,只有。这也和语义学有关。只要适当类型的对象,通过void *转换到其他指针类型的混叠是完全可以的。(否则void *将不会有用。)

E。g。

uint32_t reg = 1337;
void *ptr = ®
*(uint32_t *)ptr = 42;

是可以的,因为ptr 不包含 uint32_t对象的地址;只是它有不同的类型。

那么,下面这段代码:

uint32_t *regs = mmap(0xf00ba12, ...);
regs[0] = 0xffffffff;

可能违反也可能不违反严格混叠规则,这取决于地址0xf00ba12的寄存器是否是uint32_t类型。因此,在您的情况下,这是有效的。


严格混叠规则涉及那些试图通过绕过类型系统并通过不同类型的左值访问对象来作弊的程序员。这当然涉及到转换指针,但这并不是转换和解引用指针的行为违反了严格混叠,而是在引用地址处没有给定类型的对象这一事实。<<p> <子>,请做strong>不是使用-fno-strict-aliasing !

这里解释了严格混叠本身,相关的标准引号是C99/C11 6.5 p.7。简而言之,它说您不能通过与其有效类型不同类型的左值访问对象(有一些例外,请参阅链接)。

C99/C11 6.5 p.6

*)如果一个值通过一个非字符类型的左值被存储到一个没有声明类型的对象中,那么该左值的类型将成为该访问和后续不修改该存储值的访问的有效类型。如果使用memcpy或memmove将值复制到没有声明类型的对象中,或者将值复制为字符类型的数组,那么对于该访问和后续不修改该值的访问,修改后的对象的有效类型是复制该值的对象的有效类型(如果有)。对于对没有声明类型的对象的所有其他访问,对象的有效类型只是用于访问的左值的类型。

*)已分配对象没有声明类型。

换句话说,你对该内存的第一次写访问决定了它的有效类型,直到下一次写访问,例如

void *foo = mmap(...);
*(int32_t *)foo = 1; // legal, the type of the mmaped object is now int32_t
*(float *)foo = 1.0; // legal, now the effective type is float
int32_t tmp = *(int32_t *)foo; // illegal, not compatible with the effective type

只要你访问你的映射寄存器只作为int32_t,你是安全的(你可以做更多)。

相关内容

最新更新