tiangj
驱动牛犊
驱动牛犊
  • 注册日期2002-07-25
  • 最后登录2006-04-18
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
阅读:1509回复:5

关于DMA

楼主#
更多 发布于:2003-08-04 13:55

为什么每次DMA都要初始化..
m_CurrentTransfer->Initiate(.....
然后再m_CurrentTransfer->Continue(UseTransferSize);

不能初始化一次m_CurrentTransfer->Initiate(.....
然后保留其中初试化的相关参数.
以后每次DMA就执行m_CurrentTransfer->Continue(UseTransferSize);

有高手能给我指点么???
tianguojun@eyou.com
leerom
驱动小牛
驱动小牛
  • 注册日期2001-06-08
  • 最后登录2010-08-31
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望22点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2003-08-04 14:57
原因在于系统对内存的调度。比如,你的驱动程序完成了数据传输返回到应用程序,这时操作系统分配给你的应用程序的时间片刚好到期,于是你的应用程序被挂起。另一个应用程序投入运行,如果新的应用程序需要大量的内存,系统很有可能刚才的程序请到硬盘上的交换空间去。当被换出的程序再次被换入时,它所使用的物理地址可能会和上一次的不同。于是必须要重新计算DMA传输使用的物理地址(即重新调用m_CurrentTransfer->Initiate(.....)。
如果你实在不想每次初始化,那么你可以这样做:
1)在应用程序中用GlobalAlloc()和GlobalLock()来分配并锁定内存。
2)第一次读写设备时初始化dma链表。后续读写不必再初始化。
3)应用程序结束时,解锁并释放内存。
不推荐使用这个方法,因为这种方法只能使用一个缓冲区读取数据,不能进行异步I/O。所以并没有提高效率。(另外,我在用DDK直接写驱动时用过这个方法,没在DriverWorks下试过)。
leerom
tiangj
驱动牛犊
驱动牛犊
  • 注册日期2002-07-25
  • 最后登录2006-04-18
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2003-08-04 15:51
我按照你说的去做了,好像不行.
传回来的数据都是第一次的数据.
tianguojun@eyou.com
leerom
驱动小牛
驱动小牛
  • 注册日期2001-06-08
  • 最后登录2010-08-31
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望22点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地板#
发布于:2003-08-04 16:51
两种可能:
1)第二次之后dma地址不对,数据传到别的地方去了,检查dma地址。
2)第二次之后,没有启动dma硬件。我想你第二次只是简单的调用m_CurrentTransfer->Continue(UseTransferSize),这时的UseTransferSize应该表示传输已经完成,驱动程序立即就返回了。根本没有启动硬件。
leerom
tiangj
驱动牛犊
驱动牛犊
  • 注册日期2002-07-25
  • 最后登录2006-04-18
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望0点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2003-08-04 18:01
你回答的好像有道理,但是第二次怎样启动DMA???
tianguojun@eyou.com
leerom
驱动小牛
驱动小牛
  • 注册日期2001-06-08
  • 最后登录2010-08-31
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望22点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2003-08-05 09:14
直接写硬件寄存器。
再说明一次,我不推荐你使用这个方法。首先增加了驱动程序的复杂性,你要判断是否第一次数据传输等等。其次这个方法的致命的缺点是不支持多个数据缓冲区,这就是说你不但不能在一个应用程序中使用多缓冲,并且你的设备不能被多个应用程序同时打开(因为每个程序使用了不同的缓冲区)。不知你为什么要这么做?如果为了提高效率可以考虑在应用程序分配多个缓冲区,然后用异步I/O进行设备读写。这样你可以在处理第一个缓冲区的返回数据同时,让设备将数据写如第二个缓冲区,用并行处理提高效率不是更好吗?
leerom
游客

返回顶部