Understanding CAN Bus in Embedded Linux

What is CAN? Also known as Controller Area Network, the initial motivation was to solve the communication between the vast electronic control systems in modern vehicles, reducing the increasing number of signal wires. Various electronic control systems have been developed, and the number of electronic control systems in vehicles is increasing, such as engine management control, transmission control, automotive instrumentation, air conditioning, door control, lighting control, airbag control, steering control, tire pressure monitoring, braking systems, radar, adaptive cruise control, electronic anti-theft systems, etc. Due to the different types of data used for communication between these systems and the varying requirements for reliability, many systems are composed of multiple buses, which increases the number of wiring harnesses. To meet the needs of “reducing the number of wiring harnesses” and “high-speed communication of large amounts of data through multiple LANs,” Bosch, a German electrical company, developed the CAN communication protocol for automotive applications in 1986.Understanding CAN Bus in Embedded LinuxCharacteristics of CAN Bus:① Multi-master control: When the bus is idle, all nodes can start sending messages. The node that first accesses the bus gains the right to send, and if multiple nodes start sending simultaneously, the node sending the message with the highest priority ID gains the right to send.② Message transmission: When the bus is idle, all nodes connected to the bus can start sending new messages. When more than two nodes start sending messages simultaneously, priority is determined based on the identifier.③ System flexibility: When adding nodes to the bus, the hardware and application layers of other nodes connected to the bus do not need to change.④ Communication speed: All nodes in the same network must be set to a uniform communication speed. If one node’s communication speed differs from the others, it will output an error signal, disrupting communication across the entire network; different networks can have different communication speeds.⑤ Connectivity: The CAN bus can connect multiple nodes simultaneously, and theoretically, there is no limit to the number of nodes that can be connected, but in practice, the number of connectable nodes is limited by the time delay and electrical load on the bus.The CAN bus transmission speed can reach 1 Mbps, and the latest CAN-FD can achieve speeds up to 5 Mbps or even higher.Data Frame of CAN BusFrame start, arbitration segment, control segment, data segment, CRC segment, ACK segment, frame endSocketCan Application Programming:Linux provides the SocketCAN application programming interface, making CAN bus communication similar to Ethernet communication, with a more general and flexible application programming interface.① Create a socket

int sockfd = -1;/* Create socket */sockfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);if(0 > sockfd) {perror("socket error");exit(EXIT_FAILURE);}

② Bind the socket to the CAN device

/* Specify can0 device */struct ifreq ifr = {0};struct sockaddr_can can_addr = {0};strcpy(ifr.ifr_name, "can0"); // Specify nameioctl(sockfd, SIOCGIFINDEX, &ifr);can_addr.can_family = AF_CAN; // Fill data can_addr.can_ifindex = ifr.ifr_ifindex;/* Bind the socket to can0 */ret = bind(sockfd, (struct sockaddr *)&can_addr, sizeof(can_addr));if (0 > ret) {perror("bind error");close(sockfd);exit(EXIT_FAILURE);}

struct ifreq:The structure contains network interface configuration/query (interface name, IP address, MAC address)struct sockaddr_can:The structure binds the CAN socket to a specific interface, specifying the CAN ID

struct ifreq {    char ifr_name[IFNAMSIZ];    // Input: interface name (e.g., "can0")    int  ifr_ifindex;           // Output: interface index (filled by kernel)};
struct sockaddr_can {    sa_family_t can_family;    // Address family, fixed to AF_CAN    int         can_ifindex;   // CAN interface index (obtained via ifreq)    union {        struct { canid_t rx_id, tx_id; } tp;  // For ISO-TP protocol        // Other members...    } can_addr;};
// Bus data frame structurestruct can_frame {    canid_t can_id;  // CAN identifier (11-bit standard frame or 29-bit extended frame)    __u8    can_dlc; // Data Length Code, 0-8 bytes    __u8    data[8]; // Data field, up to 8 bytes    __u8    padding; // Padding byte (for alignment)    __u8    reserved; // Reserved byte};

③ Set filtering rules If no filtering rules are set, the application will receive messages with all IDs by default; if our application only needs to receive messages with certain specific IDs (or does not accept all messages, only sends messages), filtering rules can be set using the setsockopt function.

struct can_filter rfilter[2]; // Define a can_filter structure object// Fill filtering rules, only receive messages with ID (can_id & can_mask)rfilter[0].can_id = 0x60A;rfilter[0].can_mask = 0x7FF;rfilter[1].can_id = 0x60B;rfilter[1].can_mask = 0x7FF;// Call setsockopt to set filtering rulessetsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

④ Data transmission

struct can_frame frame; // Define a can_frame variableframe.can_id = 123;// If it is an extended frame, then frame.can_id = CAN_EFF_FLAG | 123;frame.can_dlc = 3; // Data length is 3frame.data[0] = 0xA0; // Data content is 0xA0frame.data[1] = 0xB0; // Data content is 0xB0frame.data[2] = 0xC0; // Data content is 0xC0write(sockfd, &frame, sizeof(frame)); // Send data

⑤ Data reception:

struct can_frame frame;read(sockfd, &frame, sizeof(frame));

Leave a Comment