简体   繁体   English

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

[英]Using memcpy and friends with memory-mapped I/O

I'm working on an embedded project which involves I/O on memory-mapped FPGA registers. 我正在研究一个涉及内存映射FPGA寄存器的I / O的嵌入式项目。 Pointers to these memory regions need to be marked volatile so the compiler does not "optimize out" reads and writes to the FPGA by caching values in CPU registers. 这些存储区域的指针需要标记为volatile因此编译器不会通过缓存CPU寄存器中的值来“优化”对FPGA的读写操作。

In a few cases, we want to copy a series of FPGA registers into a buffer for further use. 在少数情况下,我们希望将一系列FPGA寄存器复制到缓冲区中以供进一步使用。 Since the registers are mapped to contiguous addresses, memcpy seems appropriate, but passing our volatile pointer as the source argument gives a warning about discarding the volatile qualifier. 由于寄存器映射到连续的地址, memcpy似乎是合适的,但是传递我们的volatile指针作为source参数会发出关于丢弃volatile限定符的警告。

Is it safe (and sane) to cast away the volatile -ness of the pointer to suppress this warning? 是否安全(并且理智)抛弃指针的volatile以抑制此警告? Unless the compiler does something magical, I can't imagine a scenario where calling memcpy would fail to perform an actual copy. 除非编译器做了一些神奇的事情,否则我无法想象调用memcpy会无法执行实际复制的情况。 The alternative is to just use a for loop and copy byte by byte, but memcpy implementations can (and do) optimize the copy based on size of the copy, alignment, etc. 另一种方法是只使用for循环并逐字节复制,但memcpy实现可以(并且确实)根据副本的大小,对齐等来优化副本。

As a developer of both: FPGA and embedded software, there is just one clear answer: do not use memcpy et al. 作为FPGA和嵌入式软件的开发人员,只有一个明确的答案: 不要使用memcpy等。 for this 为了这

Some reasons: 一些原因:

  • There is no guarantee memcpy will work in any specific order. 无法保证memcpy可以按任何特定顺序运行。
  • The compiler might very well replace the call with inline code. 编译器可能会使用内联代码替换调用。
  • Such acceses often require a certain word-size. 这种接受通常需要一定的字大小。 memcpy does not guarantee that. memcpy不保证。
  • Gaps in the register map might result in undefined behaviour. 寄存器映射中的间隙可能导致未定义的行为。

You can, however, use a simple for loop and copy yourself. 但是,您可以使用简单的for循环并自行复制。 This is safe, if the registers are volatile ( see below ). 如果寄存器是volatile ,这是安全的( 见下文 )。

Depending on your platform, volatile alone might not be sufficient. 根据您的平台,单独使用volatile可能还不够。 The memory area has also to be non-cachable and strictily ordered (and - possibly - non-shared). 内存区域也必须是不可 缓存严格排序的 (并且可能是非共享的)。 Otherwise the system busses might (and will for some platforms) reorder accesses. 否则,系统总线可能(并且将针对某些平台)重新排序访问。

Furthermore, you might need barriers/fences for your CPU not to reorder accesses. 此外,您可能需要CPU的障碍/围栏不要重新排序访问。 Please read your hardware-specs very carefully about this. 请仔细阅读您的硬件规格。

If you need to transfer larger blocks more often, think about using DMA. 如果您需要更频繁地传输更大的块,请考虑使用DMA。 If the FPGA uses PCI(e), you could use busmaster DMA with scatter/gather for instance (however, this is not easily implemented; did that myself, but might be worth the effort). 如果FPGA使用PCI(e),你可以使用带有分散/聚集的busmaster DMA(但是,这不容易实现;自己这样做,但可能值得付出努力)。

The best (and most sane) approach depends actually on multiple factors, like platform, required speed, etc. Of all possible approaches, I would deem using mempcy() one of the lesser sane(1) at best (1): not sure if that is correct grammar, but I hope you got my point). 最好的(也是最理智的)方法实际上取决于多种因素,例如平台,要求的速度等。在所有可能的方法中,我认为使用mempcy()一个(1)(1):不确定如果这是正确的语法,但我希望你得到我的观点)。

Absolutely not safe. 绝对不安全。 There is no guarantee whatsoever in which order memcpy will copy the data, and how many bytes are copied at a time. 无法保证memcpy将复制数据的顺序,以及一次复制多少字节。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM