CEDDK提供了DMA的相关函数,在CEDDK/DDK_DMA/ddk_dma.c中定义。实际上里面最有用的就两个函数,HalAllocateCommonBuffer(..)和HalFreeCommonBuffer(..)分别用于为DMA申请和释放
首先介绍一下会用到的DMA适配器结构,在ceddk.h中定义,如下:
typedef struct _DMA_ADAPTER_OBJECT_
{
USHORT ObjectSize; //该结构的大小
INTERFACE_TYPE InterfaceType; //接口类型,一般用做DMA时设置为Internal
ULONG BusNumber; //一般设置为0
} DMA_ADAPTER_OBJECT, *PDMA_ADAPTER_OBJECT;
下面介绍一下函数:
1. DMA内存分配函数:
PVOID HalAllocateCommonBuffer(PDMA_ADAPTER_OBJECT DmaAdapter, ULONG Length, PPHYSICAL_ADDRESS LogicalAddress, BOOLEAN CacheEnabled)
DmaAdapter: DMA适配器结构指针
Length: 要分配的内存的大小
LogicalAddress: 分配成功后,内存的物理起始地址
CacheEnabled: 是否使用Cache
实际上该函数通过调用AllocPhysMem函数来分配一段物理地址连续的内存,这段内存默认是64KB字节对齐的,这完全可以理解,DMA操作的物理内存必须是连续的。该函数调用成功以后,返回值是虚拟地址,可以在
2. DMA内存释放函数:
VOID HalFreeCommonBuffer(PDMA_ADAPTER_OBJECT DmaAdapter, ULONG Length, PHYSICAL_ADDRESS LogicalAddress, PVOID VirtualAddress, BOOLEAN CacheEnabled)
DmaAdapter: DMA适配器结构指针
Length: 内存的大小
LogicalAddress: 内存的物理起始地址
VirtualAddress: 内存的虚拟地址
CacheEnabled: 是否使用Cache
该函数通过调用FreePhysMem函数来完成内存的释放,所以在使用该函数的时候,只有函数的第四个参数是必须的,也就是内存的虚拟地址,其他的都可以忽略。
下面给个使用上面两个函数的例子:
DMA_ADAPTER_OBJECTdmaAdapter;
//初始化DMA适配器
dmaAdapter.ObjectSize=sizeof(dmaAdapter);
dmaAdapter.InterfaceType=Internal;
dmaAdapter.BusNumber=0;
//分配DMA内存
m_pDMABuf=(PBYTE)HalAllocateCommonBuffer(&dmaAdapter,256*1024,&m_pDMABufPhys,FALSE);
//将物理地址赋值给DMA控制器
vm_pDMAreg->DST=(int)m_pDMABufPhys.LowPart;
...
//释放DMA内存
if(m_pDMABuf!=NULL)
{
HalFreeCommonBuffer(NULL,0,0,m_pDMABuffer,FALSE);
m_pDMABuf=NULL;
}
在ddk_dma.c中,还可以看到其他很多DMA相关的
一般来说,DMA驱动会配合其他设备驱动来完成数据传输,所以很少会被单独作为一个设备来使用,大多数情况我们开发设备驱动时需要用到DMA的时候,会用到上面两个函数来申请和释放内存。
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/xinchow/archive/2010/04/12/5477723.aspx