在CAN通讯时候让某节点做插拔、断电等测试,人为的产生一些CAN总线错误,看看能否让总线恢复正常。 结果测试发现,如果总线出现错误,并且打开了CAN错误中断处理的话,通过仿真器调试发现CPU一直在处理CAN错误中断,其他程序得不到处理而呈死机状态。 先是怀疑CAN控制器因为各类错误条件而进入错误中断后,虽在错误中断里清除了相关中断状态标志,但由于计数器值没有清零的原因,马上又产生新的错误中断,这样循环反复,导致其他程序得不到调度。
然后继续做实验,将CAN_IER寄存器中的LECIE和EWGIE这两种中断使能关闭掉,发现还是有这个问题。 客户觉得这样有点奇怪。
从客户粗略描述的现象来看,很像没有清除中断标志导致中断没完没了。经进一步的沟通了解,客户除了开启相关收发中断外,还使能了LECIE、EWGIE、EPVIE、BOFIE、ERRIE跟出错有关的中断,当然SLKIE和WKUIE没有使能。
结合CAN_IER和CAN_ESR寄存器的相关描述,可以看出即使关闭了LECIE、EWGIE两个出错条件,但还有EPVIE、BOFIE两种情形可能导致CAN出错中断。
跟CAN出错中断有关的寄存器主要涉及到3个,分别是CAN主控状态寄存器CAN_MSR,CAN中断使能寄存器CAN_IER,CAN错误状态寄存器CAN_ESR. 说实在的,这个跟CAN出错中断有关的东西还是有点复杂。看看下图,蓝色方框里的是各种错误中断的使能位,红色方框里的是各类出错条件或状态变化条件。请注意图中的与逻辑符号&和或逻辑符号+。
上图中下方与CAN_MSR相关的两类中断触发源跟本话题无关,就不提了,重点看看上方那四个与CAN出错有关的中断源。
细心的人会发现,其实CAN_IER中的ERRIE位是一个CAN出错中断总开关,只有当它被使能的前提下,EWG、EPV、BOF、LEC四个中的一个或几个出错事件配合各自的中断使能位才能产生出错中断,并统一将CAN_MSR中的错误中断请求ERRI位置1,从而申请CAN错误中断。显然,CAN错误中断的请求标志位是ERRI@CAN_MSR,而不是CAN_ESR中的EWGF\EPVF\BOFF的任一位。
聊到这里,我们基本对CAN出错中断相关的寄存器和相关标志有了大致的了解。要把握一点,CAN出错中断有个总使能位ERRIE,其它几个出错事件配合该总使能位最终产生错误中断请求,置位ERRI@CAN_MSR。
回到上面的话题,当查看客户的CAN错误中断处理程序时,发现他在中断程序里的确是做了些标志的清除【本意是想清除中断请求标志】。遗憾的是全是对CAN_ESR寄存器中的相关错误标志进行清零,即对LEC\EWGF\EPVF\BOFF这几个东西清零,偏偏没有对ERRI@CAN_MSR的清零。关键的东西成了漏网之鱼。
还有,他对EWGF\EPVF\BOFF这几个标志清零是无效的,因为这几个标志位是只读的,置1或清零是硬件根据TEC/REC的值动态处理的。
最后让客户把CAN出错中断代码做些调整,在进入CAN出错中断后将CAN_MSR中的ERRI位清0,确实可以解决错误中断循环往复的问题。
小结下,MCU中断行为一般涉及到使能标志、请求标志和触发源。应用中偶尔会出现有人把中断使能标志和中断请求标志弄混的情况。不过相比之下,这里谈到的CAN出错中断相比ST MCU其它外设的中断应用就要复杂或啰嗦些,尤其那个出错中断请求标志感觉有点隐晦。上面提到的案例,当事人可能没弄清CAN出错中断请求标志位到底是哪个,导致进入中断服务程序后清除动作无效,使得出错中断服务程序没完没了,而且还会影响到其它进程正常运行进而导致其它连锁异常。
上一篇:stm32之CAN总线基础
下一篇:基于STM32的FreeRTOS应用问题解答