【200分】中断驱动+应用层同步响应的问题咨询

xumercury 2010-01-14 03:26:50
问题描述:

1.一个流式驱动,工作流程是硬件触发一个中断,系统采集到数据信息后通过xxx_READ将采集到的数据发给应用层;

2.驱动通过一个线程函数来获取GPIO的中断信号,并读取值从打印信息打印出。
(这里的处理正常,有多少中断都接受到,并且值采集正确)

3.读取到中断后,系统通过一个采集函数将数据信息采集,并将数据存放在一个全局变量中,并设定一个事件a;

4.XXX_READ函数中等待事件信号a,等待到了就将数据送到xxx_read函数的status接口上;

5.应用层创建一个线程,在线程中实现一个readfile功能去读取xxx_Read传送出来的值;

问题点:
1.现在驱动层打印信息看,在驱动层每次都获取到了,但是应用层上,我在实际操作的时候发现产生数据是如果速度过快每次只能获取到一个数值,如果产生数据慢的时候就能很准的获取并在响应应用层的功能;

请教下各位大牛这个问题如何解决?也就是中断响应的问题,如何实现驱动层响应中断和应用层响应中断同步??

分不够再加。

慢速正确的信息

the 0 number SentOut Value for point variable is bb//来自驱动层
the 0 number SentOut Value for point variable is bb来自驱动层
READ EFFECT VALUE!
Volume value : 36
SEND ADDR ACK RECEIVER OK!!!
SEND DATA ACK RECEIVER OK!!!
Volume set Ok!!!


快速数据时产生的错误信息

the 0 number SentOut Value for point variable is aa
the 0 number SentOut Value for point variable is aa
the 0 number SentOut Value for point variable is aa
the 0 number SentOut Value for point variable is aa
the 0 number SentOut Value for point variable is aa
the 0 number SentOut Value for point variable is aa
the 0 number SentOut Value for point variable is aa
//产生了很多数据但是只响应了最后一个。
READ EFFECT VALUE!
Volume value : 3c
SEND ADDR ACK RECEIVER OK!!!
SEND DATA ACK RECEIVER OK!!!
Volume set Ok!!!
...全文
296 23 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
23 条回复
切换为时间正序
请发表友善的回复…
发表回复
wjcapple 2012-03-03
  • 打赏
  • 举报
回复
我有个问题,你在底层如何通知上层应用调用readfile在进行读数据呢?换而言之,底层的驱动如何与上层应用进行同步呢?我以前写驱动是上层不断的调用readfile去查询缓冲区,但如果我在底层定义一个event或者信号量,消息队列,上层应用程序又怎么可能等待这个信号量呢?上层应用程序可以等待的信号量必须在上层应用程序里定义,如果有机制可以将底层定义的信号量传给上层就好了
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 sunrain_hjb 的回复:]
在驱动里缓存一些数据,然后通知应用程序集中处理,其他似乎没有太好的办法。

实在不行,可以考虑使用FIQ,快速中断。以前做数据采集设备时,曾尝试过这种方法。
[/Quote]
哈哈哈HJB大牛,谢谢啦。已经搞定。最近怎么没看到你的博客发帖子啊。期待新作。

FLandY1982非常感谢。方法很好!
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 ricky_hu 的回复:]
如果lz的数据处理速度慢,而中断上来快的话,这个问题基本没得解。肯定会丢掉东西,要么丢掉数据,要么丢掉中断,相信这2种情况都不是lz想要的。所以lz还是要想办法尽量提高数据处理速度。

另外,lz可以考虑使用循环缓冲buffer的方式来做。数据一来就把它存到缓冲区,然后马上取走去处理,这样的话即使你处理稍微慢一点,缓冲区里面的是数据总是不会丢掉的。就想往水杯里面倒水,但是这个杯子底部又有一个洞漏水一样。
[/Quote]
谢谢建议。非常感谢!
xumercury 2010-01-14
  • 打赏
  • 举报
回复
结贴。搞定。用了上面两个高手提供的方法实现。谢谢了
sunrain_hjb 2010-01-14
  • 打赏
  • 举报
回复
在驱动里缓存一些数据,然后通知应用程序集中处理,其他似乎没有太好的办法。

实在不行,可以考虑使用FIQ,快速中断。以前做数据采集设备时,曾尝试过这种方法。
Ricky_hu 2010-01-14
  • 打赏
  • 举报
回复
如果lz的数据处理速度慢,而中断上来快的话,这个问题基本没得解。肯定会丢掉东西,要么丢掉数据,要么丢掉中断,相信这2种情况都不是lz想要的。所以lz还是要想办法尽量提高数据处理速度。

另外,lz可以考虑使用循环缓冲buffer的方式来做。数据一来就把它存到缓冲区,然后马上取走去处理,这样的话即使你处理稍微慢一点,缓冲区里面的是数据总是不会丢掉的。就想往水杯里面倒水,但是这个杯子底部又有一个洞漏水一样。
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 flandy1982 的回复:]
建议楼主改用CreateSemaphore吧, IST每次都ReleaseSemaphore, 这样只要保证中断不是一直不间断的产生, 数据就不会丢失, 实时性也只与ReadFile线程处理的速度相关。。
[/Quote]
呃。现在有个情况。。。丢是没有丢了。。但是一次出了2个中断,但是速度块起来也只是响应到2个中断,其他中断都丢弃了。。晕。如果用CreateSemaphore的话

我在init初始化gReadKeyEvent[0] = CreateSemaphore(NULL, 0, cMax, NULL);
然后在xxx_DetectThread里面

if (!ReleaseSemaphore(
gReadKeyEvent[0], // 要增加的信号量。
1, // 增加1.
NULL) ) // 不想返回前一次信号量。
{}

。。。难道哪里又弄错了?
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 flandy1982 的回复:]
建议楼主改用CreateSemaphore吧, IST每次都ReleaseSemaphore, 这样只要保证中断不是一直不间断的产生, 数据就不会丢失, 实时性也只与ReadFile线程处理的速度相关。。
[/Quote]
好的。谢谢我试试
LJDTJ 2010-01-14
  • 打赏
  • 举报
回复
学习。
“两次中断间隔的时间快起来会非常短。可能是1ms单位甚至500us。”
LZ的这个中断速度也真够快的啊。
FLandY1982 2010-01-14
  • 打赏
  • 举报
回复
建议楼主改用CreateSemaphore吧, IST每次都ReleaseSemaphore, 这样只要保证中断不是一直不间断的产生, 数据就不会丢失, 实时性也只与ReadFile线程处理的速度相关。。
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 flandy1982 的回复:]
中断产生了N个信号,但你的ReadFile可能读不到那么多,就被ResetEvent了。
[/Quote]
可能是。。。。一次只有一个值
[Quote=引用 10 楼 rushonin 的回复:]
把interruptdone() 移到XXX_read中复制数据的后面吧.
[/Quote]
好的我试试
FLandY1982 2010-01-14
  • 打赏
  • 举报
回复
中断产生了N个信号,但你的ReadFile可能读不到那么多,就被ResetEvent了。
FLandY1982 2010-01-14
  • 打赏
  • 举报
回复
ReadFile的次数和你产生的中断没有直接的关系.
你需要在XXX_READ里面开个足够大的BUFFER把数据存下来,并且对接收的数据进行计数处理。
rushonin 2010-01-14
  • 打赏
  • 举报
回复
把interruptdone() 移到XXX_read中复制数据的后面吧.
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 veabol 的回复:]
两次中断之间时间间隔短吗?如果比较长的话可以在驱动中中断来了之后采集完全部数据后向上层发个消息或者事件,应用层接收到这个事件之后再去读驱动中的数据。
如果过快的话可能底层都已经开始更新下次的数据了,应用层还没读完呢。
[/Quote]
牛人。两次中断间隔的时间快起来会非常短。可能是1ms单位甚至500us。现在的情况应该是数据还没处理完下好几次的数据就已经过去了。
但是又要保持实时性。。。诶。这个比较头痛。数据慢的时候还可以接受。快了可能丢掉10个左右的数据
博说医械研发 2010-01-14
  • 打赏
  • 举报
回复
两次中断之间时间间隔短吗?如果比较长的话可以在驱动中中断来了之后采集完全部数据后向上层发个消息或者事件,应用层接收到这个事件之后再去读驱动中的数据。
如果过快的话可能底层都已经开始更新下次的数据了,应用层还没读完呢。
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 flandy1982 的回复:]
驱动层的BUFFER开得足够大吗?会不会出现应用层还未处理完,新的中断又产生的情况?
IST的优先级和采集线程的优先级怎么设置的?
[/Quote]
感觉是这种情况。

出现应用层还未处理完,新的中断又产生的情况
xumercury 2010-01-14
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 flandy1982 的回复:]
驱动层的BUFFER开得足够大吗?会不会出现应用层还未处理完,新的中断又产生的情况?
IST的优先级和采集线程的优先级怎么设置的?
[/Quote]
大小应该是够的。因为至少采集是都采集到了。但是到XXX_READ和readfile地方出了问题。是不是我read的地方写的有问题。
一般用XXX_READ和readfile来处理中断应当如何去处理下?
也就是每一次硬件中断来了,我就得马上XXX_read然后应用层就马上readfile,处理数据。

话说过来也就是硬件中断和XXX_READ和readfile如何同步响应处理。
xumercury 2010-01-14
  • 打赏
  • 举报
回复
驱动层部分代码

/////////////////////////////////////////////////////////////////////
//=============================================================================
//Title : xxx_IntrThread
//Detail: Receive INTR EVENT from gpio for xxx communication
//Input : PVOID pArg
//Output: DWORD
//Author: Mercury
//Data : 2009-12-26
//=============================================================================
DWORD xxx_DetectThread(PVOID pArg)
{
//变量定义
//Sleep(1);
while (1)
{
dwRet = WaitForMultipleObjects(2, rghEvents, FALSE, INFINITE);
if(pMcuCtl->bDeinit) {

return 0;
}
switch(dwRet) {
case WAIT_OBJECT_0:
RETAILMSG(1, (TEXT("mcu_DetectThread Wait deinit\r\n")));
//deinit event
return 0;
break;

case WAIT_OBJECT_0+1:
OperationCS8953(READ, &sendOut[0], 2);
#if 1
RETAILMSG(1,(TEXT("the %d number SentOut Value for point variable is %x\r\n"),i,sendOut[i]));
#endif
SetEvent(gReadKeyEvent[0]); /* 通知读函数, 外部中断产生 */
}
break;
default:
//error
dwAction = 0x00;//MCU_STAT_NOCHANGE;
break;
}
//do real action
}
return 0;
}
extern "C" DWORD XXX_Init(DWORD Index)
{


RETAILMSG(1,(TEXT("++XXX_Init!\r\n ")));
//事件创建部分。。省略部分代码
pXXXCtl->hDetectThread = CreateThread(0, 0, (LPTHREAD_START_ROUTINE) XXX_DetectThread, (LPVOID)pXXXCtl, 0, &IDThread);
if (pXXXCtl->hDetectThread == 0)
{
RETAILMSG(1,(TEXT("XXX_Init::: CreateThread Failed\r\n")));
goto Error;
}

//初始化中断 。。省略部分代码
return(DWORD)pXXXCtl;

Error:
(VOID)XXX_Deinit((DWORD)pXXXCtl);
RETAILMSG(1,(TEXT("--error !XXX_Init!\r\n ")));
#endif
return(0);
}

extern "C" DWORD xxx_Read(DWORD dwData,
LPVOID pBuf,
DWORD Len)
{
DWORD ret;
unsigned char *pReadBuffer = NULL;

if ((pBuf == NULL) || (Len <= 0))
return 0;

pReadBuffer = (unsigned char *)MapPtrToProcess(pBuf, GetCallerProcess());
*pReadBuffer = NULL;

ret = WaitForMultipleObjects(2, gReadKeyEvent, FALSE, INFINITE);
if (ret == WAIT_OBJECT_0)
{
ResetEvent(gReadKeyEvent[0]);
*pReadBuffer = sendOut[0];
RETAILMSG(1,(TEXT("READ EFFECT VALUE!\r\n")));/* 获取有效值 */
//return 1;
}
else if(ret == (WAIT_OBJECT_0 + 1))
{
ResetEvent(gReadKeyEvent[1]);
RETAILMSG(1,(TEXT("OUT\r\n")));/* 驱动关闭 */
//return 1;
}

return(0);
}

FLandY1982 2010-01-14
  • 打赏
  • 举报
回复
驱动层的BUFFER开得足够大吗?会不会出现应用层还未处理完,新的中断又产生的情况?
IST的优先级和采集线程的优先级怎么设置的?
加载更多回复(3)

19,519

社区成员

发帖
与我相关
我的任务
社区描述
硬件/嵌入开发 嵌入开发(WinCE)
社区管理员
  • 嵌入开发(WinCE)社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧