- #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
- #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2…3] */
- #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
- #define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
- #define CAN_ERR_BUSOFF 0x00000040U /* bus off */
- #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
- #define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
/* error class (mask) in can_id */
#define CAN_ERR_TX_TIMEOUT 0x00000001U /* TX timeout (by netdevice driver) */
#define CAN_ERR_LOSTARB 0x00000002U /* lost arbitration / data[0] */
#define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
#define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2..3] */
#define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
#define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
#define CAN_ERR_BUSOFF 0x00000040U /* bus off */
#define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
#define CAN_ERR_RESTARTED 0x00000100U /* controller restarted */
由错误帧CAN ID : 0x20000004 = 10 0000 0000 0000 0000 0000 0000 0100, 去除最高为的1(SOFZ帧起始位?),因为仲裁位是29位,所以应该是0 0000 0000 0000 0000 0000 0000 0100 =0x00000004,既不是CAN_ERR_BUSOFF也不是CAN_ERR_BUSERROR, 而是CAN_ERR_CTRL, 即CAN控制器的问题,而我们在看data[1]描述的CAN 控制器错误类型描述:
[cpp]
view plain
copy
print
?
- /* error status of CAN-controller / data[1] */
- #define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
- #define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
- #define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
- #define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
- #define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
- #define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
- #define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
/* error status of CAN-controller / data[1] */
#define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
#define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
#define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
#define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
#define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
#define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
#define CAN_ERR_CRTL_TX_PASSIVE 0x20 /* reached error passive status TX */
我们再看我们截取的错误帧数据报文中显示data[1] = 0x04,如下图所示:
即具体错误为:
#define CAN\_ERR\_CRTL\_RX\_WARNING 0x04 /\* reached warning level for RX errors \*/
也就是说CAN 控制器接收错误计数达到了警告的级别,需要提出警告,如果再这样下去CAN控制器就要过载了,甚至会引起总线的BUS OFF.
我们再回头看内核源码对此错误的处理:产生data[1] = CAN_ERR_CRTL_RX_WARNING 错误的内核源函数为:
[cpp]
view plain
copy
print
?
- static int ti_hecc_error(struct net_device *ndev, int int_status,
- int err_status)
static int ti_hecc_error(struct net_device *ndev, int int_status,
int err_status)
HECC也就是TI公司高速终端CAN控制器的简称,用以上的函数描述TI CAN core的错误处理,如下,我们可以看到也就是CAN控制器接收错误计数REC大于96的时候内核就会报此错误
[cpp]
view plain
copy
print
?
- if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
- if ((int_status & HECC_CANGIF_BOIF) == 0) {
- priv->can.state = CAN_STATE_ERROR_WARNING;
- ++priv->can.can_stats.error_warning;
- cf->can_id |= CAN_ERR_CRTL;
- if (hecc_read(priv, HECC_CANTEC) > 96)
- cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
- if (hecc_read(priv, HECC_CANREC) > 96)
- cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
- }
- hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
- dev_dbg(priv->ndev->dev.parent, “Error Warning interrupt\n”);
- hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
- }
if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
if ((int_status & HECC_CANGIF_BOIF) == 0) {
priv->can.state = CAN_STATE_ERROR_WARNING;
++priv->can.can_stats.error_warning;
cf->can_id |= CAN_ERR_CRTL;
if (hecc_read(priv, HECC_CANTEC) > 96)
cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
if (hecc_read(priv, HECC_CANREC) > 96)
cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
}
hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
dev_dbg(priv->ndev->dev.parent, "Error Warning interrupt\n");
hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
}
出现这个错误警告的原因很可能是:
-
此CAN总线上有干扰,导致CAN控制器发生接收错误,CAN总线上的信号经过收发器转化为差分电平信号,此时信号容易受到外界干扰,这样容易使CAN控制器发生接收错误,接收错误寄存器接收错误计数累计到一定值后会报此错误,如果错误计数达到一定程度甚至会导致总线关闭也就是BUS OFF. 如果最终确认是由于干扰引起的错误计数累计,则应该排查干扰源,然后增加抗干扰措施。
-
此CAN节点经过消息滤波后仍然需要接收大量的消息,导致CPU中的CAN控制器接收出错,并且错误计数达到了错误警告的上限。但是庆幸的是总线仍然没有过载,总线还可以正常收发数据,没有引起BUS OFF。但是对于一个安全可靠控制系统,这样的警告是绝对不允许的。我们需要通过一些手段去避免这样的问题出现,例如降低总线数据并发量,降低总线负载。
-
CAN总线设备离线与错误恢复
这种问题同样很诡异,但是似乎又是比较常见的问题,这样的问题出现的情况往往比较多,例如CAN节Power off也就是电断了,总线上也就肯定监听不到此CAN节点的心跳,或是CAN总线节点没有及时发送心跳,阻塞在任务处理里,又或是此CAN节点物理接线和总线断开,等等原因很多。
我这里要说的一种情况是我厂碰到的另一种问题。
在整个系统重启后发现CAN总线上的某一个Cortex M0设备节点丢失,而其他的设备,也是同样M0架构的MCU和相同控制软件的设备则没有出现丢失的情况。
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
问题描述
在整个系统重启后发现CAN总线上的某一个Cortex M0设备节点丢失,而其他的设备,也是同样M0架构的MCU和相同控制软件的设备则没有出现丢失的情况。
收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-6MK11XDj-1726118054047)]
[外链图片转存中…(img-M2jJLpAq-1726118054048)]