6410BSP 中断的大bug

qwqwqw408 2015-06-16 07:37:45
加精
最近发现新加的电容屏,有一定的概率会出现永远无法触摸的情况。经过调试,发现中断被屏蔽,但是确认驱动已经调用了InterruptDone,并且在调用之后打印,发现触摸屏中断屏蔽位是0(未屏蔽),说明是被其他地方设置成屏蔽的。后面经过一系列的调试和分析,终于找到了可能的原因,是设置屏蔽中断的地方没有同步引起的。我们触摸屏用是EINT15,DM9000用的是EINT10,对应的中断屏蔽寄存器是EINT0MASK ,一个是第15位,一个是第10位。屏蔽中断的代码为 g_pGPIOReg->EINT0MASK |= (1<<(VirtualIRQ-30)); 问题就出现在这里,因为这一句有几个地方会执行,首先是OALIntrDoneIrqs(驱动代码里面调用的InterruptDone会调用它),还有OEMInterruptHandler里面也会调用。这几个地方完全没有做同步处理,所以会导致并发执行。比如两个驱动的InterruptDone会同时执行,InterruptDone和OEMInterruptHandler也会同时执行。下面列举一个可能的执行序列:
1,DM9000->InterruptDone->OALIntrDoneIrqs -> 读取EINT0MASK
2,TOUCH->InterruptDone->OALIntrDoneIrqs ->保存(EINT0MASK &= ~(1<<(15))
3,DM9000->InterruptDone->OALIntrDoneIrqs ->保存 (EINT0MASK &= ~(1<<(10))

这里就可以看出问题来了。第一步DM9000读取的EINT0MASK里面,第15位是为1,TOUCH中断被屏蔽。第二步时触摸屏驱动处理完毕,打开TOUCH中断,此时EINT0MASK第15位为0。第三步时,此时因为是在旧的数据(EINT0MASK第15位为1)上做的运算,所以最后的结果是打开了DM9000中断,但是屏蔽了TOUCH中断。

简单的说,就是类似于多线程里面并发的 i = i +1;的问题。

另外,网上有些人疑惑VICxINTENABLE寄存器为什么要通过VICxINTENCLEAR这个寄存器设置值,比如想把VICxINTENABLE某一位置位,并不是直接向VICxINTENABLE的对应位写1,而是通过向VICxINTENCLEAR对应位写1,其他位为0(0为不影响)来实现,估计就是考虑到同步问题。通过这种方式操作就一定不会有以上的问题了,因为修改VICxINTENCLEAR的指令一定是顺序执行的,并且只需要对应的位是1,其他位为0,不会造成覆盖别的位。


以下是BSP 中断处理的部分代码
OALIntrDoneIrqs函数的处理
else if (PhysicalIRQ == PHYIRQ_EINT2 || // IRQ_EINT12 ~ IRQ_EINT19
PhysicalIRQ == PHYIRQ_EINT3 ) // IRQ_EINT20 ~ IRQ_EINT27
{
g_pGPIOReg->EINT0MASK &= ~(1<<(VirtualIRQ-30)); // Enable Sub Interrupt
}

OEMInterruptHandler函数的处理
// Check Sub Source
uiPending = g_pGPIOReg->EINT0PEND;
uiMask = g_pGPIOReg->EINT0MASK;

for (nNumber=12; nNumber<20; nNumber++) // EINT12~EINT19
{
if ((uiPending & (1<<nNumber)) && !(uiMask & (1<<nNumber)))
{
g_pGPIOReg->EINT0MASK |= (1<<nNumber); // Mask Sub Interrupt
g_pGPIOReg->EINT0PEND = (1<<nNumber); // Clear Sub Pending
VirtualIRQ = (IRQ_EINT12+(nNumber-12)); // Set Virtual IRQ
break;
}
}
...全文
3406 41 打赏 收藏 转发到动态 举报
写回复
用AI写文章
41 条回复
切换为时间正序
请发表友善的回复…
发表回复
caraso 2016-10-11
  • 打赏
  • 举报
回复
所以还是最好使用有后续维护支持的BSP包。
paul_chao 2015-07-28
  • 打赏
  • 举报
回复
DM9000, Samsung 原廠的 Reference Board 應不是用這一顆 Ethernet Chip 吧. 說不定又是哪一家做板子的廠商自己改的. WinCE 是一個很好又很穩定的作業系統, 但是若大家自己亂改, 那有些奇怪的BUG就不足為奇了. 建議還是拿原廠的BSP來改最保險, 起碼是做過CETK認證的. Paul, Chao @ Techware
qwqwqw408 2015-07-01
  • 打赏
  • 举报
回复
引用 37 楼 LouisScola 的回复:
引用 36 楼 qwqwqw408 的回复:
你说的中断机制是指什么,处理的流程吗。两者是差不多的,没有本质上的区别,都是由一个中断服务程序+中断服务线程(linux叫工作线程)。中断服务程序会屏蔽当前处理的中断,做比较少的必要工作后,会启动相应驱动的工作线程处理,工作线程处理完毕,再打开对应的中断。也就是说同一个中断的中断服务程序和工作线程是不会并发执行的。wince也是这个机制,没有区别。
是的,我就是这个意思,你的InterruptDone是isr,OALIntrDoneIrqs 是工作线程是吧,你在工作线程里再打开对应中断明显是太慢了。最好的做法应该是在isr中把中断对应的事件和数据放到队列中,然后最后打开中断;工作队列只处理具体的事件和数据,不处理中断打开关闭,这样才是isr的上半部和下半部的概念
WINCE就是这种机制的,不可能像你说的那样改了。。再说了,触摸屏中断时,数据还需要通过IIC去读,读IIC是有可能会睡眠的,中断里面肯定不能读。linux里面也不是这么做的吧。
qwqwqw408 2015-06-29
  • 打赏
  • 举报
回复
引用 35 楼 LouisScola 的回复:
这种读写最好还是改写bsp代码最好,不清楚wince的中断机制,不过中断机制也就那几种,参考linux下
你说的中断机制是指什么,处理的流程吗。两者是差不多的,没有本质上的区别,都是由一个中断服务程序+中断服务线程(linux叫工作线程)。中断服务程序会屏蔽当前处理的中断,做比较少的必要工作后,会启动相应驱动的工作线程处理,工作线程处理完毕,再打开对应的中断。也就是说同一个中断的中断服务程序和工作线程是不会并发执行的。wince也是这个机制,没有区别。
LouisScola 2015-06-29
  • 打赏
  • 举报
回复
这种读写最好还是改写bsp代码最好,不清楚wince的中断机制,不过中断机制也就那几种,参考linux下
LouisScola 2015-06-29
  • 打赏
  • 举报
回复
引用 36 楼 qwqwqw408 的回复:
你说的中断机制是指什么,处理的流程吗。两者是差不多的,没有本质上的区别,都是由一个中断服务程序+中断服务线程(linux叫工作线程)。中断服务程序会屏蔽当前处理的中断,做比较少的必要工作后,会启动相应驱动的工作线程处理,工作线程处理完毕,再打开对应的中断。也就是说同一个中断的中断服务程序和工作线程是不会并发执行的。wince也是这个机制,没有区别。
是的,我就是这个意思,你的InterruptDone是isr,OALIntrDoneIrqs 是工作线程是吧,你在工作线程里再打开对应中断明显是太慢了。最好的做法应该是在isr中把中断对应的事件和数据放到队列中,然后最后打开中断;工作队列只处理具体的事件和数据,不处理中断打开关闭,这样才是isr的上半部和下半部的概念
qq_22946017 2015-06-27
  • 打赏
  • 举报
回复
学习吧!!!
  • 打赏
  • 举报
回复
引用 31 楼 xqhrs232 的回复:
[quote=引用 29 楼 code_style 的回复:] 一般的小白用户很难遇到这个bug,更别提别的了。 确实是硬伤,三星6410停产了,现在支持wince/mobile的SOC已经寥寥无几了,别提MTK,高通,这不是消费电子 赶紧转其他平台吧
三星6410停产了???真的假的?[/quote] 他们网站上的产品没有6410了,但是没停产。还是可以买得到。
qwqwqw408 2015-06-24
  • 打赏
  • 举报
回复
引用 29 楼 code_style 的回复:
一般的小白用户很难遇到这个bug,更别提别的了。 确实是硬伤,三星6410停产了,现在支持wince/mobile的SOC已经寥寥无几了,别提MTK,高通,这不是消费电子 赶紧转其他平台吧
这个问题具有一定的通用性,我没有去看linux的BSP,但是我知道linux驱动中断处理也是分两部分的,中断处理部分,和后续的工作线程。这里的问题就是禁用当前中断只能保证当前中断不会和当前中断的工作线程并发执行,但是不能保证当前中断处理部分不和其他的驱动工作线程并发执行。不知道linux那里对中断的屏蔽和启用是如何处理的。最好的解决办法就是增加另外一个控制屏蔽寄存器的寄存器,而不要直接操作屏蔽寄存器,这样对内核的改动最小。
xqhrs232 2015-06-24
  • 打赏
  • 举报
回复
引用 29 楼 code_style 的回复:
一般的小白用户很难遇到这个bug,更别提别的了。 确实是硬伤,三星6410停产了,现在支持wince/mobile的SOC已经寥寥无几了,别提MTK,高通,这不是消费电子 赶紧转其他平台吧
三星6410停产了???真的假的?
  • 打赏
  • 举报
回复
一般的小白用户很难遇到这个bug,更别提别的了。 确实是硬伤,三星6410停产了,现在支持wince/mobile的SOC已经寥寥无几了,别提MTK,高通,这不是消费电子 赶紧转其他平台吧
程序员鼓励师 2015-06-22
  • 打赏
  • 举报
回复
qq_29211333 2015-06-22
  • 打赏
  • 举报
回复
还好吧 没遇到过这个问题 一般比较难遇到
qq_29223357 2015-06-22
  • 打赏
  • 举报
回复
恩恩,很有用啊,不错,给个赞
qq_29221631 2015-06-22
  • 打赏
  • 举报
回复
很好,很好!学习学习
qq_29218737 2015-06-22
  • 打赏
  • 举报
回复
学习!!!!!!
qq_29195415 2015-06-21
  • 打赏
  • 举报
回复
值得关注啊,很不错
cattpon 2015-06-21
  • 打赏
  • 举报
回复
表示关注一下~
laoer_2002 2015-06-20
  • 打赏
  • 举报
回复
好厉害,学习了!
nettman 2015-06-20
  • 打赏
  • 举报
回复
关注下
加载更多回复(16)

19,502

社区成员

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

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