Linux 复制到DMA缓冲区时,memcpy()挂起

Linux 复制到DMA缓冲区时,memcpy()挂起,linux,arm,memcpy,neon,dma,Linux,Arm,Memcpy,Neon,Dma,我通过从“普通”内存中复制290字节的数据块,周期性地用我的数据填充mmap ed DMA缓冲区 在第一个循环中memcpy始终通过OK。在第二个循环中,它挂起在\uu memcpy\u neon(至少每次按下Ctrl-C时gdb都会这样说) 反汇编程序总是显示插入的strmi指令 仅出于测试目的,我用我的简单字节替换了memcpy(),在所有3MB DMA缓冲区上一切都很好(但显然速度较慢…:-)。为了排除对齐问题,我测试了库memcpy()以复制未对齐的缓冲区-未检测到任何问题 我在DM81

我通过从“普通”内存中复制290字节的数据块,周期性地用我的数据填充mmap ed DMA缓冲区

在第一个循环中
memcpy
始终通过OK。在第二个循环中,它挂起在
\uu memcpy\u neon
(至少每次按下Ctrl-C时gdb都会这样说)

反汇编程序总是显示插入的
strmi
指令

仅出于测试目的,我用我的简单字节替换了
memcpy()
,在所有3MB DMA缓冲区上一切都很好(但显然速度较慢…:-)。为了排除对齐问题,我测试了库
memcpy()
以复制未对齐的缓冲区-未检测到任何问题

我在
DM8148
CPU上使用
Linux2.6.37
Glibc2.23(GCC6.3.1Linaro)

为什么这个memcpy通常挂起,第二次挂起,特别是

更新:在对memcpy的不同汇编器变体进行了大量实验之后,我可以说挂起的是NEON内存拷贝指令,包括预加载和未预加载:

Loop:
  PLD [r1, #0xC0]
  VLDM r1!,{d0-d7}
  VSTM r0!,{d0-d7}
  SUBS r2,r2,#0x40
  BNE Loop
memcpy()的所有其他“正常”变体都可以正常工作。
将DMA未缓存(!)MMA内存与霓虹灯指令一起使用有什么神秘之处吗?

嗯,答案似乎是“是的!将DMA未缓存(!)MMA内存与霓虹灯指令一起使用有神秘之处”。正如ARM手册所述,“Cortex A8支持未对齐的内存访问。但是不支持对强顺序内存的未对齐访问”
由于DMA缓冲区很可能是强有序内存,因此使用NEON的glibc memcpy在访问此DMA内存时失败。在我的第二个循环中发生了这种情况,因为第一个访问是对齐的,而第二个没有对齐。

你能解释一下为什么有两个memcpy吗?你有什么代码可以共享吗?@Stoogy我相信这些源代码是为那个memcpy提供的。@Stoogy不知道你的意思。从数据源复制到DMA缓冲区是一个无止境的循环。库memcpy()在第二个周期挂起。当我使用简单的字节复制时,一切正常-这意味着没有边界、映射或类似的问题。你应该检查地址是否与8对齐。如果不能保证对齐,则应使用
vld1.8
vst1.8
说明。@Jake'Alquimista'LEE,谢谢。是的,我需要检查这个,但是我需要检查传递给C-library memcpy()函数的参数吗?!?!如果您对此有任何控制权,请尝试不要使用强顺序内存(或设备内存),除非您确实需要。对于大多数DMA用例,您可以使用未缓存的“普通”内存,这允许未对齐的访问。我真的不明白什么是“强有序”内存。我的DMA缓冲区在普通的DDR中,我在Linux的“虚拟内核内存布局”中看到的是“DMA”。我使用dma_alloc_coherent()接收此内存。请评论…:-)尝试使用
dma_alloc_writecombine()
,但请注意,这将开始使用CPU写缓冲区,因此您需要调用
dma_wmb()
,以确保在启动对另一个硬件的任何访问之前,写缓冲区已耗尽。@solidpixel感谢您的教训-非常有趣,我不知道。遗憾的是,我不能使用
dma\u wmb()
——所有这些都在用户空间中运行。但它是非常有用的知识。同时,我以Android版本的
memcpy()
结束,每个块16个字节略微更改为64…:-)这个版本使用预对齐代码。。。