WinCE CEDDK之DMA相关函数

本文深入探讨了CEDDK/DDK_DMA/ddk_dma.c文件中的DMA内存管理函数HalAllocateCommonBuffer和HalFreeCommonBuffer的用法。通过介绍DMA适配器结构和函数参数,解释了如何使用这些函数进行DMA内存的申请与释放。并通过实例演示了在实际应用中的操作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CEDDK提供了DMA的相关函数,在CEDDK/DDK_DMA/ddk_dma.c中定义。实际上里面最有用的就两个函数,HalAllocateCommonBuffer(..)HalFreeCommonBuffer(..)分别用于为DMA申请和释放内存。

 

首先介绍一下会用到的DMA适配器结构,在ceddk.h中定义,如下:

  1. typedef struct _DMA_ADAPTER_OBJECT_
  2. {
  3.     USHORT ObjectSize;               //该结构的大小
  4.     INTERFACE_TYPE InterfaceType;    //接口类型,一般用做DMA时设置为Internal
  5.     ULONG BusNumber;                 //一般设置为0
  6. } 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操作的物理内存必须是连续的。该函数调用成功以后,返回值是虚拟地址,可以在驱动中访问其中的内容,函数的第三个参数返回内存的物理地址,可以赋值给DMA控制器来完成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函数来完成内存的释放,所以在使用该函数的时候,只有函数的第四个参数是必须的,也就是内存的虚拟地址,其他的都可以忽略。

 

下面给个使用上面两个函数的例子:

  1. DMA_ADAPTER_OBJECT dmaAdapter;
  2. //初始化DMA适配器
  3. dmaAdapter.ObjectSize = sizeof(dmaAdapter);
  4. dmaAdapter.InterfaceType = Internal;
  5. dmaAdapter.BusNumber = 0;
  6. //分配DMA内存
  7. m_pDMABuf = (PBYTE)HalAllocateCommonBuffer( &dmaAdapter, 256 * 1024, &m_pDMABufPhys, FALSE );
  8. //将物理地址赋值给DMA控制器
  9. vm_pDMAreg->DST = (int)m_pDMABufPhys.LowPart;
  10. ...
  11. //释放DMA内存
  12. if( m_pDMABuf != NULL )
  13. {
  14.      HalFreeCommonBuffer( NULL, 0, 0, m_pDMABuffer, FALSE);
  15.      m_pDMABuf = NULL;
  16. }

在ddk_dma.c中,还可以看到其他很多DMA相关的操作函数。这些DMA函数是用来操作DMA设备的,通过CreateFile来打开DMA设备,然后调用DeviceIoControl函数来访问DMA设备。DMA设备驱动在/WINCE600/PUBLIC/Common/Oak/Drivers/DMA下面,该DMA驱动以流设备驱动的形式实现。

一般来说,DMA驱动会配合其他设备驱动来完成数据传输,所以很少会被单独作为一个设备来使用,大多数情况我们开发设备驱动时需要用到DMA的时候,会用到上面两个函数来申请和释放内存。

DMA(Direct Memory Access)是一种允许外设与内存之间直接进行数据传输的硬件机制,避免了CPU参与传输过程。在不同的系统和平台中,DMA相关函数可能有所不同。以下是一些常见的DMA相关函数及其用途: 1. **HalAllocateCommonBuffer** 和 **HalFreeCommonBuffer** - 这两个函数用于为DMA操作申请和释放内存。它们通常用于Windows驱动开发中的CEDDK环境。 - `HalAllocateCommonBuffer` 用于分配DMA缓冲区[^1]。 - `HalFreeCommonBuffer` 用于释放之前分配的DMA缓冲区[^1]。 2. **dma_fence_init** - 这个函数用于初始化DMA fence对象,它在Linux内核中使用,用来同步DMA操作。 - 函数原型:`void dma_fence_init(struct dma_fence *fence, const struct dma_fence_ops *ops, spinlock_t *lock, u64 context, u64 seqno)`[^3]。 - `dma_fence_init` 的作用是设置fence对象的基本属性,包括操作结构体、锁、上下文和序列号等[^5]。 3. **dma_dence_init** - 在某些实现中,可能会有类似的函数名如 `dma_dence_init` 来初始化DMA fence对象,尽管这可能是拼写错误或特定于某个项目的命名[^5]。 4. **STM32 DMA控制器相关函数** - 对于STM32系列微控制器,DMA控制器提供了多个函数来管理DMA通道和数据流。这些函数通常涉及配置DMA参数、启动传输以及处理中断等。 - STM32F4最多可以有两个DMA控制器(DMA1和DMA2),每个控制器有8个数据流,每个数据流有8个通道[^2]。 5. **其他通用DMA函数** - 在嵌入式系统中,DMA函数通常包括初始化DMA模块、配置DMA通道、启动DMA传输、停止DMA传输等功能。 - 例如,在STM32的HAL库中,会有像 `HAL_DMA_Start`, `HAL_DMA_Stop`, `HAL_DMA_GetState` 等函数[^2]。 ### 示例代码 下面是一个简单的示例,展示如何使用 `dma_fence_init` 来初始化一个DMA fence对象: ```c struct dma_fence my_fence; const struct dma_fence_ops my_fence_ops = { // 定义必要的操作函数 }; spinlock_t my_lock; // 初始化自旋锁 spin_lock_init(&my_lock); // 初始化DMA fence dma_fence_init(&my_fence, &my_fence_ops, &my_lock, 0x1234, 0); ``` 这个例子假设你已经有了一个定义好的 `dma_fence_ops` 结构体,并且已经初始化了一个自旋锁。通过调用 `dma_fence_init`,你可以创建一个DMA fence实例,以便在DMA操作中使用。 ### 注意事项 - 在实际应用中,需要根据具体的硬件平台和操作系统选择合适的DMA函数。 - 需要确保DMA操作的安全性和正确性,比如正确地同步DMA操作以防止数据竞争问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值