使用内存映射I / O的memcpy和朋友

我正在研究一个涉及内存映射FPGA寄存器的I / O的嵌入式项目.这些存储区域的指针需要标记为volatile,因此编译器不会通过缓存CPU寄存器中的值来“优化”对FPGA的读写操作.

在少数情况下,我们希望将一系列FPGA寄存器复制到缓冲区中以供进一步使用.由于寄存器映射到连续的地址,memcpy似乎是合适的,但是传递我们的volatile指针作为source参数会发出关于丢弃volatile限定符的警告.

是否安全(并且理智)抛弃指针的易失性以抑制此警告?除非编译器做了一些神奇的事情,否则我无法想象调用memcpy会无法执行实际复制的情况.另一种方法是只使用for循环并逐字节复制,但memcpy实现可以(并且确实)根据副本的大小,对齐等来优化副本.

最佳答案
作为FPGA和嵌入式软件的开发人员,只有一个明确的答案:不要使用memcpy等.为了这

一些原因:

>无法保证memcpy可以按任何特定顺序运行.
>编译器可能会使用内联代码替换调用.
>此类加入通常需要一定的字大小. memcpy不保证.
>寄存器映射中的间隙可能导致未定义的行为.

但是,您可以使用简单的for循环并自行复制.如果寄存器是易失性的,这是安全的(见下文).

根据您的平台,单独使用volatile可能还不够.内存区域也必须是不可缓存且严格排序的(并且可能是非共享的).否则,系统总线可能(并且将针对某些平台)重新排序访问.

此外,您可能需要CPU的障碍/围栏不要重新排序访问.请仔细阅读您的硬件规格.

如果您需要更频繁地传输更大的块,请考虑使用DMA.如果FPGA使用PCI(e),你可以使用带有分散/聚集的busmaster DMA(但是,这不容易实现;自己这样做,但可能值得付出努力).

最好的(也是最理智的)方法实际上取决于多种因素,例如平台,要求的速度等.在所有可能的方法中,我认为使用mempcy()最小的一个(1)(1):不确定如果这是正确的语法,但我希望你得到我的观点).

转载注明原文:使用内存映射I / O的memcpy和朋友 - 代码日志