3

在通过第三方库使用 CAN 控制器时,在我的 C 应用程序中的某个时刻(运行裸机,监督模式),发生了非法指令错误,该错误被 ISR 捕获;到那时,ISR可用的异常堆栈帧中的程序计数器,故障和返回地址已经为0。当我第一次遇到它时,我能够备份堆栈,看到这样的堆栈跟踪:

Thread [1] <main> (Suspended : Step)    
    0x0    
    0x41f42200    
    ... 
    timerInterrupt() at timer.c:1,175 0x2432ec    
    0x41902210
    ...
    main() at main.c:1,433 0x211a44

其中 0x40000000 是此处理器的 IPSBAR。

我以可以快速重现此问题的已知状态多次运行该应用程序,通常在跳转到 0x0 之前的中断/异常时下降到完全相同的堆栈跟踪/保存的指令。通过测试,我注意到跳转只会发生在中断被禁用后重新启用之后的指令上,或者发生在没有屏蔽中断的代码段中。因此,我认为这一定是导致问题的用户中断,尽管我不确定为什么它似乎会尝试调用在掩码中未启用中断时未设置的处理程序。我不是 100% 确定 IPSBAR 范围内地址的含义,之前和 ISR 被调用,但因为它们对于该 ISR 的每次调用都是相同的,

因此,在添加正常处理程序并再次运行应用程序之前,我向中断控制器 0 上的所有中断向量添加了一个默认中断处理程序 - 你瞧,当该可疑中断被触发时,默认处理程序中设置的断点被命中(例如,堆栈看起来像这样):

Thread [1] <main> (Suspended : Step)    
    __DefaultInterrupt() at interrupts.c    
    0x41f42200    
    ...
    timerInterrupt() at timer.c:1,175 0x2432ec    
    0x41902210       
    ...
    main() at main.c:1,433 0x211a44

观察那个函数中SWIACK0的值,我看到中断源是100(用户中断36,PIT0中断)。好吧,它已经有一个 ISR(上面的堆栈中的 timerInterrupt() )。接下来,我检查了保存 ISR 函数指针的 RAM 区域,以查看定时器中断处理程序函数指针是否已损坏,但在设置所有中断处理程序的时间与默认处理程序中的断点被命中之间没有变化。

我还注意到,如果我将 CAN 控制器的中断处理程序的中断级别设置为 7(同一个中断处理所有 18 个 FlexCAN 中断源),则不会出现问题。我还不确定该怎么做,但这个问题确实表明 CAN 库或控制器存在问题。

编辑-此时我不确定哪个 ISR 正在处理中断,但我已将单独的处理程序添加到最初怀疑的中断源中,并且它始终是中断源 63-根据文档,这是一个未使用的中断,最后一个在中断控制器 0 上。

编辑 2:我想到 SWIACK0 中的活动中断源实际上是正确的,但可能还有另一个问题,比如向量基地址可能被重写。不幸的是,我不确定如何将其读回,因为它是只写值。我最初认为 PIT0 的中断源在该寄存器中,因为默认中断处理程序是从定时器中断处理程序中调用的,但如果定时器中断不在堆栈中,它也会被指示。参考手册表明片上调试设备可用于回读控制寄存器和 VBR,但我在调试手册中没有看到任何信息来执行此操作。

长话短说,我想找出跳转到超空间的来源,或者我可以使用什么信息来获取它。

  • IPSBAR 范围内的地址被推入堆栈是什么意思?

  • 由于那些寻址似乎完全与它们的源相关联,有没有办法使用堆栈中的值(例如,第一个示例中的 0x41f42200)来确定将
    其推入堆栈的中断/异常的源?

  • 我会完全错了吗?我非常乐意
    放弃所有这些想法。

感谢您提供任何帮助或见解,当我可以将两个脑细胞揉在一起时,我会用更多(简洁的)信息来更新它。

4

1 回答 1

0

解决了这个问题——原来是在 CPU 的勘误表中处理的。

于 2013-04-08T21:20:28.573 回答