S3C6410+WinCE6.0的系统,两个中断同一时刻来的时候,就出现丢数的现象。
详细情况是这样:做磁卡的驱动,有两个磁道:每个磁道有一个时钟线、一个数据线。
磁卡驱动原理很简单,当时钟线下降沿触发中断时,就去读数据线上的电平就行。
现在是:当只有一个磁道(禁止另一个时钟中断信号)时:读数正确;
当两个磁道同时打开时,两个磁道读数都错,出现丢数现象,偶尔有读对的时候,用示波器量,发
现有两个中断信号有统一时刻来的——很明显,这时候丢数了,只进入了一个ISR,另一个根本
没理。
请问,遇到这种情况S3C6410是怎么处理的?它干嘛要丢掉一个中断?另外,它俩在中断向量表VIC0里属于同一个中断源PHYIRQ_EINT1——我用的中断号是EINT10、EINT11.
12 个解决方案
#1
这个肯定是响应优先级高的了。
#2
这个只能增加 isr ist的效率来做。
楼主可以参考我 做外部串口驱动的办法,博客有。
还有这两个中断线程要互斥。
楼主可以参考我 做外部串口驱动的办法,博客有。
还有这两个中断线程要互斥。
#3
回楼上:
谢谢googoleman这么快就回复,谢谢!
但我觉得问题没这么简单:
1、EINT10、EINT11都属于中断向量表VIC1的同一个物理中断PHYIRQ_EINT1,设置优先级只能针对 PHYIRQ_EINT1,所以它俩的优先级肯定一致;
2、因为从ISQ--->ISR--->IST的过程需要花费时间,另外两个IST切换的时间更长(1ms不止)如果我两个ISR分别对应一个IST的话那就更惨了,又因为怕进入IST再去读数据线上的电平就不是1ms以前的了,所以现在读电平的处理我放在了ISR中,只有ISR将所有的数据都处理完了(响应了N个中断),我才通知IST来处理,是通过共享内存来实现的。
3、所以问题应该还不是楼上说的。
谢谢googoleman这么快就回复,谢谢!
但我觉得问题没这么简单:
1、EINT10、EINT11都属于中断向量表VIC1的同一个物理中断PHYIRQ_EINT1,设置优先级只能针对 PHYIRQ_EINT1,所以它俩的优先级肯定一致;
2、因为从ISQ--->ISR--->IST的过程需要花费时间,另外两个IST切换的时间更长(1ms不止)如果我两个ISR分别对应一个IST的话那就更惨了,又因为怕进入IST再去读数据线上的电平就不是1ms以前的了,所以现在读电平的处理我放在了ISR中,只有ISR将所有的数据都处理完了(响应了N个中断),我才通知IST来处理,是通过共享内存来实现的。
3、所以问题应该还不是楼上说的。
#4
我觉得读取电平确实应该放在ISR中,但是读取电平速度很快的,理论上不会影响ISR的效率。并且你不应该让ISR响应N个中断之后才通知ISR,而是响应一个ISR之后立刻通知IST处理。或者引入DMA来读取数据。
#5
这个要学习一下 呵呵
#6
这个和isr里面判断中断源有关.举个例子.
if(int10)
{}
else if(int11)
{}
这种代码,如果两个中断同时来了,INT11就丢了.
会不会有这种现象发生.要不同时来中断,应该都会有响应.
if(int10)
{}
if(int11)
{}
这样判断就不会丢.
if(int10)
{}
else if(int11)
{}
这种代码,如果两个中断同时来了,INT11就丢了.
会不会有这种现象发生.要不同时来中断,应该都会有响应.
if(int10)
{}
if(int11)
{}
这样判断就不会丢.
#7
//*****************added by haiou for magcard driver in 2010-04-20*****************************
if(VirtualIRQ == IRQ_EINT10) //Track3
{
//OALMSG(TRUE, (L"*********OEMInterruptHandler:IRQ_EINT8 haiou************\r\n"));
/*
g_pMAGBuf->primal_num_track3 = 0;
for(g_pMAGBuf->primal_num_track3; g_pMAGBuf->primal_num_track3<CARD_NUM_TRACK3; g_pMAGBuf->primal_num_track3++)
{
g_pMAGBuf->card_data_track3[g_pMAGBuf->primal_num_track3] = g_pMAGBuf->primal_num_track3;
}
g_pMAGBuf->primal_num_track3 = 0;
g_pGPIOReg->EINT0MASK &= ~(0x1<<8); // Enable EINT8
g_pVIC0Reg->VICINTENABLE |= (0x1<<PHYIRQ_EINT1); //(IRQ_EINT4~IRQ_EINT11)
*/
//OALMSG(TRUE, (L"*********OEMInterruptHandler:IRQ_EINT8 haiou************\r\n"));
if(0x02 == (UCHAR)(g_pMAGBuf->trans_flag & BRUSH_END)) //只有IST允许,中断处理才能有效
{
if((!(g_pGPIOReg->GPKDAT & CP_LOW)) && (g_pMAGBuf->primal_num_track3 < 1000))
{
g_pMAGBuf->card_data_track3[g_pMAGBuf->primal_num_track3++] = (char)(g_pGPIOReg->GPKDAT & TRACK3); //读出GPK2 bit
}
g_pMAGBuf->trans_flag |= BRUSH_BEGIN;
g_pGPIOReg->EINT0MASK &= ~(0x1<<10); // Enable EINT8
g_pVIC0Reg->VICINTENABLE |= (0x1<<PHYIRQ_EINT1); //(IRQ_EINT4~IRQ_EINT11)
}
return SYSINTR_NOP;
}
if(VirtualIRQ == IRQ_EINT18) //Track2
{
//OALMSG(TRUE, (L"*********OEMInterruptHandler:IRQ_EINT9 haiou************\r\n"));
if(0x02 == (UCHAR)(g_pMAGBuf->trans_flag & BRUSH_END)) //只有IST允许,中断处理才能有效
{
if((!(g_pGPIOReg->GPKDAT & CP_LOW)) && (g_pMAGBuf->primal_num_track2 < 300))
{
g_pMAGBuf->card_data_track2[g_pMAGBuf->primal_num_track2++] = (char)(g_pGPIOReg->GPKDAT & TRACK2); //读出GPK3 bit
}
g_pMAGBuf->trans_flag |= BRUSH_BEGIN;
g_pGPIOReg->EINT0MASK &= ~(0x1<<18); // Enable EINT9
g_pVIC1Reg->VICINTENABLE |= (0x1<<(PHYIRQ_EINT2-32)); //(IRQ_EINT4~IRQ_EINT11)
}
return SYSINTR_NOP;
}
//*******************end of magcard driver***************************************************/
#8
有道理,ISR响应N个中断后通知的方法不是 return sys_intr的方式,是设置了g_pMAGBuf->trans_flag |= BRUSH_BEGIN(所在的内存空间由ISR和IST共享);这个全局变量,IST端每隔100ms就去读这个变量,然后再等1.5ms处理_pMAGBuf->card_data_track3中的数。
引入DMA读取数据,还真不会,能否详细说明下方法?
引入DMA读取数据,还真不会,能否详细说明下方法?
#9
要使用DMA需要你的外部接口支持DMA,如果支持,那么你只需要将外部接口的中断方式设置为DMA处理即可。这样,到外部中断来的时候,DMA自动处理,不需要经过CPU
#10
回楼上,明白了,谢谢!~这个作为优化方案,我后面做下。
我现在比较怀疑的是这个:
S3C6410有两个中断向量表VIC0、VIC1。共对应64个interrupt sources。
其中有五个分别是INT_EINT0、INT_EINT1、INT_EINT2、INT_EINT3、INT_EINT4。
以INT_EINT0、INT_EINT1举例如下:
INT_EINT0又分别对应IRQ_EINT0,IRQ_EINT1,IRQ_EINT2,IRQ_EINT3四个外部中断;
INT_EINT1对应IRQ_EINT4~IRQ_EINT11;
现在有两种情况:
1、如果IRQ_EINT0和IRQ_EINT1同时都来了会丢一个吗?
2、如果IRQ_EINT0和IRQ_EINT4同时都来了会丢一个吗?
我记得S3C2410的中断和ARM7核的单片机中断处理机制有个SRCPND的寄存器,两个中断同时都来了,SRCPND中两个中断位都会同时置位,按照优先级一个先处理,另一个等先处理的处理完了总会处理。对吧?总之不会丢
S3C6410也是这样吗?它也有EINT0PND寄存器,还一样吗?不知道我上面的理解对不对?
我现在比较怀疑的是这个:
S3C6410有两个中断向量表VIC0、VIC1。共对应64个interrupt sources。
其中有五个分别是INT_EINT0、INT_EINT1、INT_EINT2、INT_EINT3、INT_EINT4。
以INT_EINT0、INT_EINT1举例如下:
INT_EINT0又分别对应IRQ_EINT0,IRQ_EINT1,IRQ_EINT2,IRQ_EINT3四个外部中断;
INT_EINT1对应IRQ_EINT4~IRQ_EINT11;
现在有两种情况:
1、如果IRQ_EINT0和IRQ_EINT1同时都来了会丢一个吗?
2、如果IRQ_EINT0和IRQ_EINT4同时都来了会丢一个吗?
我记得S3C2410的中断和ARM7核的单片机中断处理机制有个SRCPND的寄存器,两个中断同时都来了,SRCPND中两个中断位都会同时置位,按照优先级一个先处理,另一个等先处理的处理完了总会处理。对吧?总之不会丢
S3C6410也是这样吗?它也有EINT0PND寄存器,还一样吗?不知道我上面的理解对不对?
#11
今天该结贴了,看来我这个理解是有问题的,我引用所存在的问题是对一级中断和二级中断的理解有误。
后来我做了这样一个实验:
1、一个开关同时对应两个中断,模拟两个终端同时产生;
2、得到的结果是:只能产生一个syetem_intr;
3、其实这个不难理解:仔细看OEMInterruptHandle这个函数就能明白;
4、因为磁卡肯定有两个终端同时来的情况,后来换成了别的思路解决了这个问题,才磁卡CS信号作为中断,然后扫描读取二、三磁道的值,读值过程中CPU是独占的,但因为这个时间不到1S,目前应用是能接受的。
最终得出的结论是:WinCE当有两个外部中断同时产生时,只返回一个逻辑中断号,也就是我会丢掉一个!
#12
我的理解是,两个中断同时来的时候,没有丢一个中断,而是先处理了一个中断,而再处理另外一个中断。
“我记得S3C2410的中断和ARM7核的单片机中断处理机制有个SRCPND的寄存器,两个中断同时都来了,SRCPND中两个中断位都会同时置位,按照优先级一个先处理,另一个等先处理的处理完了总会处理。对吧?总之不会丢”
你的这个理解是对的啊,正因为如此才不会把另外一个中断给丢了,
如果你的读卡数据的时间比较长的话,且多于两倍的ISR处理的时间的话,应该是可以一前一后读到两个卡的数据,不会丢失的。
#1
这个肯定是响应优先级高的了。
#2
这个只能增加 isr ist的效率来做。
楼主可以参考我 做外部串口驱动的办法,博客有。
还有这两个中断线程要互斥。
楼主可以参考我 做外部串口驱动的办法,博客有。
还有这两个中断线程要互斥。
#3
回楼上:
谢谢googoleman这么快就回复,谢谢!
但我觉得问题没这么简单:
1、EINT10、EINT11都属于中断向量表VIC1的同一个物理中断PHYIRQ_EINT1,设置优先级只能针对 PHYIRQ_EINT1,所以它俩的优先级肯定一致;
2、因为从ISQ--->ISR--->IST的过程需要花费时间,另外两个IST切换的时间更长(1ms不止)如果我两个ISR分别对应一个IST的话那就更惨了,又因为怕进入IST再去读数据线上的电平就不是1ms以前的了,所以现在读电平的处理我放在了ISR中,只有ISR将所有的数据都处理完了(响应了N个中断),我才通知IST来处理,是通过共享内存来实现的。
3、所以问题应该还不是楼上说的。
谢谢googoleman这么快就回复,谢谢!
但我觉得问题没这么简单:
1、EINT10、EINT11都属于中断向量表VIC1的同一个物理中断PHYIRQ_EINT1,设置优先级只能针对 PHYIRQ_EINT1,所以它俩的优先级肯定一致;
2、因为从ISQ--->ISR--->IST的过程需要花费时间,另外两个IST切换的时间更长(1ms不止)如果我两个ISR分别对应一个IST的话那就更惨了,又因为怕进入IST再去读数据线上的电平就不是1ms以前的了,所以现在读电平的处理我放在了ISR中,只有ISR将所有的数据都处理完了(响应了N个中断),我才通知IST来处理,是通过共享内存来实现的。
3、所以问题应该还不是楼上说的。
#4
我觉得读取电平确实应该放在ISR中,但是读取电平速度很快的,理论上不会影响ISR的效率。并且你不应该让ISR响应N个中断之后才通知ISR,而是响应一个ISR之后立刻通知IST处理。或者引入DMA来读取数据。
#5
这个要学习一下 呵呵
#6
这个和isr里面判断中断源有关.举个例子.
if(int10)
{}
else if(int11)
{}
这种代码,如果两个中断同时来了,INT11就丢了.
会不会有这种现象发生.要不同时来中断,应该都会有响应.
if(int10)
{}
if(int11)
{}
这样判断就不会丢.
if(int10)
{}
else if(int11)
{}
这种代码,如果两个中断同时来了,INT11就丢了.
会不会有这种现象发生.要不同时来中断,应该都会有响应.
if(int10)
{}
if(int11)
{}
这样判断就不会丢.
#7
//*****************added by haiou for magcard driver in 2010-04-20*****************************
if(VirtualIRQ == IRQ_EINT10) //Track3
{
//OALMSG(TRUE, (L"*********OEMInterruptHandler:IRQ_EINT8 haiou************\r\n"));
/*
g_pMAGBuf->primal_num_track3 = 0;
for(g_pMAGBuf->primal_num_track3; g_pMAGBuf->primal_num_track3<CARD_NUM_TRACK3; g_pMAGBuf->primal_num_track3++)
{
g_pMAGBuf->card_data_track3[g_pMAGBuf->primal_num_track3] = g_pMAGBuf->primal_num_track3;
}
g_pMAGBuf->primal_num_track3 = 0;
g_pGPIOReg->EINT0MASK &= ~(0x1<<8); // Enable EINT8
g_pVIC0Reg->VICINTENABLE |= (0x1<<PHYIRQ_EINT1); //(IRQ_EINT4~IRQ_EINT11)
*/
//OALMSG(TRUE, (L"*********OEMInterruptHandler:IRQ_EINT8 haiou************\r\n"));
if(0x02 == (UCHAR)(g_pMAGBuf->trans_flag & BRUSH_END)) //只有IST允许,中断处理才能有效
{
if((!(g_pGPIOReg->GPKDAT & CP_LOW)) && (g_pMAGBuf->primal_num_track3 < 1000))
{
g_pMAGBuf->card_data_track3[g_pMAGBuf->primal_num_track3++] = (char)(g_pGPIOReg->GPKDAT & TRACK3); //读出GPK2 bit
}
g_pMAGBuf->trans_flag |= BRUSH_BEGIN;
g_pGPIOReg->EINT0MASK &= ~(0x1<<10); // Enable EINT8
g_pVIC0Reg->VICINTENABLE |= (0x1<<PHYIRQ_EINT1); //(IRQ_EINT4~IRQ_EINT11)
}
return SYSINTR_NOP;
}
if(VirtualIRQ == IRQ_EINT18) //Track2
{
//OALMSG(TRUE, (L"*********OEMInterruptHandler:IRQ_EINT9 haiou************\r\n"));
if(0x02 == (UCHAR)(g_pMAGBuf->trans_flag & BRUSH_END)) //只有IST允许,中断处理才能有效
{
if((!(g_pGPIOReg->GPKDAT & CP_LOW)) && (g_pMAGBuf->primal_num_track2 < 300))
{
g_pMAGBuf->card_data_track2[g_pMAGBuf->primal_num_track2++] = (char)(g_pGPIOReg->GPKDAT & TRACK2); //读出GPK3 bit
}
g_pMAGBuf->trans_flag |= BRUSH_BEGIN;
g_pGPIOReg->EINT0MASK &= ~(0x1<<18); // Enable EINT9
g_pVIC1Reg->VICINTENABLE |= (0x1<<(PHYIRQ_EINT2-32)); //(IRQ_EINT4~IRQ_EINT11)
}
return SYSINTR_NOP;
}
//*******************end of magcard driver***************************************************/
#8
有道理,ISR响应N个中断后通知的方法不是 return sys_intr的方式,是设置了g_pMAGBuf->trans_flag |= BRUSH_BEGIN(所在的内存空间由ISR和IST共享);这个全局变量,IST端每隔100ms就去读这个变量,然后再等1.5ms处理_pMAGBuf->card_data_track3中的数。
引入DMA读取数据,还真不会,能否详细说明下方法?
引入DMA读取数据,还真不会,能否详细说明下方法?
#9
要使用DMA需要你的外部接口支持DMA,如果支持,那么你只需要将外部接口的中断方式设置为DMA处理即可。这样,到外部中断来的时候,DMA自动处理,不需要经过CPU
#10
回楼上,明白了,谢谢!~这个作为优化方案,我后面做下。
我现在比较怀疑的是这个:
S3C6410有两个中断向量表VIC0、VIC1。共对应64个interrupt sources。
其中有五个分别是INT_EINT0、INT_EINT1、INT_EINT2、INT_EINT3、INT_EINT4。
以INT_EINT0、INT_EINT1举例如下:
INT_EINT0又分别对应IRQ_EINT0,IRQ_EINT1,IRQ_EINT2,IRQ_EINT3四个外部中断;
INT_EINT1对应IRQ_EINT4~IRQ_EINT11;
现在有两种情况:
1、如果IRQ_EINT0和IRQ_EINT1同时都来了会丢一个吗?
2、如果IRQ_EINT0和IRQ_EINT4同时都来了会丢一个吗?
我记得S3C2410的中断和ARM7核的单片机中断处理机制有个SRCPND的寄存器,两个中断同时都来了,SRCPND中两个中断位都会同时置位,按照优先级一个先处理,另一个等先处理的处理完了总会处理。对吧?总之不会丢
S3C6410也是这样吗?它也有EINT0PND寄存器,还一样吗?不知道我上面的理解对不对?
我现在比较怀疑的是这个:
S3C6410有两个中断向量表VIC0、VIC1。共对应64个interrupt sources。
其中有五个分别是INT_EINT0、INT_EINT1、INT_EINT2、INT_EINT3、INT_EINT4。
以INT_EINT0、INT_EINT1举例如下:
INT_EINT0又分别对应IRQ_EINT0,IRQ_EINT1,IRQ_EINT2,IRQ_EINT3四个外部中断;
INT_EINT1对应IRQ_EINT4~IRQ_EINT11;
现在有两种情况:
1、如果IRQ_EINT0和IRQ_EINT1同时都来了会丢一个吗?
2、如果IRQ_EINT0和IRQ_EINT4同时都来了会丢一个吗?
我记得S3C2410的中断和ARM7核的单片机中断处理机制有个SRCPND的寄存器,两个中断同时都来了,SRCPND中两个中断位都会同时置位,按照优先级一个先处理,另一个等先处理的处理完了总会处理。对吧?总之不会丢
S3C6410也是这样吗?它也有EINT0PND寄存器,还一样吗?不知道我上面的理解对不对?
#11
今天该结贴了,看来我这个理解是有问题的,我引用所存在的问题是对一级中断和二级中断的理解有误。
后来我做了这样一个实验:
1、一个开关同时对应两个中断,模拟两个终端同时产生;
2、得到的结果是:只能产生一个syetem_intr;
3、其实这个不难理解:仔细看OEMInterruptHandle这个函数就能明白;
4、因为磁卡肯定有两个终端同时来的情况,后来换成了别的思路解决了这个问题,才磁卡CS信号作为中断,然后扫描读取二、三磁道的值,读值过程中CPU是独占的,但因为这个时间不到1S,目前应用是能接受的。
最终得出的结论是:WinCE当有两个外部中断同时产生时,只返回一个逻辑中断号,也就是我会丢掉一个!
#12
我的理解是,两个中断同时来的时候,没有丢一个中断,而是先处理了一个中断,而再处理另外一个中断。
“我记得S3C2410的中断和ARM7核的单片机中断处理机制有个SRCPND的寄存器,两个中断同时都来了,SRCPND中两个中断位都会同时置位,按照优先级一个先处理,另一个等先处理的处理完了总会处理。对吧?总之不会丢”
你的这个理解是对的啊,正因为如此才不会把另外一个中断给丢了,
如果你的读卡数据的时间比较长的话,且多于两倍的ISR处理的时间的话,应该是可以一前一后读到两个卡的数据,不会丢失的。