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

时间:2015-06-25 00:31:38

标签: c memory volatile memcpy memory-mapping

我正在开发一个涉及内存映射FPGA寄存器的I / O的嵌入式项目。需要将这些内存区域的指针标记为volatile,因此编译器不会优化"优化"通过缓存CPU寄存器中的值来读取和写入FPGA。

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

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

2 个答案:

答案 0 :(得分:4)

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

一些原因:

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

但是,您可以使用简单的for循环并自行复制。如果寄存器为volatile见下文),则这是安全的。

根据您的平台,仅volatile可能还不够。内存区域也必须不可缓存严格排序(和 - 可能 - 非共享)。否则,系统总线可能(并且对于某些平台)将重新排序访问。

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

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

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

答案 1 :(得分:0)

绝对不安全。无法保证memcpy将复制数据的顺序,以及一次复制多少字节。