阅读:2805回复: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-10-31 14:32
我来了,看看先 :D
|
|
|
板凳#
发布于:2002-10-31 14:40
谢了,呵呵
我想有没有可能是同步问题,这里可能的问题是: 1。中断处理可能不及时,我是在dpc中做的 2. rps运行与cpu无关,通过设置某些寄存器标记当前进行的缓冲区号,以实现与cpu同步,有可能同步没有做好 3。四个缓冲区循环采集,应用程序只是循环得到这四个缓冲区的地址,若出现太大的滞后,有可能缓冲区被新的dma改写,不过要出现这种情况,除非rps与cpu同步做的太差 4。无法解释为什么是2个页面,我从未在哪设置过2个页面这个大小 |
|
地板#
发布于:2002-10-31 15:20
有点长。
|
|
地下室#
发布于:2002-10-31 15:23
有点长。 看在100分的份上,辛苦一下吧 ;) 小弟实在郁闷,无法解释 :( |
|
5楼#
发布于:2002-10-31 15:26
没看懂你的意思,不过我想不就是从驱动里面把数据读到应用层嘛?我觉得可以在驱动里面做一个缓冲区,应用程序里面开一个线程,不停地从驱动读,应该没问题吧?还有我觉得你这种情况很怪异,为什么中间差几个字节。
|
|
6楼#
发布于:2002-10-31 15:27
你的IOCTL_CODE的定义呢?
|
|
7楼#
发布于:2002-10-31 15:33
网站又不对了,半天没上来
我到是看明白了,但是觉得处理方式没什么问题 确实很诡异 :mad: |
|
|
8楼#
发布于:2002-10-31 15:33
没看懂你的意思,不过我想不就是从驱动里面把数据读到应用层嘛?我觉得可以在驱动里面做一个缓冲区,应用程序里面开一个线程,不停地从驱动读,应该没问题吧?还有我觉得你这种情况很怪异,为什么中间差几个字节。 就是这样呀,这么别扭主要是因为读数必须保持较好的连续性,一次读结束不能等待cpu处理万数据在启动下一次读,这样的话数据源很容易溢出,所以设置了4个缓冲区,独立于cpu循环读,然后应用程序里开线程不停的读。 另,不是差几个字节,而是错了两个页(8k) |
|
9楼#
发布于:2002-10-31 15:37
谢了,呵呵 1。偶觉得中断应该来的及,因为你在isr中并没有作什么事情,设置事件只能在dpc中。 2。同步如果不合适,不会只有两个页面有问题了 3。这个到有可能,应用程序似乎不应该直接读那四个缓冲区,怎么的也应该有个标志辨明是不是应该读, 4。霍霍,不知道 :D |
|
|
10楼#
发布于:2002-10-31 15:41
你的IOCTL_CODE的定义呢? ioctl的传递和处理应该是正确地,出错的数据包只是前两个页有问题,后面的数据是正确的,这样的话,我想数据包的虚拟地址应该是传对了吧 |
|
11楼#
发布于:2002-10-31 15:49
1.事实上中断处理程序没有做什么,只是检测中断状态寄存器,然后将相应的处理程序排入dpc,而所有处理工作是在dpc中进行的,由于一些原因,中断处理程序不能修改,只能修改dpc,由于视频的处理较复杂,而且在前面处理的,因此还是有延时的。 2。是阿 3。有倒是有个标志,7146有个寄存器可以有四个标志信号位,rps启动一个缓冲区时就至相应的信号位,然后驱动程序就是根据这个标志寄存器的值来确定当前正在进行的缓冲区号的。 |
|
12楼#
发布于:2002-10-31 16:01
3。有倒是有个标志,7146有个寄存器可以有四个标志信号位,rps启动一个缓冲区时就至相应的信号位,然后驱动程序就是根据这个标志寄存器的值来确定当前正在进行的缓冲区号的。 可是应用程序不知道啊, |
|
|
13楼#
发布于:2002-10-31 16:01
用户被禁言,该主题自动屏蔽! |
|
14楼#
发布于:2002-10-31 16:03
太长了,眼晕了。 抱歉,呵呵 :D |
|
15楼#
发布于:2002-10-31 16:09
应用程序:“给我数据!” 驱动程序把上次给应用程序的buffer号加加,得到这次应该给它的buffer号,然后与标志寄存器比较,看看这个buffer是不是正在进行,若是就说:“等等!”,若不是,就说:“你可以取了!” [编辑 - 10/31/02 by gung] |
|
16楼#
发布于:2002-10-31 16:46
嗨,哥们,你最好把rps例程作成中断同步例程,否则isr要影响rps的!
|
|
17楼#
发布于:2002-10-31 17:10
嗨,哥们,你最好把rps例程作成中断同步例程,否则isr要影响rps的! :o 我就是怕isr影响rps,所以把rps写成独立于cpu的循环读,这样可以吗?另外,目前我只能在dpc中做文章,中断对象不是我创建的,我目前拿不到中断对象,难以初始化中断同步例程,要改成中断同步例程可能会涉及到很大的工作量(改程序的尴尬),用dpc不行吗? |
|
18楼#
发布于:2002-10-31 17:14
另外,中断同步例程是在什么时候执行的阿,和dpc有什么区别呢,我是说从分工上?
|
|
19楼#
发布于:2002-10-31 17:15
通过设备对象可以拿到中断对象吗?
|
|
上一页
下一页