CAN总线错误分析与解决_can总线的错误帧,应用层要处理吗

  1. #define CAN_ERR_CRTL 0x00000004U /* controller problems / data[1] */
  2. #define CAN_ERR_PROT 0x00000008U /* protocol violations / data[2…3] */
  3. #define CAN_ERR_TRX 0x00000010U /* transceiver status / data[4] */
  4. #define CAN_ERR_ACK 0x00000020U /* received no ACK on transmission */
  5. #define CAN_ERR_BUSOFF 0x00000040U /* bus off */
  6. #define CAN_ERR_BUSERROR 0x00000080U /* bus error (may flood!) */
  7. #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
?

  1. /* error status of CAN-controller / data[1] */
  2. #define CAN_ERR_CRTL_UNSPEC 0x00 /* unspecified */
  3. #define CAN_ERR_CRTL_RX_OVERFLOW 0x01 /* RX buffer overflow */
  4. #define CAN_ERR_CRTL_TX_OVERFLOW 0x02 /* TX buffer overflow */
  5. #define CAN_ERR_CRTL_RX_WARNING 0x04 /* reached warning level for RX errors */
  6. #define CAN_ERR_CRTL_TX_WARNING 0x08 /* reached warning level for TX errors */
  7. #define CAN_ERR_CRTL_RX_PASSIVE 0x10 /* reached error passive status RX */
  8. #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
?

  1. static int ti_hecc_error(struct net_device *ndev, int int_status,
  2. 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
?

  1. if (int_status & HECC_CANGIF_WLIF) { /* warning level int */
  2. if ((int_status & HECC_CANGIF_BOIF) == 0) {
  3. priv->can.state = CAN_STATE_ERROR_WARNING;
  4. ++priv->can.can_stats.error_warning;
  5. cf->can_id |= CAN_ERR_CRTL;
  6. if (hecc_read(priv, HECC_CANTEC) > 96)
  7. cf->data[1] |= CAN_ERR_CRTL_TX_WARNING;
  8. if (hecc_read(priv, HECC_CANREC) > 96)
  9. cf->data[1] |= CAN_ERR_CRTL_RX_WARNING;
  10. }
  11. hecc_set_bit(priv, HECC_CANES, HECC_CANES_EW);
  12. dev_dbg(priv->ndev->dev.parent, “Error Warning interrupt\n”);
  13. hecc_clear_bit(priv, HECC_CANMC, HECC_CANMC_CCR);
  14. }
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);
    }

  1. 总结

出现这个错误警告的原因很可能是:

  1. 此CAN总线上有干扰,导致CAN控制器发生接收错误,CAN总线上的信号经过收发器转化为差分电平信号,此时信号容易受到外界干扰,这样容易使CAN控制器发生接收错误,接收错误寄存器接收错误计数累计到一定值后会报此错误,如果错误计数达到一定程度甚至会导致总线关闭也就是BUS OFF. 如果最终确认是由于干扰引起的错误计数累计,则应该排查干扰源,然后增加抗干扰措施。

  2. 此CAN节点经过消息滤波后仍然需要接收大量的消息,导致CPU中的CAN控制器接收出错,并且错误计数达到了错误警告的上限。但是庆幸的是总线仍然没有过载,总线还可以正常收发数据,没有引起BUS OFF。但是对于一个安全可靠控制系统,这样的警告是绝对不允许的。我们需要通过一些手段去避免这样的问题出现,例如降低总线数据并发量,降低总线负载。

  3. CAN总线设备离线与错误恢复

这种问题同样很诡异,但是似乎又是比较常见的问题,这样的问题出现的情况往往比较多,例如CAN节Power off也就是电断了,总线上也就肯定监听不到此CAN节点的心跳,或是CAN总线节点没有及时发送心跳,阻塞在任务处理里,又或是此CAN节点物理接线和总线断开,等等原因很多。

我这里要说的一种情况是我厂碰到的另一种问题。

  1. 问题描述

在整个系统重启后发现CAN总线上的某一个Cortex M0设备节点丢失,而其他的设备,也是同样M0架构的MCU和相同控制软件的设备则没有出现丢失的情况。

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
img
img

问题描述

在整个系统重启后发现CAN总线上的某一个Cortex M0设备节点丢失,而其他的设备,也是同样M0架构的MCU和相同控制软件的设备则没有出现丢失的情况。

收集整理了一份《2024年最新物联网嵌入式全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升的朋友。
[外链图片转存中…(img-6MK11XDj-1726118054047)]
[外链图片转存中…(img-M2jJLpAq-1726118054048)]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值