阅读:2825回复:30
诡异的两个内存页面(100分!)
软件:w2k wdm
硬件:saa7146 目标:利用D1A通道采集视频数据显示,利用DEBI通道采集编码数据存盘。 问题:视频显示正常,但采集到的编码数据不正常,有时数据包中前两个页面(8k)的数据错误,但两个页面后面的数据正常,即: 若数据包4个页面,则称第3个数据包的四个页面为3a 3b 3c 3d 若数据出错表示为xx。 正确数据:1a 1b 1c 1d 2a 2b 2c 2d 3a 3b 3c 3d ... 错误数据:1a 1b 1c 1d xx xx 2c 2d 3a 3b 3c 3d ... 错误包出现频率为每几个至几百个包出现一次(随机) 改变包大小,若大于两个页面,则仍然是两个页面出错,除非包大小小于两个页面,则整个包出错,不影响下一个包。 实现方法:视频数据采集正常,在此不多说,采集编码数据时,在程序初始化时在非分页区申请四个同样大小的缓冲区(多页,页对齐,相当与上面提到的数据包),对rps编程可以实现四个缓冲区循环采集,每一个缓冲区完成后发出中断,并在rps中马上直接启动下一次DEBI传输,因此DEBI操作可以认为不受CPU干预。应用程序采集数据的流程为:应用程序通过deviceio发出启动命令,通知driver启动rps,硬件上开始循环采集,然后应用程序发出读数据命令传递给驱动一个已经被reset的event,并等待event事件,driver接受到后检查当前是否有已完成的缓冲区,若有,直接setevent,此时应用程序检测到event有效,则向driver发出请求返回数据包指令,driver立即返回已完成的缓冲区虚拟地址及长度,应用程序将该数据存盘;若应用程序发读数据命令时没有已完成的缓冲区,则驱动程序接受到该指令时保存应用程序传过来的event标记等待状态为真并返回,当缓冲区完成后isr程序被调用,isr检测等待状态是否为真,若是则set保存的event,唤醒等待中的应用程序线程,否则什么也不做。应用程序被唤醒后同样发出请求返回数据包指令,此时driver立即返回已完成的缓冲区虚拟地址及长度。 也就是: 应用程序: { 初始化event; 启动; while(notstop) { 清event; 发读数据指令并传送event; 等待event; 发请求返回数据包指令; 将返回的数据存盘; } 停止; } 驱动程序: { switch(指令) { case 启动: 启动rps; break; case 读数据: if(有已完成buffer)置event; else 等待=true,保存event; break; case 请求返回数据包: 返回当前第一个已完成的缓冲区虚拟地址; break; case 停止: 停止rps; break; } } isr: { if(该中断由视频数据产生)处理视频数据 else if(该中断由RPS产生) { if(等待 == true)set event } } rps: { while(notstop) { 利用BUFFER0初始化DEBI 启动DEBI 等待完成 产生中断 利用BUFFER1初始化DEBI 启动DEBI 等待完成 产生中断 利用BUFFER2初始化DEBI 启动DEBI 等待完成 产生中断 利用BUFFER3初始化DEBI 启动DEBI 等待完成 产生中断 } } to不了解7146的朋友: 7146为视频桥芯片,可以采集视频数据和一路其他数据(通过DEBI总线),视频数据和DEBI数据均可通过DMA向内存直接传送,并支持scatter/gather.所有DMA公用一个中断,通过中断状态寄存器确定产生中断的原因。 DEBI:数据扩展总线接口。 RPS:register program sequence,一段保存在内存中的指令,可以控制7146的所有寄存器,并有简单的条件、跳转等指令,启动后由7146自动通过dma逐条读入芯片运行,与cpu无关。 |
|
最新喜欢:![]() |
沙发#
发布于:2002-11-05 10:04
关于两个页面的数据错误: 哥们休假归来了?:D 项目作完了,老板该发奖金了吧,赫赫:D mmu是memory manage unit,就是管理分页内存的dma传输的,就是给它个页地址索引表,它就可以管理dma传输地址,使驱动感觉就是个连续地址一样。 郁闷的是,我的缓冲区全是固定的,事先申请好后直到关机都不会变的,页地址索引表的内容也从来不会变的,真不知什么原因。 若说开始位置出错,如果说开始位置写成了两页面后的位置,那么错误就是 a b c d e f --> a b x x c d 而不是我看到的 a b c d e f --> a b x x e f 若说开始位置写成其他页面了,那它有没有理由两个页面后还能回来。唉,虽然绕过了,可还是于心不甘 :( |
|
板凳#
发布于:2002-11-05 09:31
关于两个页面的数据错误:
因为后面的数据是正确的,所以可能是你捕捉数据的指令开始位置出错。 mmu的功能用来做什么啊! |
|
地板#
发布于:2002-11-05 09:12
郁闷 :(
是7146的mmu出的问题,scatter/gather没控制好,有没有人遇到过7146的这个问题,唉 :( :( 不过不用mmu就可以了,问题算是绕过去了,不爽啊。 不过还是多谢大家参与 :) |
|
地下室#
发布于:2002-11-01 12:01
感觉与BT878传输方式的差不多。 是把数据保存好后再启动下一次dma吗,这样做我这里也可以,可是我的dpc总是延迟太大,而我的数据源很容易溢出:(所以我想用rps脱离cpu启动dma,保证两次dma间的延迟最小 |
|
5楼#
发布于:2002-11-01 11:52
感觉与BT878传输方式的差不多。
我做的与你有一点不一样: 就是在DMA传输之前,把中断事件传入到DRIVER中。 |
|
|
6楼#
发布于:2002-11-01 08:42
只要你在低于DIRQL上对硬件操作,就会被ISR例程打断!实际上只要你的driver里面有ISR,你用softice一看就知道,ISR是不停的被调用!(而不管是不是你的板卡来了中断!)在rps运行期间被isr打断,就有可能出现你这样的错误!
|
|
7楼#
发布于:2002-10-31 19:02
还有,对这个两页面现象有没有一个可能的解释呢,不然,我×不瞑目 :( :( :mad: :mad:不管可能性有多大
|
|
8楼#
发布于:2002-10-31 18:59
非常感谢热心的各位,我会试试看 :)
不过有一点要指出的是,这里的rps是不会被中断的,因为rps是被7146读入芯片内,由7146执行的risc指令,是属于7146的指令,指令是由7146控制的dma从内存中读入,一旦读入运行后,脱离计算机的,我也就是看重这一点才采用rps来控制debi数据的读取的 :) |
|
9楼#
发布于:2002-10-31 17:38
我的意思就是用KeSynchronizeExecution()函数把rps作成中断同步例程!在DDK帮助里面看看这个函数!因为我当初也是你那样写的,就是有错!后来这样改了,就好了! :D :cool: :cool: 有道理,应该这样,否则rps可以被中断似乎会出问题 |
|
|
10楼#
发布于:2002-10-31 17:37
通过设备对象可以拿到中断对象吗? 设备扩展中应该保留中断对象的指针 |
|
|
11楼#
发布于:2002-10-31 17:27
我的意思就是用KeSynchronizeExecution()函数把rps作成中断同步例程!在DDK帮助里面看看这个函数!因为我当初也是你那样写的,就是有错!后来这样改了,就好了! :D :cool: :cool:
|
|
12楼#
发布于:2002-10-31 17:15
通过设备对象可以拿到中断对象吗?
|
|
13楼#
发布于:2002-10-31 17:14
另外,中断同步例程是在什么时候执行的阿,和dpc有什么区别呢,我是说从分工上?
|
|
14楼#
发布于:2002-10-31 17:10
嗨,哥们,你最好把rps例程作成中断同步例程,否则isr要影响rps的! :o 我就是怕isr影响rps,所以把rps写成独立于cpu的循环读,这样可以吗?另外,目前我只能在dpc中做文章,中断对象不是我创建的,我目前拿不到中断对象,难以初始化中断同步例程,要改成中断同步例程可能会涉及到很大的工作量(改程序的尴尬),用dpc不行吗? |
|
15楼#
发布于:2002-10-31 16:46
嗨,哥们,你最好把rps例程作成中断同步例程,否则isr要影响rps的!
|
|
16楼#
发布于:2002-10-31 16:09
应用程序:“给我数据!” 驱动程序把上次给应用程序的buffer号加加,得到这次应该给它的buffer号,然后与标志寄存器比较,看看这个buffer是不是正在进行,若是就说:“等等!”,若不是,就说:“你可以取了!” [编辑 - 10/31/02 by gung] |
|
17楼#
发布于:2002-10-31 16:03
太长了,眼晕了。 抱歉,呵呵 :D |
|
18楼#
发布于:2002-10-31 16:01
用户被禁言,该主题自动屏蔽! |
|
19楼#
发布于:2002-10-31 16:01
3。有倒是有个标志,7146有个寄存器可以有四个标志信号位,rps启动一个缓冲区时就至相应的信号位,然后驱动程序就是根据这个标志寄存器的值来确定当前正在进行的缓冲区号的。 可是应用程序不知道啊, |
|
|
上一页
下一页