embedded-linuxcan-bussocketcan

How check bus state in socketcan


I am using flexcan driver on an embedded linux and I have C program controling can messages. In my C program I need to check the state of the can bus e.g. buss-off or error-active. I can use linux command like ip -details -statistics link show can0 with following result:

2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state *ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 100 
          bitrate 250000 sample-point 0.866 
          tq 266 prop-seg 6 phase-seg1 6 phase-seg2 2 sjw 1
          flexcan: tseg1 4..16 tseg2 2..8 sjw 1..4 brp 1..256 brp-inc 1
          clock 30000000
          re-started bus-errors arbit-lost error-warn error-pass bus-off
          31594      0          0          7686       25577      33258     
    RX: bytes  packets  errors  dropped overrun mcast   
    5784560    723230   0       1       0       0       
    TX: bytes  packets  errors  dropped carrier collsns 
    157896     19742    0       33269   0       0       

How can I get that can state ERROR-ACTIVE in my C program? Also I can see in the flex can driver there are some registers that can be used to see the state but I don't know how to include these values in my program also. registers like FLEXCAN_ESR_BOFF_INT contains the values that I need.


Solution

  • You can setup your socket to return CAN errors as messages.

    As described in Network Problem Notifications the CAN interface driver can generate so called Error Message Frames that can optionally be passed to the user application in the same way as other CAN frames. The possible errors are divided into different error classes that may be filtered using the appropriate error mask. To register for every possible error condition CAN_ERR_MASK can be used as value for the error mask. The values for the error mask are defined in linux/can/error.h

    can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );
    
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER,
               &err_mask, sizeof(err_mask));
    

    See kernel documentation for more information.

    Update

    Take a look at libsocketcan and the routine can_get_state.