大家好、我将 Micrium uCOS III 与 TMS570LC4357搭配使用、并尝试调试幻象中断问题。 我已经阅读 了 spna063.pdf 、但仍然不太了解防止幻象中断的核心/VIM 相关性。 是否有一个文档更清楚地描述了如何根据发生的中断和屏蔽活动来更新/清除索引寄存器(IRQINDEX、VIM 中的偏移0)? 以及在此过程中如何触发内核? 时序图很好。 如果逻辑图显示了 spna063的情形2中描述的竞态条件、即使是逻辑图也会有所帮助。
在我的当前配置中、有2个中断被启用、RTI (索引= 4、IRQ 通道= 3)和 DCAN3 (索引= 46、IRQ 通道= 45)。 未使用 FIQ。 所有中断均通过 IRQ 矢量进行功能处理、操作系统在处理特定请求时通过屏蔽所有较低优先级的中断来"管理"中断。 我看到两种情况-
发生 RTI、当中断被重新启用时、一个嵌套 CAN 中断发生、当被处理时、在索引寄存器中增加一个"0"。 请注意、我知道处理哪个 IRQ 的方法是在服务的早期添加了一些汇编代码、以便根据是 RTI 还是 CAN 来读取索引和切换 GPIO 位。 我还在 Micrium "嵌套 IRQ 检测"部分切换 GPIO 位。 似乎每次检测到嵌套中断时都会生成幻象中断。 虽然很少见、但我不明白如何防止、或者它实际上是否是问题-我没有查看帧是丢弃还是以后处理帧。
2、 产生一个 CAN 中断、另一个 CAN 中断嵌套会引起幻象中断。 这一点我真的不理解、因为我在 CAN 服务期间不会重新启用中断。 我的理解是、当 IRQ 被处理时、CPSR 位7被置位、从而在服务的持续时间内禁用中断。 因此、在这种情况下、除非通过清除 CPSR 位7 (我不是这样)显式重新启用中断、否则我看不到 CAN 中断可能嵌套的方式。 但我肯定会看到它。
在标准 Micrium 配置中、IRQ 索引寄存器在 ISR 中的读取时间不是很早、这一点似乎不太正确。 似乎需要提前进行一些内部整理。 这只是我注意到的问题、可能是问题、也可能不是问题。 不过,我认为尽快把指数捕捞出来,可能会减低种族状况。 但是、再次提前读取索引可能会将同一问题移至更早的时间。
如果您有任何想法或信息、我们将不胜感激。 我将包括优先级/屏蔽例程-我添加了行" if (ch_ix =0U)... " 来中止幻象中断的服务。 如果没有这一行代码、代码将锁定-在调用特定 ISR 之前重新启用中断时、幻象中断将保持。
void bsp_IntHandlerSrc (CPU_INT16U src_id)
{
CPU_Fnct_PTR ISR_fnct;
CPU_REG32 p_vim_tbl;
CPU_INT32U ch_ix;
CPU_INT32U Pend_reg_0;
CPU_INT32U Pend_reg_1;
CPU_INT32U Pend_reg_2;
CPU_INT32U Pend_reg_3;
CPU_INT32U Pend_mask;
开关(src_id){
示例 OS_CPU_ARM_FLOW_IRQ:
CH_IX =(CPU_INT32U) BSP_INT_REG_IRQ_INDEX;
if (ch_ix =0U){ phantomIRQcnt++;break;/* phantomInterrupt ();*/}
P_vim_tbl =(CPU_REG32 *) BSP_INT_ADDR_INT_TBL;
ISR_fnct =(cpu_Fnct_ptr) p_vim_tbl[ch_ix];
ch_ix--;
if ((ch_ix =16U)||(ch_ix =35U)||(ch_ix ==45U)||(ch_ix ==113u)){
//在不启用中断的情况下执行 ISR
(* isr_fnct)((void *) ch_ix);//调用 ISR,并将其作为参数传递给通道。 *
中断;
}
if (isr_fnct!=(cpu_Fnct_ptr) 0){
Pend_reg_0 = BSP_INT_REG_REQENACLR0; /*存储中断状态 *
Pend_reg_1 = BSP_INT_REG_REQENACLR1;
Pend_reg_2 = BSP_INT_REG_REQENACLR2;
Pend_reg_3 = BSP_INT_REG_REQENACLR3;
if (ch_ix <= 31){ /* Dis。 所有优先级低于当前*/的中断
Pend_mask = 0xFFFFFFFF << ch_ix;
bsp_int_REG_REQENACLR0 = Pend_MASK;
BSP_INT_REG_REQENACLR1 = 0xFFFFFFFF;
BSP_INT_REG_REQENACLR2 = 0xFFFFFFFF;
BSP_INT_REG_REQENACLR3 = 0xFFFFFFFF;
} 否则、如果(ch_ix <= 63){
Pend_mask = 0xFFFFFFFF <<(ch_ix - 32);
bsp_int_REG_REQENACLR1 = Pend_MASK;
BSP_INT_REG_REQENACLR2 = 0xFFFFFFFF;
BSP_INT_REG_REQENACLR3 = 0xFFFFFFFF;
} 否则、如果(ch_ix <= 95){
Pend_mask = 0xFFFFFFFF <<(ch_ix - 64);
bsp_int_REG_REQENACLR2 = Pend_MASK;
BSP_INT_REG_REQENACLR3 = 0xFFFFFFFF;
} 否则{
Pend_mask = 0xFFFFFFFF <<(ch_ix - 96);
bsp_int_REG_REQENACLR3 = Pend_MASK;
}
//在启用中断的情况下执行所有其它 ISR
cpu_inten(); /*启用高优先级中断 *
(* isr_fnct)((void *) ch_ix);//调用 ISR,并将其作为参数传递给通道。 *
cpu_IntDiss(); /*禁用中断 *
BSP_INT_REG_REQENASET0 = PEND _REG_0;/*恢复原始中断状态 *
bsp_int_REG_REQENASET1 = Pend_reg_1;
bsp_int_REG_REQENASET2 = Pend_reg_2;
bsp_int_REG_REQENASET3 = Pend_reg_3;
}
否则{nullIRQcnt++;}
中断;
OS_CPU_ARM_FLOW_FIQ 情况: /*参见注1。 *
默认值:
中断;
}
}