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