是否可以模仿CAN总线上的仲裁?

时间:2019-07-18 07:36:45

标签: can-bus socketcan

设置

我有两个节点连接到一条CAN总线。第一个节点是黑匣子,由一些实时硬件控制。第二个节点是一台装有PEAK-USB CAN控制器的Linux机器:

+--------+               +----------+
| HW CAN |--- CAN BUS ---| Linux PC |
+--------+               +----------+

为了调查一些与偶尔的帧丢失有关的问题,我想模仿CAN仲裁过程。为此,我将CAN比特率设置为125Kb / s,并使用具有1ms延迟的随机CAN帧对其进行泛洪,使用来自 can-utils canbusload 控制总线负载。我还监视运行candump can0,0~0,#ffffffff的CAN错误帧以及使用ip -s -d link show can的总体can统计信息:

26: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UNKNOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0
    can state ERROR-ACTIVE restart-ms 0
          bitrate 125000 sample-point 0.875
          tq 500 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
          pcan_usb: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
          clock 8000000
          re-started bus-errors arbit-lost error-warn error-pass bus-off
          0          0          0          0          0          0
    RX: bytes  packets  errors  dropped overrun mcast
    120880     15110    0       0       0       0
    TX: bytes  packets  errors  dropped carrier collsns
    234123     123412   0       0       0       0

问题

现在的问题是,当负载为99%时,给定的设置可以在零冲突(仲裁)或任何其他类型的错误帧的情况下工作数小时。当我减少增加总线负载的延迟时,write(2)失败,出现“ ENOBUFS 105 No可用的缓冲区空间” “ EAGAIN 11资源暂时不可用” -实际错误取决于我是否修改 qlen 参数或将其设置为默认值。

据我了解,我施加的负载不够或太大。使两个节点进入仲裁的正确方法是什么?成功的结果将是接收到一个与CAN_ERR_LOSTARB的{​​{1}}常量相对应的CAN错误帧,以及一个 collsns 而不是 0 的值。

UDP-两个节点的源代码

硬件节点(带有CAN板的Arduino Due)

can/error.h

Linux节点

#include <due_can.h>

CAN_FRAME input, output;

// the setup function runs once when you press reset or power the board
void setup() {
  Serial.begin(9600);
  Serial.println("start");

//  Can0.begin(CAN_BPS_10K);
  Can0.begin(CAN_BPS_125K);
//  Can0.begin(CAN_BPS_250K);


  output.id = 0x303;
  output.length = 8;
  output.data.low = 0x12abcdef;
  output.data.high = 0x24abcdef;
}

// the loop function runs over and over again forever
void loop() {    
    Can0.sendFrame(output);
    Can0.read(input);

    delay(1);
}

1 个答案:

答案 0 :(得分:1)

documentation小节4.1.2 RAW套接字选项CAN_RAW_ERR_FILTER中,该错误默认情况下未激活,这就是ip中丢失仲裁字段没有增加的原因。

为了触发所有错误,您需要添加这两行:

can_err_mask_t err_mask = CAN_ERR_MASK;
setsockopt(socket_can, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));

但是此功能并非对所有驱动程序和设备都可用,因为它要求硬件具有环回模式。对于PEAK-USB,似乎如果来自设备的固件版本低于4.x,则不会出现环回[source]。因此SocketCAN将无法检测丢失的仲裁。