问题描述:
RapidIO卡在收发数据时,均使用了DMA方式。发送方式为先malloc一段memory空间,然后把该段空间的首地址写入到DMA的基地址寄存器中,以后在发送数据时,就将数据复制到该memory空间中,然后启动DMA发送即可,接收也是相同的方法。
目前的问题是发送和接收均不正确,原因是:设备驱动使用DMA工作方式对所申请的memory空间有一定要求,首先需要memory空间在物理上连续,另外malloc出来的memory空间的地址因为是虚拟地址,所以需要先将该地址转换成物理地址,再把该物理地址写入到DMA的基地址寄存器中去,这样DMA才能正确的在正确的物理地址空间上去发送数据,接收也是同样的道理。所以我们如果malloc一段memory空间,但malloc不能保证这段memory空间在物理上连续,另外malloc在上层分配的memory空间也是虚拟地址空间,所以还需要将该虚拟地址先调用转换函数将其转换成物理地址之后才能使用,但目前VISA并没有找到提供分配连续空间的函数,也没有提供将虚拟地址转换成物理地址的函数,所以现在DMA收发存在问题。
其他平台对驱动中的DMA方式的支持:
Windows平台:
申请连续的memory空间有专门的函数,如下:
VirtualAddress = MmAllocateContiguousMemory(Len, PhyAddress);
上面的函数就申请到了在物理上连续的memory空间,但申请到的memory依然是虚拟地址,所以有另外一个专门的函数将该虚拟地址转换成物理地址,如下:
PhyAddress = MmGetPhysicalAddress(VirtualAddress);
然后就可以将转换后得到的物理地址PhyAddress写入到DMA相关的基地址中去,这样DMA就能正确的工作。
VxWorks平台:
vxworks平台因为用于嵌入式实时系统,所以vxworks和其他一般的操作系统有所不同,最大的不同就是vxworks一般使用的flat地址空间,就是不分用户空间和内核空间,所以程序和操作系统都是位于同一个地址空间范围内,没有换页的功能,所以应用程序能访问到整个内存地址,也可以破坏操作系统的代码,因为这样,所以在vxworks平台malloc一段memory空间的话,其必然在物理上连续,同时也就是物理地址,所以可以直接将该首地址写入到DMA的基地址中去,DMA也能正常工作。
综上,每个平台都有自己的DMA实现方式,但目前NI的VISA驱动模型却没有找到相关DMA支持方式???