在通过第三方库使用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%确定ISB被调用的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) 例子)确定这个中断/异常的来源 把它推到堆栈上?
我是否完全错了?我很高兴 放弃任何和所有这一思路。
感谢您提供任何帮助或见解,当我可以将两个脑细胞组合在一起时,我会用更多(简明)信息更新此信息。
答案 0 :(得分:0)
解决了问题 - 原来是在CPU的勘误表中处理。