3

Our products are using a well known CANopen stack, which uses socketCAN, on an embedded Beaglebone Black based system running under Ubuntu 14.04 LTS. But for some reason, even though the stack we're using will detect when the CAN bus goes into a PASSIVE state or even a BUS OFF state, it never indicates when the CAN bus recovers from errors and goes out of a PASSIVE or warning state, and enters a non error state.

If I were to query the socketCAN driver directly (via ioctl calls), would I be able to detect when the CAN bus goes in and out of a warning state (which is less than 127 errors), in and out of a PASSIVE state (greater than 127 errors) or goes BUS OFF (greater than 255 errors)?

I'd like to know if I'd be wasting my time doing this or is there a better way to detect, accurately and in real-time, all conditions of a CAN bus?

Chris Galas
  • 43
  • 1
  • 6

2 Answers2

1

I have only a partial solution to that problem. As you are using socketCAN, the interface is seen as a standard network interface, on which we can query the status. Based on How to check Ethernet in Linux? (replace "eth0" by "can0"), you can check the link status. This is not real-time, but can be executed in a periodic thread to check the bus state.

Nico7as
  • 176
  • 1
  • 7
1

So while this is an old question, I just happened to stumble upon it (while searching for something only mildly related).

SocketCAN provides all the means for detecting error frames OOB. Assuming your code looks similar to this:

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
}
Bayou
  • 3,293
  • 1
  • 9
  • 22
SimonC
  • 1,547
  • 1
  • 19
  • 43