2

設定

1 つの CAN バスに 2 つのノードが接続されています。最初のノードは、いくつかのリアルタイム ハードウェアによって制御されるブラック ボックスです。2 番目のノードは、PEAK-USB CAN コントローラーが接続された Linux マシンです。

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

時折のフレーム損失に関連する問題を調査するために、CAN アービトレーション プロセスを模倣したいと考えています。そのために、CAN ビットレートを 125Kb/s に設定し、1ms の遅延でランダムな CAN フレームをフラッディングし、can-utils のcanbusloadでバス負荷を制御しています。また、実行中のCANエラーフレームと全体的な缶の統計を次のように監視します。candump can0,0~0,#ffffffffip -s -d link show 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% のときに、衝突 (調停) が発生せず、またはその他の種類のエラー フレームが発生することなく、何時間も機能することです。遅延を減らしてバスの負荷を増やすと、 「ENOBUFS 105 No buffer space available」または「EAGAIN 11 Resource temporarywrite(2) available」のいずれかで失敗します- 実際のエラーは、qlenパラメータを変更するか、デフォルトに設定するかによって異なります。

私が理解しているように、私がかけた負荷は十分でないか、または多すぎます。2 つのノードを調停に参加させる正しい方法は何でしょうか? CAN_ERR_LOSTARB正常な結果は、定数 fromと0以外のcollsnscan/error.hの値に対応する受信 CAN エラー フレームになります。

ソースコード

HW ノード (CAN ボードを搭載した Arduino Due)

#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);
}

Linux ノード

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <linux/can.h>
#include <linux/can/raw.h>

int main(int argc, char *argv[])
{
  int s;
  int nbytes;
  struct sockaddr_can addr;
  struct can_frame frame;
  struct ifreq ifr;

  const char *ifname = "can0";

  if((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
    perror("Error while opening socket");
    return -1;
  }

  strcpy(ifr.ifr_name, ifname);
  ioctl(s, SIOCGIFINDEX, &ifr);

  addr.can_family  = AF_CAN;
  addr.can_ifindex = ifr.ifr_ifindex;

  printf("%s at index %d\n", ifname, ifr.ifr_ifindex);

  if(bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    perror("Error in socket bind");
    return -2;
  }

  frame.can_id  = 0x304;
  frame.can_dlc = 2;
  frame.data[0] = 0x11;
  frame.data[1] = 0x22;

  int sleep_ms = atoi(argv[1]) * 1000;

  for (;;) {
    nbytes = write(s, &frame, sizeof(struct can_frame));
    if (nbytes == -1) {
      perror("write");
      return 1;
    }
    usleep(sleep_ms);
  }
  return 0;
}
4

1 に答える 1