我正在使用Xilinx Zynq(ARM)平台从事嵌入式Linux项目,该平台需要将一些物理FPGA地址映射到虚拟地址空间,以便访问某些32位寄存器。有没有办法让我调用mmap(),然后在映射地址上覆盖32位数组,以便对这些寄存器进行单一操作访问?
我目前正在使用memcpy()来遵守严格的别名规则,但这显示为对FPGA的4次单独访问(每个字节1次)。在编译时,我唯一可以选择指定-fno-strict-aliasing吗?
答案 0 :(得分:4)
您误解了严格的别名规则。
关于类型的规则不仅 。它也是关于语义的。只要是适当类型的对象,通过void *
强制转换为其他指针类型的方式就完全没问题了。 (否则void *
没用。)
电子。克,
uint32_t reg = 1337;
void *ptr = ®
*(uint32_t *)ptr = 42;
没问题,因为ptr
确实包含 uint32_t
对象的地址;只是它有不同的类型。
所以,下面这段代码:
uint32_t *regs = mmap(0xf00ba12, ...);
regs[0] = 0xffffffff;
可能会也可能不会违反严格的别名规则,具体取决于地址0xf00ba12
的注册是否为uint32_t
类型。因此,在您的情况下,这是有效的。
严格别名规则涉及程序员试图通过解决类型系统并通过不同类型的左值访问对象来作弊。当然这涉及到构建指针,但是它不是违反严格别名的转换和解除引用指针的行为,而是在引用地址处没有给定类型的对象这一事实。
请不使用-fno-strict-aliasing
!
答案 1 :(得分:3)
严格别名本身解释为here,相关标准报价为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
访问,您就可以安全了(您可以做得更多)。