1. 问题背景
在软件开发初期基本上需要开发CAN驱动模块,最为常见的一类问题就是软件内部虽然在周期发送CAN帧,但是仅发出一帧?
今天小T跟大家一起来解析这个最为常见的问题原因,以英飞凌TC3XX芯片CAN驱动开发为例。
2. 过程分析
2.1 CAN发送状态分析
以TC3XX芯片为例,CAN发送一般均通过如下函数接口Can_17_McmCan_Write 对外发送CAN报文。
该函数也有相应的返回值, 相关说明如下图:
我们通过调试代码发现此时canStatus的状态为CAN_BUSY, 则表示当前CAN没有可用的Tx hardware buffer。
Q1:为什么没有可用的Tx hardware Buffer呢?
Ans: 首先我们查看下回复CAN_BUSY的条件:
CanTxMask表示32个Tx的发送状态Bit位,其中某Bit位为1表示当前Tx Buffer处于空闲状态,为0则表示已经使用。当前可以看到是由于Line 7564行条件满足时才会进入到CAN_BUSY状态。
其中BufferIndex可理解为对应发送数据的Tx Mailobx,当前可以判断对应的Bit位为0,从而造成条件成立,导致回复CAN_BUSY。
Q2:什么情况CanTxMask中特定的Bit位为0呢?
Ans: 通过分析代码发现,CAN初始化过程会将CanTxMask全部初始化为1,如下图所示:
在调用发送函数Can_17_McmCan_Write 中,首次发送时,任意对应TxBuffer均会满足条件成立,从而能够分配得到Tx Buffer,得到Buffer之后,便会将对应Buffer的CanTxMask的Bit置位为0,进而锁住该Buffer,直到被释放之后才能够使用,如下图为锁住对应Tx Buffer代码:
Q2:什么情况下会释放这个Tx Buffer所在的Bit位呢?
Ans: 通过分析代码发现在对应的Controller发送完成中断中如下代码:
如下图为Controller0的发送完成中断代码,一级一级的追溯,最终我们可以看到中断函数中调用了函数接口Can_17_McmCan_IsrTransmitHandler。
在上述函数接口中继续调用了函数接口Can_17_McmCan_lTxEventHandler。
在上述TxEventHandler函数中继续调用了Can_17_McmCan_lTxEventProcessingHandler ,在该函数中我们便发现了释放Tx Buffer的地方,如下图所示:
2.2 中断分析
接下来我们看下中断是否使能了呢?很明显发现发送完成中断并没有使能,如下图所示:
Q3:如何使能CAN发送完成中断呢?
Ans: 对于英飞凌TC3XX芯片而言,总共3个Can Module, 每个Can Module有4个Can Node,所以总共有12个Can Controller。每一个CAN Controller均有如下四类中断必须进行使能:
- CAN Rx FIFO中断:如果对应的CAN Mailbox配置为接收且Mailbox大于1,那么此时对应Mapping到这类CAN Mailbox将会触发Rx FIFO中断,而不是Rx Dedicated Buffer中断;
- CAN Rx Dedicated Buffer 中断:如果对应的CAN Mailbox配置成接收且Mailbox等于1,那么则会触发该类中断,则不会触发Rx FIFO中断;
- CAN Tx Finish 中断:每次CAN发送成功之后均会触发此类中断;
- CAN Busoff中断:当发送CAN Busoff时便会触发此类中断;
这四类中断使能的前提条件有两个:
- 配置对应CAN Controller的上述4个中断优先级且均大于0,那么上述发送完成中断则不会是灰色状态,能够加入到代码编译;
- 将中断挂载到英飞凌中断处理模块IR上并使能中断;
上述这两个步骤统一在MCAL中IRQ模块或者OS中任意一个配置即可,无需同时配置。本文以没有OS,在MCAL中的IRQ模块中进行配置作为参考示例:
至此中断函数入口使能完毕,除此之外并没有真正意义上使能了CAN中断,此时还需要调用如下图CAN中断初始化函数挂载中断并使能中断。
注意:如果仅仅调用了IrqCan_Init进行了中断初始化,只是代表挂载了中断,中断标志位能够在SRC相关寄存器置位,如果对应中断的SRE没有使能,也不会将中断传递至对应中断服务者,即CPU0,这点特别注意,许多情况下中断没有产生基本上就是这个最为简单的问题。
2.3 问题发生逻辑关系图
如下图所示为问题发生逻辑关系图:
3. 根本原因
- 在MCAL IRQ模块中没有配置CAN相关中断以及优先级,导致中断入口没有使能;
- 没有调用CAN中断初始化函数或者在SRC中没有使能对应的SRE位;
4. 修复措施
- 在MCAL IRQ模块配置好CAN相关中断以及优先级,同时在调用CAN中断初始化函数并使能对应SRC的SRE中断使能位;
- 如果存在OS则需要在OS中配置好CAT2中断并挂载中断即可;
5. 小T总结
- 在开发任何外设驱动过程中如果需要使用中断,务必要检查中断被成功使能以及如何使能;
- 如果出现发送不成功,首先检查CAN驱动接口的返回值是否检查,然后按图索骥便可以找到问题所在,要不怕调试,调试多了自然经验就上去了,下次就无需调试也就知道问题最有可能出在那里了。
作者:汽车小T8
来源:ADAS与ECU之吾见
推荐阅读:
更多汽车电子干货请关注汽车电子与软件专栏。欢迎添加极术小姐姐微信(id:aijishu20)加入技术交流群,请备注研究方向。