Обнаружение ошибок CAN-шины под драйвером socketCAN linux

Наши продукты используют хорошо известный стек CANopen, который использует socketCAN, на встроенной системе на основе Beaglebone Black, работающей под Ubuntu 14.04 LTS. Но по какой-то причине, даже несмотря на то, что стек, который мы используем, будет определять, когда шина CAN переходит в ПАССИВНОЕ состояние или даже в состояние ВЫКЛ., Он никогда не указывает, когда шина CAN восстанавливается после ошибок и выходит из ПАССИВНОГО состояния или состояния предупреждения. , и переходит в состояние без ошибок.

Если бы мне пришлось напрямую запросить драйвер socketCAN (через вызовы ioctl), смог бы я определить, когда шина CAN входит и выходит из состояния предупреждения (которое составляет менее 127 ошибок), в ПАССИВНОМ состоянии и выходит из него ( больше 127 ошибок) или отключается шина (больше 255 ошибок)?

Я хотел бы знать, трачу ли я свое время на это или есть лучший способ точно и в реальном времени обнаруживать все состояния CAN-шины?


person Chris Galas    schedule 02.10.2018    source источник


Ответы (2)


У меня есть лишь частичное решение этой проблемы. Поскольку вы используете socketCAN, интерфейс рассматривается как стандартный сетевой интерфейс, на котором мы можем запросить статус. На основе Как проверить Ethernet в Linux? (замените "eth0" на " can0 "), вы можете проверить статус ссылки. Это не в реальном времени, но может выполняться в периодическом потоке для проверки состояния шины.

person Nico7as    schedule 18.11.2019

Так что, хотя это старый вопрос, я случайно наткнулся на него (пока искал что-то, относящееся только к категории).

SocketCAN предоставляет все средства для обнаружения ошибочных кадров OOB. Предположим, ваш код выглядит примерно так:

int readFromCan(int socketFd, unsigned char* data, unsigned int* rxId) {
    int32_t bytesRead = -1;
    struct can_frame canFrame = {0};

    bytesRead = (int32_t)read(socketFd, &canFrame, sizeof(can_frame));
    if (bytesRead >= 0) {
        bytesRead = canFrame.can_dlc;

        if (data) {
            memcpy(data, canFrame.data, readBytes);
        }

        if (rxId) {
             *rxId = canFrame.can_id; // This will come in handy
        }
    }

    return bytesRead;
}

void doStuffWithMessage() {
    int32_t mySocketFd = fooGetSocketFd();
    int32_t receiveId = 0;
    unsigned char myData[8] = {0};
    int32_t dataLength = 0;

    if ((dataLength = readFromCan(mySocketFd, myData, &receiveId) == -1) {
        // Handle error
        return;
    }

    if (receiveId & CAN_ERR_MASK != 0) {
        // Handle error frame
        return;
    }

    // Do stuff with your data
}
person SimonC    schedule 17.06.2020
comment
Этот код не работает. Думаю, вам нужно заменить CAN_ERR_MASK на CAN_ERR_FLAG ... - person Wile E. Genius; 03.03.2021