美文网首页
Linux SocketCAN说明文档-can.txt

Linux SocketCAN说明文档-can.txt

作者: YottaYuan | 来源:发表于2020-03-15 04:43 被阅读0次

    Linux SocketCAN说明文档-can.txt

    本文为控制器局域网协议系列(又名SocketCAN)的自述文件,该文件包含以下内容:

    • 1 概述/什么是SocketCAN

    • 2 动机/为什么要使用套接字API

    • 3 SocketCAN概念
      3.1 接收清单
      3.2 发送帧的本地环回
      3.3 网络问题通知

    • 4 如何使用SocketCAN
      4.1带有can_filters(SOCK_RAW)的RAW协议套接字
      4.1.1 RAW套接字选项CAN_RAW_FILTER
      4.1.2 RAW套接字选项CAN_RAW_ERR_FILTER
      4.1.3 RAW套接字选项CAN_RAW_LOOPBACK
      4.1.4 RAW套接字选项CAN_RAW_RECV_OWN_MSGS
      4.1.5 RAW套接字选项CAN_RAW_FD_FRAMES
      4.1.6 RAW套接字选项CAN_RAW_JOIN_FILTERS
      4.1.7 RAW套接字返回的消息标志
      4.2 广播管理器协议套接字(SOCK_DGRAM)
      4.2.1 广播管理器操作
      4.2.2 广播管理器消息标志
      4.2.3 广播管理器传输计时器
      4.2.4 广播管理器消息序列传输
      4.2.5 广播管理器接收过滤计时器
      4.2.6 广播管理器多路消息接收过滤器
      4.2.7 广播管理器CAN FD支持
      4.3 连接传输协议(SOCK_SEQPACKET)
      4.4 未连接传输协议(SOCK_DGRAM)

    • 5 SocketCAN核心模块
      5.1 can.ko模块参数
      5.2 procfs内容
      5.3编写自己的CAN协议模块

    • 6 CAN网络驱动程序
      6.1常规设置
      6.2发送帧的本地环回
      6.3 CAN控制器硬件过滤器
      6.4 虚拟CAN驱动程序(vcan)
      6.5 CAN网络设备驱动程序接口
      6.5.1 Netlink界面,用于设置/获取设备属性
      6.5.2 设置CAN位定时
      6.5.3 启动和停止CAN网络设备
      6.6 CAN FD(灵活数据速率)驱动程序支持
      6.7 支持的CAN硬件

    • 7 SocketCAN资源

    • 8 鸣谢(Credits)

    ================================================== =========================

    1.概述/什么是SocketCAN

    socketcan软件包是CAN(控制器局域网)协议的实现,适用于Linux。CAN是一种广泛应用于自动化,嵌入式设备和汽车领域的网络技术。对比Linux下基于字符设备的其他CAN实施方案,SocketCAN使用Berkeley
    套接字API、Linux网络堆栈实现了将CAN设备作为网络接口驱动。CAN套接字API已被设计成与TCP / IP协议尽可能相似,以方便熟悉网络编程的程序员轻松学习使用。

    2.动机/为什么要使用套接字API

    在SocketCAN之前已有基于Linux的CAN实现,问题出现了,为什么我们开始另一个项目。最初的
    实现是作为某些CAN硬件的设备驱动程序,它们基于字符设备,提​​供的功能相对较少。通常,只有特定于硬件的设备,此设备提供字符接口直接从控制器接收和发送原始CAN帧。帧排队和更高级别的传输协议(例如ISO-TP)必须在用户空间应用程序中实现。而且,大多数字符设备实现仅支持单进程操作,类似于串行接口。替换CAN控制器需要使用另一个设备驱动程序,并且通常需要移植程序很多部分以适应新设备的驱动程序API。

    SocketCAN旨在克服这些限制。一个为用户空间应用程序提供套接字接口的新协议系列
    已经实现了,它基于Linux网络构建层,可以使用所有提供的排队功能。一个装置
    CAN控制器驱动将自身向Linux
    网络层注册为网络设备,以便来自CAN控制器模块的CAN帧能够传递到网络层,反之亦然。另外,协议族
    模块提供了用于传输协议模块注册的API,因此可以动态地加载或卸载任意数量的传输协议。实际上,仅can核心模块无法提供任何功能协议,必须加载一个附加协议模块。多套接字可被同时打开,可以在不同或相同的协议模块上侦听/发送不同或相同CAN ID上的帧。同时监听相同CAN ID的套接字可全部收到匹配的CAN帧。希望使用特定的传输协议(例如ISO-TP)进行通信,仅需要在打开套接字时选择该协议,就可以读取和
    写入应用程序数据字节流,而无需处理CAN-ID,帧等。

    用户空间可使用的功能同样适用于字符设备,但从技术角度看,这不是优雅的解决方案,原因如下:

    • 用法复杂。对比将协议参数传递给socket(2)并使用bind(2)选择一个CAN接口和CAN ID,字符设备程序必须使用ioctl(2)执行所有这些操作。

    • 代码重复。角色设备无法使用Linux网络排队代码,因此所有这些代码都必须复制以用于CAN网络。

    • 抽象。在大多数现有的字符设备实现中,直接用于CAN控制器的特定于硬件的设备驱动程序
      为应用程序提供字符设备。
      至少在Unix系统中,对于char和char这都是非常不寻常的
      块设备。例如,您没有用于
      某个串行接口的UART,您的某个声音芯片
      计算机,SCSI或IDE控制器,可以访问您的硬盘
      磁盘或磁带流媒体设备。相反,您有抽象层
      提供统一的字符或块设备接口给
      一方面是一个应用程序,一个用于特定于硬件的接口
      另一方面,设备驱动程序。提供了这些抽象
      通过诸如tty层,音频子系统或SCSI之类的子系统
      和上述设备的IDE子系统。

      实现CAN设备驱动程序的最简单方法是将字符
      设备没有这样的(完整的)抽象层,就像大多数人所做的那样
      现有的驱动程序。正确的方法是添加这样一个
      层具有所有功能,例如注册某些CAN
      ID,支持几个打开的文件描述符和(解复用)
      它们之间的CAN帧,(复杂的)CAN帧排队,以及
      提供用于设备驱动程序进行注册的API。但是
      使用它不会再困难,甚至可能会更容易。
      Linux内核提供的网络框架,这就是
      SocketCAN可以。

      Linux内核的网络框架的使用仅仅是
      自然和最合适的方式来为Linux实现CAN。

    1. SocketCAN概念

    如第2章所述,SocketCAN的主要目标是在Linux网络层上给用户空间应用程序构建一个套接字接口。
    。与众所周知的TCP / IP和以太网相反,CAN总线仅支持广播!,没有如以太网一样MAC层寻址介质。CAN标识符-Can-identifier(can_id)用于在CAN总线上进行仲裁。因此,CAN-ID必须在总线上唯一。设计CAN-ECU时,在网络中,CAN-ID被映射为由特定ECU发送。因此,最好将CAN-ID视为一种源地址。

    3.1接收清单

    多个应用程序的网络透明访问导致不同的应用程序可能对来自同一CAN-ID的CAN网络接口程序感兴趣。因此,实现CAN协议系列的SocketCAN核心模块提供几个高效的接收列表。如果例如用户空间
    应用程序打开CAN RAW套接字,即原始协议模块本身
    从SocketCAN核心请求(范围)CAN-ID
    用户要求。的订阅和取消订阅
    可以为特定的CAN接口或已知的所有(!)完成CAN-ID
    CAN与提供给以下用户的can_rx_(un)register()函数接口
    SocketCAN内核提供的CAN协议模块(请参阅第5章)。
    为了优化运行时的CPU使用率,接收列表被拆分
    每个设备的几个特定列表中,这些列表与请求的匹配
    给定用例的过滤器复杂度。

    3.2发送帧的本地环回

    从其他网络概念可以知道,数据交换
    应用程序可以在相同或不同节点上运行,而无需任何
    更改(相应的寻址信息除外):

         ___ ___ ___ _______ ___
        | _ | | _ | | _ | | _ _ | | _ |
        || A || || B || || C || || A | | B || || C ||
        | ___ | | ___ | | ___ | | _______ | | ___ |
          | | | | |
        -----------------(1)-CAN总线-(2)---------------
    

    为确保应用程序A在
    如示例(1)所示,示例(2)需要
    在适当的位置对发送的CAN帧进行某种本地环回
    节点。

    Linux网络设备(默认情况下)只能处理
    媒体相关帧的发送和接收。因为
    在CAN总线上仲裁低优先级CAN-ID的传输
    可能会由于高优先级CAN帧的接收而延迟。至
    反映节点上正确的流量*发送的环回
    成功传输后,必须立即执行数据。如果
    CAN网络接口无法执行环回
    由于某些原因,SocketCAN内核可以作为备用解决方案来完成此任务。
    有关详细信息,请参见第6.2章(推荐)。

    默认情况下启用环回功能以反映标准
    CAN应用程序的网络行为。由于有一些要求
    RT-SocketCAN组的环回(可选)可以为每个环禁用
    独立的插座。请参阅第4.1章中来自CAN RAW插槽的sockopts。

    • =您确实希望在运行分析器工具时拥有此功能
      就像(相同)节点上的“ candump”或“ cansniffer”。

    3.3 网络问题通知

    CAN总线的使用可能导致物理和媒体访问控制层上的一些问题。检测并记录这些底层问题是CAN用户识别物理收发器层问题、仲裁问题和错误帧所引起的不同ECU问题的关键。检测到错误的发生对于诊断很重要,同时错误必须与确切的时间戳一起记录。为此,CAN接口驱动程序可以生成所谓的错误消息帧,错误消息帧可选择是否同其他CAN帧发送给用户程序。每当物理层或MAC层(例如,通过CAN控制器)发生错误时,驱动创建一个适当的错误消息帧。用户应用程序可通用CAN过滤器请求机制获取错误消息框。在此过滤器定义中,(感兴趣的)错误类型可以被选中。接收错误消息帧默认情况下被禁用。CAN错误消息帧的格式在Linux头文件"include/uapi/linux/can/error.h"中进行了简短介绍。

    4.如何使用SocketCAN

    与TCP/IP一样,您首先需要打开一个套接字以连接CAN网络。由于SocketCAN实现新的协议集,因此您
    需要将PF_CAN作为第一个参数传递给socket(2)函数调用,目前,有两种CAN协议可选,原始套接字协议(Raw)和广播管理器(BCM)。要打开一个套接字,可以对应这么写:

    s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    

    s = socket(PF_CAN, SOCK_DGRAM, CAN_BCM);
    

    成功创建套接字后,通常使用bind(2)系统调用将套接字绑定到CAN接口(由于寻址方式不同,因此与TCP/IP不同-参见第3章)。绑定(CAN_RAW)或连接(CAN_BCM)套接字后,
    ,您可以从套接字使用读取read(2)和写入write(2)或使用send(2),sendto(2),sendmsg(2)和recv *等对应操作。也有CAN特定的套接字选项,如下面所述:

    在include/linux/can.h中定义了基本的CAN框架结构和sockaddr结构 :

        struct can_frame {
                canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
                __u8    can_dlc; /* frame payload length in byte (0 .. 8) */
                __u8    __pad;   /* padding */
                __u8    __res0;  /* reserved / padding */
                __u8    __res1;  /* reserved / padding */
                __u8    data[8] __attribute__((aligned(8)));
        };
    

    (线性)有效载荷数据[]与64位边界的对齐(The alignment of the linear payload data[] to a 64bit boundary)允许用户定义自己的结构和联合以轻松访问CAN有效载荷。CAN总线上没有给定默认的字节序 。CAN_RAW套接字上的read(2)系统调用将传输一个struct can_frame到用户空间。

    sockaddr_can结构的接口索引类似于PF_PACKET套接字,该套接字还绑定到特定接口:

      struct sockaddr_can {
                sa_family_t can_family;
                int         can_ifindex;
                union {
                        /* transport protocol class address info (e.g. ISOTP) */
                        struct { canid_t rx_id, tx_id; } tp;
    
                        /* reserved for future CAN protocols address information */
                } can_addr;
        };
    

    要确定接口索引(interface index),必须适当调用ioctl()(没有错误检查的CAN_RAW套接字示例):

    int s;
        struct sockaddr_can addr;
        struct ifreq ifr;
    
        s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    
        strcpy(ifr.ifr_name, "can0" );
        ioctl(s, SIOCGIFINDEX, &ifr);
    
        addr.can_family = AF_CAN;
        addr.can_ifindex = ifr.ifr_ifindex;
    
        bind(s, (struct sockaddr *)&addr, sizeof(addr));
    
        (..)
    
    

    要将套接字绑定到所有(!)CAN接口,接口索引必须
    为0(零)。在这种情况下,套接字从每个启用的CAN接口接收帧。如果接收的CAN接口,可以使用系统调用recvfrom(2)代替read(2)。发送给绑定到“任何”接口上的套接字,需要调用sendto(2)指定相应接口。

    从绑定的CAN_RAW套接字(参见上文)读取CAN帧包括读取一个can_frame结构:

    struct can_frame frame;
    
     nbytes = read(s, &frame, sizeof(struct can_frame));
    
     if (nbytes < 0) {
             perror("can raw socket read");
             return 1;
     }
    
     /* paranoid check ... */
     if (nbytes < sizeof(struct can_frame)) {
             fprintf(stderr, "read: incomplete CAN frame\n");
             return 1;
     }
    
     /* do something with the received CAN frame */
    

    CAN帧的写入通过使用write(2)系统调用完成:

    nbytes = write(s, &frame, sizeof(struct can_frame));
    

    当CAN接口绑定到“任何”现有CAN接口时
    (addr.can_ifindex = 0),如果需要原始CAN接口的信息推荐使用recvfrom(2):

        struct sockaddr_can addr;
        struct ifreq ifr;
        socklen_t len = sizeof(addr);
        struct can_frame frame;
    
        nbytes = recvfrom(s, &frame, sizeof(struct can_frame),
                          0, (struct sockaddr*)&addr, &len);
    
        /* get interface name of the received CAN frame */
        ifr.ifr_ifindex = addr.can_ifindex;
        ioctl(s, SIOCGIFNAME, &ifr);
        printf("Received a CAN frame from interface %s", ifr.ifr_name);
    

    要在绑定到“任意” CAN接口的套接字上写入CAN帧,必须明确定义传出接口。

        strcpy(ifr.ifr_name, "can0");
        ioctl(s, SIOCGIFINDEX, &ifr);
        addr.can_ifindex = ifr.ifr_ifindex;
        addr.can_family  = AF_CAN;
    
        nbytes = sendto(s, &frame, sizeof(struct can_frame),
                        0, (struct sockaddr*)&addr, sizeof(addr));
    

    读取来自套接字的消息后,可以通过ioctl(2)调用获得准确的时间戳:

        struct timeval tv;
        ioctl(s, SIOCGSTAMP, &tv);
    

    时间戳的分辨率为一微秒,并且会在接收CAN帧时自动设置。

    关于CAN FD(灵活数据速率-flexible data rate)支持的说明:

    通常,CAN FD的处理与先前描述的非常相似
    例子。支持CAN FD的新型CAN控制器支持两种不同
    CAN FD帧的仲裁阶段和有效负载阶段的比特率
    以及高达64字节的有效负载。有效载荷长度的延长打破了所有
    内核接口(ABI)严重依赖固定8个CAN帧
    有效负载的字节数(结构can_frame),例如CAN_RAW套接字。因此例如
    CAN_RAW套接字支持新的套接字选项CAN_RAW_FD_FRAMES
    将套接字切换为允许处理CAN FD帧的模式
    和(传统)CAN帧同时进行(请参阅第4.1.5节)。

    结构canfd_frame在include/linux/can.h中定义:

        struct canfd_frame {
                canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
                __u8    len;     /* frame payload length in byte (0 .. 64) */
                __u8    flags;   /* additional flags for CAN FD */
                __u8    __res0;  /* reserved / padding */
                __u8    __res1;  /* reserved / padding */
                __u8    data[64] __attribute__((aligned(8)));
        };
    

    struct canfd_frame和现有的struct can_frame具有can_id,
    有效载荷长度和有效载荷数据在其内部的相同偏移处
    结构。这允许处理非常相似的不同结构。
    将结构can_frame的内容复制到结构canfd_frame中时
    所有结构元素都可以按原样使用-只有data []可以扩展。

    当引入结构canfd_frame时,结果是数据长度
    can_frame的代码(DLC)被用作长度信息,因为
    长度,并且DLC在0 .. 8范围内具有1:1映射。
    长度信息的简单处理canfd_frame.len元素
    包含一个从0到64的普通长度值。因此canfd_frame.len和
    can_frame.can_dlc相等,并且包含长度信息且没有DLC。
    有关可区分CAN和CAN FD的设备以及
    到与总线相关的数据长度代码(DLC)的映射,请参见第6.6节。

    两个CAN(FD)帧结构的长度定义了最大传输
    CAN(FD)网络接口的单位(MTU)和skbuff数据长度。二
    在include/linux/can.h中为CAN特定的MTU指定了定义:

      #define CAN_MTU   (sizeof(struct can_frame))   == 16  => 'legacy' CAN frame
      #define CANFD_MTU (sizeof(struct canfd_frame)) == 72  => CAN FD frame
    

    4.1 带有can_filters(SOCK_RAW)的RAW协议套接字

    使用CAN_RAW套接字可与通常使用的套接字进行广泛比较
    对CAN字符设备的已知访问。迎接新的可能性
    由多用户SocketCAN方法提供,有些合理
    默认值是在RAW套接字绑定时设置的:

    -将过滤器设置为仅一个接收所有内容的过滤器
    -套接字仅接收有效的数据帧(=>没有错误消息帧)
    -已启用发送的CAN帧的环回(请参见第3.2章)
    -套接字不接收自己发送的帧(在环回模式下)

    这些默认设置可以在绑定套接字之前或之后进行更改。
    为CAN_RAW使用套接字选项的引用定义
    套接字,包括<linux / can / raw.h>。

    4.1.1 RAW套接字选项CAN_RAW_FILTER

    可以控制使用CAN_RAW套接字的CAN帧的接收
    通过使用CAN_RAW_FILTER套接字选项定义0 .. n过滤器。

    CAN过滤器结构在include / linux / can.h中定义:

        struct can_filter {
                canid_t can_id;
                canid_t can_mask;
        };
    
    

    过滤条件匹配

        <received_can_id>和mask == can_id和mask
    

    与已知的CAN控制器硬件过滤器语义类似。
    当CAN_INV_FILTER处于该语义时,过滤器可以反转
    在can_filter结构的can_id元素中设置该位。在
    与CAN控制器硬件滤波器相反,用户可以将0设置为n
    分别为每个打开的插座接收过滤器:

        struct can_filter rfilter[2];
    
        rfilter[0].can_id   = 0x123;
        rfilter[0].can_mask = CAN_SFF_MASK;
        rfilter[1].can_id   = 0x200;
        rfilter[1].can_mask = 0x700;
    
        setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));
    

    要在选定的CAN_RAW套接字上禁用CAN帧的接收,请执行以下操作:

    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
    

    将过滤器设置为零过滤器已经过时,无法读取
    数据导致原始套接字丢弃接收到的CAN帧。但
    具有“仅发送”用例的情况下,我们可以在
    内核可以节省一点(真的很少!)的CPU使用率。

    4.1.1.1 CAN过滤器使用优化

    CAN过滤器在CAN帧的每个设备的过滤器列表中进行处理
    接待时间。减少需要执行的检查数量
    遍历过滤器列表时,CAN内核提供了优化的
    过滤器订阅集中于单个CAN ID时的过滤器处理。

    对于可能的2048个SFF CAN标识符,该标识符用作索引
    无需进一步检查即可访问相应的订阅列表。
    对于2 ^ 29个可能的EFF CAN标识符,将10位XOR折叠用作
    散列函数检索EFF表索引。

    为了受益于针对单个CAN标识符的优化过滤器,
    必须将CAN_SFF_MASK或CAN_EFF_MASK一起设置到can_filter.mask中
    设置了CAN_EFF_FLAG和CAN_RTR_FLAG位。设置中的CAN_EFF_FLAG位
    can_filter.mask清楚表明SFF或EFF CAN ID是否重要
    已订阅。例如上面的例子

    rfilter [0] .can_id = 0x123;
    rfilter [0] .can_mask = CAN_SFF_MASK;
    

    CAN ID 0x123的SFF帧和0xXXXXX123的EFF帧都可以通过。

    要仅过滤0x123(SFF)和0x12345678(EFF)CAN标识符,
    必须以这种方式定义过滤器,以从优化的过滤器中受益:

    struct can_filter rfilter [2];
    
    rfilter [0] .can_id = 0x123;
    rfilter [0] .can_mask =(CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_SFF_MASK);
    rfilter [1] .can_id = 0x12345678 | CAN_EFF_FLAG;
    rfilter [1] .can_mask =(CAN_EFF_FLAG | CAN_RTR_FLAG | CAN_EFF_MASK);
    
    setsockopt(s,SOL_CAN_RAW,CAN_RAW_FILTER,&rfilter,sizeof(rfilter));
    

    4.1.2 RAW套接字选项CAN_RAW_ERR_FILTER

    如3.3章所述,CAN接口驱动程序可以生成
    称为错误消息帧,可以选择将其传递给用户
    与其他CAN框架相同的应用方式。可能的
    错误分为可以过滤的不同错误类别
    使用适当的错误掩码。报名参加
    错误条件CAN_ERR_MASK可用作错误掩码的值。
    错误掩码的值在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));
    

    4.1.3 RAW套接字选项CAN_RAW_LOOPBACK

    为了满足多用户需求,默认情况下启用本地环回
    (有关详细信息,请参见第3.2章)。但是在某些嵌入式用例中
    (例如,当只有一个应用程序使用CAN总线时)此环回
    可以禁用功能(每个插槽分别禁用):

    int环回= 0; / * 0 =禁用,1 =启用(默认)* /
    
    setsockopt(s,SOL_CAN_RAW,CAN_RAW_LOOPBACK,&loopback,sizeof(loopback));
    

    4.1.4 RAW套接字选项CAN_RAW_RECV_OWN_MSGS

    启用本地环回后,所有发送的CAN帧都将
    循环回到为CAN注册的开放式CAN插座
    该给定接口上的帧的CAN-ID,以满足多用户
    需要。在同一插座上接收CAN帧
    发送CAN帧被认为是不必要的,因此
    默认禁用。此默认行为可能会在
    需求:

    int recv_own_msgs = 1; / * 0 =禁用(默认),1 =启用* /
    
    setsockopt(s,SOL_CAN_RAW,CAN_RAW_RECV_OWN_MSGS,
               &recv_own_msgs,sizeof(recv_own_msgs));
    

    4.1.5 RAW套接字选项CAN_RAW_FD_FRAMES

    可以使用新的套接字选项启用CAN_RAW套接字中的CAN FD支持
    CAN_RAW_FD_FRAMES默认情况下处于关闭状态。当新的套接字选项为
    CAN_RAW套接字不支持(例如,在较旧的内核上),请切换
    CAN_RAW_FD_FRAMES选项返回错误-ENOPROTOOPT。

    启用CAN_RAW_FD_FRAMES后,应用程序可以发送两个CAN帧
    和CAN FD框架。OTOH应用程序必须处理CAN和CAN FD帧
    从套接字读取时。

    启用CAN_RAW_FD_FRAMES:允许CAN_MTU和CANFD_MTU
    CAN_RAW_FD_FRAMES禁用:仅允许CAN_MTU(默认)
    

    例:
    [记住:CANFD_MTU == sizeof(struct canfd_frame)]

     struct canfd_frame cfd;
    
     nbytes = read(s, &cfd, CANFD_MTU);
    
     if (nbytes == CANFD_MTU) {
             printf("got CAN FD frame with length %d\n", cfd.len);
         /* cfd.flags contains valid data */
     } else if (nbytes == CAN_MTU) {
             printf("got legacy CAN frame with length %d\n", cfd.len);
         /* cfd.flags is undefined */
     } else {
             fprintf(stderr, "read: invalid CAN(FD) frame\n");
             return 1;
     }
    
     /* the content can be handled independently from the received MTU size */
    
     printf("can_id: %X data length: %d data: ", cfd.can_id, cfd.len);
     for (i = 0; i < cfd.len; i++)
             printf("%02X ", cfd.data[i]);
    

    以CANFD_MTU大小读取时,仅返回具有以下内容的CAN_MTU字节:
    从套接字收到的旧CAN帧已被读入
    提供的CAN FD结构。请注意,canfd_frame.flags数据字段为
    未在struct can_frame中指定,因此仅在
    CANFD_MTU大小的CAN FD帧。

    新的CAN应用的实现提示:

    要构建支持CAN FD的应用程序,请使用struct canfd_frame作为基本CAN
    基于CAN_RAW的应用程序的数据结构。当应用程序是
    在较旧的Linux内核上执行并切换CAN_RAW_FD_FRAMES
    套接字选项返回错误:没问题。您将获得传统的CAN框架
    或CAN FD帧,并可以以相同方式处理它们。

    发送到CAN设备时,请确保该设备能够处理
    通过检查设备最大传输单位是否为CANFD_MTU来CAN FD帧。
    可以使用SIOCGIFMTU ioctl()系统调用来检索CAN设备MTU。

    4.1.6 RAW套接字选项CAN_RAW_JOIN_FILTERS

    CAN_RAW套接字可以设置多个CAN标识符特定的过滤器,这些过滤器
    在af_can.c过滤器处理中导致多个过滤器。这些过滤器
    彼此独立,这会导致逻辑“或”过滤器
    应用(请参阅4.1.1)。

    此套接字选项以仅CAN的方式加入给定的CAN过滤器
    帧被传递给与所有给定的CAN过滤器匹配的用户空间。的
    因此,所应用过滤器的语义更改为逻辑与。

    这在过滤器集为过滤器组合时特别有用
    设置CAN_INV_FILTER标志以对单个CAN ID进行标记或
    CAN ID范围从传入流量开始。

    4.1.7 RAW套接字返回的消息标志

    使用recvmsg()调用时,msg-> msg_flags可能包含以下标志:

    MSG_DONTROUTE:在本地主机上创建接收到的帧时设置。
    
    MSG_CONFIRM:设置何时通过套接字发送帧。
      该标志可以解释为“传输确认”
      CAN驱动程序在驱动程序级别支持帧的回显,请参见3.2和6.2。
      为了接收此类消息,必须设置CAN_RAW_RECV_OWN_MSGS。
    

    4.2 广播管理器协议套接字(SOCK_DGRAM)

    广播管理器协议提供基于命令的配置
    接口在内核空间中过滤和发送(例如循环)CAN消息。

    接收过滤器可以用来减少对频繁消息的采样;检测事件
    例如消息内容更改,数据包长度更改和超时
    监视收到的消息。

    CAN帧或一系列CAN帧的定期传输任务可以是
    在运行时创建和修改;消息内容和两者
    可能的发送间隔可以更改。

    BCM插座不适用于使用
    从CAN_RAW套接字知道的struct can_frame。而是一个特殊的BCM
    配置消息已定义。使用的基本BCM配置消息
    与广播管理器进行通信,可用的操作是
    在linux / can / bcm.h中定义。BCM消息包含
    带有命令(“操作码”)的消息头,后跟零个或多个CAN帧。
    广播管理器以以下形式将响应发送到用户空间:

    struct bcm_msg_head {
            __u32操作码; / *命令* /
            __u32标志;/ *特殊标志* /
            __u32计数;/ *使用ival1运行“计数”时间* /
            struct timeval ival1,ival2; / *计数和后续间隔* /
            canid_t can_id; / *任务的唯一can_id * /
            __u32个nframe;/ *以下* /的can_frames数
            struct can_frame框架[0];
    };
    

    对齐的有效载荷“帧”使用定义的相同基本CAN帧结构
    在第4节的开头和include / linux / can.h中包含。所有
    从用户空间发送到广播管理器的消息具有此结构。

    请注意,必须连接CAN_BCM套接字,而不是在套接字之后绑定
    创建(没有错误检查的示例):

    int s;
    struct sockaddr_can addr;
    struct ifreq ifr;
    
    s =套接字(PF_CAN,SOCK_DGRAM,CAN_BCM);
    
    strcpy(ifr.ifr_name,“ can0”);
    ioctl(s,SIOCGIFINDEX,&ifr);
    
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    
    connect(s,(struct sockaddr *)&addr,sizeof(addr));
    
    (..)
    

    广播管理器套接字能够处理任何数量的飞行中
    同时传输或接收过滤器。不同的RX / TX作业是
    通过每个BCM消息中的唯一can_id进行区分。但是额外
    建议使用CAN_BCM套接字在多个CAN接口上进行通信。
    当广播管理器套接字绑定到“任何” CAN接口(=>
    接口索引设置为零),已配置的接收过滤器适用于任何
    CAN接口,除非使用sendto()系统调用否决了“ any” CAN
    接口索引。使用recvfrom()而不是read()检索BCM时
    can_ifindex中提供了原始CAN接口的套接字消息。

    4.2.1广播管理器操作

    操作码定义了广播管理器执行的操作,
    或详细说明广播经理对多个事件的响应,包括
    用户请求。

    传输操作(用户空间到广播管理器):

    TX_SETUP:创建(循环)传输任务。
    
    TX_DELETE:删除(循环)传输任务,仅需要can_id。
    
    TX_READ:读取can_id的(循环)传输任务的属性。
    
    TX_SEND:发送一个CAN帧。
    

    传输响应(广播管理器到用户空间):

    TX_STATUS:回复TX_READ请求(传输任务配置)。
    
    TX_EXPIRED:计数器以初始间隔完成发送时通知
      'ival1'。需要将TX_COUNTEVT标志设置为TX_SETUP。
    

    接收操作(广播管理器的用户空间):

    RX_SETUP:创建RX内容过滤器订阅。
    
    RX_DELETE:删除RX内容过滤器订阅,仅要求can_id。
    
    RX_READ:读取can_id的RX内容过滤器订阅的属性。
    

    接收响应(广播管理器到用户空间):

    RX_STATUS:回复RX_READ请求(过滤器任务配置)。
    
    RX_TIMEOUT:检测到缺少循环消息(定时器ival1到期)。
    
    RX_CHANGED:具有更新的CAN帧的BCM消息(检测到的内容更改)。
      在收到第一条消息或收到修订的CAN消息时发送。
    

    4.2.2广播管理器消息标志

    向广播管理器发送消息时,“标志”元素可能会
    包含以下影响行为的标志定义:

    SETTIMER:设置ival1,ival2和count的值
    
    STARTTIMER:使用ival1,ival2的实际值启动计时器
      并数。同时启动计时器会导致发出CAN帧。
    
    TX_COUNTEVT:计数到期时创建消息TX_EXPIRED
    
    TX_ANNOUNCE:进程发出的数据更改立即发出。
    
    TX_CP_CAN_ID:将can_id从消息头复制到每个
      后续帧。这是为了简化使用。对于
      TX任务的消息标头中的唯一can_id可能与
      存储的can_id用于在后续结构can_frame中传输。
    
    RX_FILTER_ID:仅通过can_id进行过滤,不需要帧(nframes = 0)。
    
    RX_CHECK_DLC:DLC的更改导致RX_CHANGED。
    
    RX_NO_AUTOTIMER:防止自动启动超时监视器。
    
    RX_ANNOUNCE_RESUME:如果在RX_SETUP传递并且发生接收超时,则
      (循环)接收重新启动时,将生成RX_CHANGED消息。
    
    TX_RESET_MULTI_IDX:重置多帧传输的索引。
    
    RX_RTR_FRAME:发送对RTR请求的答复(置于op-> frames [0]中)。
    

    4.2.3广播管理器传输计时器

    定期传输配置最多可以使用两个间隔计时器。
    在这种情况下,BCM每隔一段时间发送一条消息(“计数”)
    'ival1',然后继续以另一个给定的间隔'ival2'发送。什么时候
    仅需要一个计时器,“计数”设置为零,仅使用“ ival2”。
    当设置了SET_TIMER和START_TIMER标志时,定时器被激活。
    仅设置SET_TIMER时,可以在运行时更改计时器值。

    4.2.4广播管理器消息序列传输

    在循环的情况下,最多可以顺序发送256个CAN帧
    TX任务配置。CAN帧的数量在“ nframes”中提供
    BCM消息头的元素。添加定义数量的CAN帧
    作为TX_SETUP BCM配置消息的数组。

    / *创建一个结构以设置四个CAN帧的序列* /
    结构{
            struct bcm_msg_head msg_head;
            struct can_frame frame [4];
    } mytxmsg;
    
    (..)
    mytxmsg.msg_head.nframes = 4;
    (..)
    
    write(s,&mytxmsg,sizeof(mytxmsg));
    

    每次传输时,CAN帧阵列中的索引都会增加
    并在索引溢出时设置为零。

    4.2.5广播管理器接收过滤器计时器

    定时器值ival1或ival2可以在RX_SETUP设置为非零值。
    设置SET_TIMER标志后,将启用计时器:

    ival1:当未在此时间内再次收到收到的消息时,发送RX_TIMEOUT
    给定的时间。当START_TIMER设置为RX_SETUP时,超时检测
    直接激活-即使以前没有CAN帧接收。

    ival2:将接收到的消息速率降低到ival2的值。这个
    当内部的信号减少时,对于减少应用程序的消息很有用
    由于ival2周期内的状态变化可能会导致CAN帧无状态
    丢失。

    4.2.6广播管理器多路消息接收过滤器

    为了过滤多路复用消息序列中的内容更改,可以使用更多的数组
    RX_SETUP配置消息中可以传递一个以上的CAN帧。的
    第一个CAN帧的数据字节包含相关位的掩码
    必须在随后的CAN帧中将其与接收到的CAN帧进行匹配。
    如果后续CAN帧之一与该帧数据中的位匹配
    标记要与先前接收到的内容进行比较的相关内容。
    多达257个CAN帧(复用滤波器位掩码CAN帧加上256个CAN
    过滤器)可以作为数组添加到TX_SETUP BCM配置消息中。

    / *通常用于清除CAN帧数据[]-注意字节序问题!* /
    #定义U64_DATA(p)(*(无符号长长*)(p)->数据)
    
    结构{
            struct bcm_msg_head msg_head;
            struct can_frame frame [5];
    } msg;
    
    msg.msg_head.opcode = RX_SETUP;
    msg.msg_head.can_id = 0x42;
    msg.msg_head.flags = 0;
    msg.msg_head.nframes = 5;
    U64_DATA(&msg.frame [0])= 0xFF00000000000000ULL; / * MUX掩码* /
    U64_DATA(&msg.frame [1])= 0x01000000000000FFULL; / *数据掩码(MUX 0x01)* /
    U64_DATA(&msg.frame [2])= 0x0200FFFF000000FFULL; / *数据掩码(MUX 0x02)* /
    U64_DATA(&msg.frame [3])= 0x330000FFFFFF0003ULL; / *数据掩码(MUX 0x33)* /
    U64_DATA(&msg.frame [4])= 0x4F07FC0FF0000000ULL; / *数据掩码(MUX 0x4F)* /
    
    写(s,&msg,sizeof(msg));
    

    4.2.7广播管理器CAN FD支持

    CAN_BCM的编程API取决于struct can_frame,即
    以数组形式直接位于bcm_msg_head结构后面。遵循这个
    CAN FD的架构在bcm_msg_head中构造一个新标志'CAN_FD_FRAME'
    标志指示连接后的CAN帧结构
    bcm_msg_head定义为struct canfd_frame。

    结构{
            struct bcm_msg_head msg_head;
            struct canfd_frame frame [5];
    } msg;
    
    msg.msg_head.opcode = RX_SETUP;
    msg.msg_head.can_id = 0x42;
    msg.msg_head.flags = CAN_FD_FRAME;
    msg.msg_head.nframes = 5;
    (..)
    

    使用CAN FD帧进行多重过滤时,MUX掩码仍然
    预期在struct canfd_frame数据部分的前64位中使用。

    4.3连接的传输协议(SOCK_SEQPACKET)
    4.4未连接的传输协议(SOCK_DGRAM)

    1. SocketCAN核心模块

    SocketCAN核心模块实现了协议系列
    PF_CAN。CAN协议模块由核心模块加载在
    运行。核心模块为CAN协议提供接口
    用于订阅所需的CAN ID的模块(请参阅第3.1章)。

    5.1 can.ko模块参数

    -stats_timer:计算SocketCAN核心统计信息
    (例如,当前/每秒最大帧数)此1秒计时器为
    默认情况下在can.ko模块启动时间调用。这个定时器可以是
    通过在模块命令行上使用stattimer = 0禁用此功能。

    -调试:(自SocketCAN SVN r546后删除)

    5.2内容

    如第3.1章所述,SocketCAN内核使用多个过滤器
    列表以将接收到的CAN帧传送到CAN协议模块 这些
    接收列表,其过滤器和过滤器匹配项的数量可以是
    在相应的接收列表中检查。所有条目均包含
    设备和协议模块标识符:

    foo @ bar:〜$ cat / proc / net / can / rcvlist_all
    
    接收列表“ rx_all”:
      (vcan3:无条目)
      (vcan2:无条目)
      (vcan1:无条目)
      设备can_id can_mask函数userdata与ident匹配
       vcan0 000 00000000 f88e6370 f6c6f400 0原始
      (任何:无条目)
    

    在此示例中,应用程序从vcan0请求任何CAN通信。

    rcvlist_all-未过滤条目的列表(无过滤操作)
    rcvlist_eff-单扩展帧(EFF)条目的列表
    rcvlist_err-错误消息框架掩码列表
    rcvlist_fil-掩码/值过滤器的列表
    rcvlist_inv-掩码/值过滤器的列表(反语义)
    rcvlist_sff-单个标准框架(SFF)条目的列表
    

    / proc / net / can中的其他procfs文件

    统计-SocketCAN核心统计信息(rx / tx帧,匹配率等)
    reset_stats-手动统计重置
    版本-打印SocketCAN核心版本和ABI版本
    

    5.3编写自己的CAN协议模块

    要在协议系列PF_CAN中实现新协议,
    协议必须在include / linux / can.h中定义。
    使用SocketCAN内核的原型和定义可以是
    通过包括include / linux / can / core.h访问。
    除了注册CAN协议和
    CAN设备通知程序链具有订阅CAN的功能
    CAN接口接收并发送CAN帧的帧:

    can_rx_register-从特定接口订阅CAN帧
    can_rx_unregister-从特定接口退订CAN帧
    can_send-传输CAN帧(本地回送可选)
    

    有关详细信息,请参见net / can / af_can.c中的kerneldoc文档或
    net / can / raw.c或net / can / bcm.c的源代码。

    1. CAN网络驱动程序

    编写CAN网络设备驱动程序比编写
    CAN字符设备驱动程序。类似于其他已知的网络设备
    您主要需要处理的驱动程序:

    -TX:将CAN帧从套接字缓冲区放到CAN控制器。
    -RX:将CAN框架中的CAN帧放入套接字缓冲区。

    参见例如Documentation / networking / netdevices.txt。差异
    下面介绍用于编写CAN网络设备驱动程序的方法:

    6.1常规设置

    dev->类型= ARPHRD_CAN; / *网络设备硬件类型* /
    dev->标志= IFF_NOARP; / * CAN没有arp * /
    
    dev-> mtu = CAN_MTU; / * sizeof(struct can_frame)->旧版CAN接口* /
    
    或替代方案,当控制器以灵活的数据速率支持CAN时:
    dev-> mtu = CANFD_MTU; / * sizeof(struct canfd_frame)-> CAN FD接口* /
    

    struct can_frame或struct canfd_frame是每个套接字的有效负载
    协议系列PF_CAN中的缓冲区(skbuff)。

    6.2发送帧的本地环回

    如第3.2章所述,CAN网络设备驱动程序应
    支持类似于本地回显的本地回送功能
    例如tty设备。在这种情况下,驱动程序标志IFF_ECHO必须为
    设置为防止PF_CAN内核本地回显已发送的帧
    (又名环回)作为后备解决方案:

    dev-> flags =(IFF_NOARP | IFF_ECHO);
    

    6.3 CAN控制器硬件过滤器

    为了减少深度嵌入式系统上的中断负载,某些CAN
    控制器支持CAN ID或CAN ID范围的过滤。
    这些硬件过滤器功能因控制器而异
    控制器,必须将其标识为在多用户中不可行
    网络方法。特定于控制器的使用
    硬件过滤器在非常专用的用例中可能有意义,因为
    驱动程序级别的过滤器将影响多用户中的所有用户
    系统。PF_CAN内核内部的高效滤波器组允许
    为每个插槽分别设置不同的多个过滤器。
    因此,硬件过滤器的使用属于“手工制造”类别。
    在深度嵌入式系统上进行调整”。作者正在运行MPC603e
    @ 133MHz,带有2002年起在重型总线下的四个SJA1000 CAN控制器
    加载没有任何问题...

    6.4虚拟CAN驱动程序(vcan)

    与网络环回设备类似,vcan提供虚拟本地
    CAN接口。CAN上的完整合格地址包括

    -唯一的CAN标识符(CAN ID)
    -传输此CAN ID的CAN总线(例如can0)

    因此在通常的使用情况下,需要多个虚拟CAN接口。

    虚拟CAN接口允许发送和接收CAN
    没有真正的CAN控制器硬件的帧。虚拟CAN网络
    设备通常被命名为“ vcanX”,例如vcan0 vcan1 vcan2 ...
    当编译为模块时,虚拟CAN驱动程序模块称为vcan.ko

    从Linux Kernel 2.6.24版本开始,vcan驱动程序支持Kernel
    netlink接口可创建vcan网络设备。创作和
    可以使用ip(8)工具管理vcan网络设备的删除:

    -创建虚拟CAN网络接口:
    $ ip链接添加类型vcan

    -使用特定名称“ vcan42”创建虚拟CAN网络接口:
    $ ip link add dev vcan42类型vcan

    -删除(虚拟CAN)网络接口“ vcan42”:
    $ ip link del vcan42

    6.5 CAN网络设备驱动程序接口

    CAN网络设备驱动程序接口提供通用接口
    设置,配置和监视CAN网络设备。用户然后可以
    通过以下方式配置CAN设备,例如设置位定时参数
    使用来自“ IPROUTE2”的程序“ ip”的netlink接口
    实用套件。以下章节简要描述了如何使用它。
    此外,该接口使用通用数据结构并导出
    一组通用功能,所有真正的CAN网络设备驱动程序
    应该使用。请看一下SJA1000或MSCAN驱动程序
    了解如何使用它们。模块的名称为can-dev.ko。

    6.5.1 Netlink界面,用于设置/获取设备属性

    必须通过netlink接口配置CAN设备。支持的
    netlink消息类型在下面定义和简要描述
    “ include / linux / can / netlink.h”。CAN链接支持程序“ ip”
    IPROUTE2实用程序套件的版本可用,可以如下所示使用
    下面:

    -设置CAN设备属性:

    $ ip link set can0类型可以帮助
    用法:ip link设置DEVICE类型即可
        [比特率BITRATE [采样点采样点]] |
        [tq TQ prop-seg PROP_SEG相位-seg1 PHASE-SEG1
          phase-seg2 PHASE-SEG2 [sjw SJW]]
    
        [dbitrate BITRATE [dsample-point SAMPLE-POINT]] |
        [dtq TQ dprop-seg PROP_SEG dphase-seg1 PHASE-SEG1
          dphase-seg2 PHASE-SEG2 [dsjw SJW]]
    
        [回送{ 关闭}]
        [仅监听{ 关闭}]
        [三重采样{ 关闭}]
        [单拍{ 关闭}]
        [berr-reporting {on | 关闭}]
        [fd { 关闭}]
        [fd-non-iso {上| 关闭}]
        [presume-ack {on | 关闭}]
    
        [restart-ms TIME-MS]
        [ 重新开始 ]
    
        其中:比特率:= {1..1000000}
               样点:= {0.000..0.999}
               TQ:= {NUMBER}
               PROP-SEG:= {1..8}
               阶段SEG1:= {1..8}
               阶段SEG2:= {1..8}
               SJW:= {1..4}
               重新启动MS:= {0 | NUMBER}
    

    -显示CAN设备的详细信息和统计信息:

    $ ip -details -statistics链接显示can0
    2:can0:<NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast状态UP qlen 10
      链接/可以
      可以<TRIPLE-SAMPLING>状态ERROR-ACTIVE restart-ms 100
      比特率125000 sample_point 0.875
      tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
      sja1000:tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
      时钟8000000
      重新启动总线错误仲裁丢失错误警告错误传递总线关闭
      41 17457 0 41 42 41
      RX:字节数据包错误丢弃了溢出mcast
      140859 17608 17457 0 0 0
      TX:字节数据包错误掉落载波冲突
      861 112 0 41 0 0
    

    以上输出的更多信息:

    “ <三重采样>”
    显示选定的CAN控制器模式的列表:LOOPBACK,
    仅侦听或三重采样。
    
    “状态错误有效”
    CAN控制器的当前状态:“ ERROR-ACTIVE”,
    “错误警告”,“被动错误”,“关闭”或“已停止”
    
    “重新启动毫秒数100”
    自动重启延迟时间。如果设置为非零值,则
    CAN控制器的重启将自动触发
    如果在指定的延迟时间后出现总线关闭状态
    以毫秒为单位。默认情况下它是关闭的。
    
    “比特率125000采样点0.875”
    显示以位/秒为单位的实际比特率,并以
    范围0.000..0.999。如果计算位定时参数
    在内核中启用(CONFIG_CAN_CALC_BITTIMING = y),
    可以通过设置“ bitrate”参数来定义位定时。
    可以选择指定“采样点”。默认情况下
    假设CIA推荐的采样点为0.000。
    
    “ tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1”
    显示以ns为单位的时间量,传播段,相位缓冲器
    段1和2以及同步跳跃宽度,单位为
    tq。它们允许在硬件中定义CAN位定时
    博世CAN 2.0规范提出的独立格式(请参阅
    http://www.semiconductors.bosch.de/pdf/can2spec.pdf的第8章)。
    
    “ sja1000:tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
     时钟8000000“
    显示CAN控制器的位定时常数,此处
    “ sja1000”。时间段1的最小值和最大值
    和2,同步跳变宽度以tq为单位,
    比特率预分频器和CAN系统时钟频率(以Hz为单位)。
    这些常量可用于用户定义的(非标准)
    用户空间中的位定时计算算法。
    
    “重新启动总线错误仲裁丢失错误警告错误传递总线关闭”
    显示重启次数,总线和仲裁丢失错误,
    状态更改为错误警告,错误被动和
    总线关闭状态。RX超限错误列在“超限”中
    标准网络统计信息的字段。
    

    6.5.2设置CAN位定时

    CAN位定时参数始终可以在硬件中定义
    博世CAN 2.0规范中提出的独立格式
    指定参数“ tq”,“ prop_seg”,“ phase_seg1”,“ phase_seg2”
    和“ sjw”:

    $ ip link set canX type can tq 125 prop-seg 6 \
                相段1 7相段2 2
    

    如果启用了内核选项CONFIG_CAN_CALC_BITTIMING,则CIA
    如果以下位将计算推荐的CAN位定时参数:
    rate由参数“ bitrate”指定:

    $ ip link set canX type can bitrate 125000
    

    请注意,这对于带有
    标准比特率,但对于外来比特率或CAN系统可能会“失败”
    时钟频率。禁用CONFIG_CAN_CALC_BITTIMING可节省一些
    空间,并允许用户空间工具单独确定和设置
    位定时参数。CAN控制器特定的位时序
    常数可以用于此目的。它们由
    以下命令:

    $ ip -details链接显示can0
    ...
      sja1000:时钟8000000 tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
    

    6.5.3启动和停止CAN网络设备

    使用以下命令照常启动或停止CAN网络设备
    “ ifconfig canX up / down”或“ ip链接设置canX up / down”。意识到
    必须为真实的CAN设备定义适当的位定时参数
    在开始它之前,避免容易出错的默认设置:

    $ ip link set canX up type can bitrate 125000
    

    如果设备上发生太多错误,则设备可能会进入“总线断开”状态
    CAN总线。然后,不再接收或发送任何消息。自动
    可以通过将“ restart-ms”设置为
    非零值,例如:

    $ ip link set canX类型可以重新启动-ms 100
    

    或者,应用程序可以实现“下车”条件
    通过监视CAN错误消息帧并在以下情况下重新启动
    适用于以下命令:

    $ ip link set canX类型可以重新启动
    

    请注意,重新启动还会创建CAN错误消息帧(请参见
    以及第3.3章)。

    6.6 CAN FD(灵活数据速率)驱动程序支持

    支持CAN FD的CAN控制器支持两种不同的比特率
    CAN FD帧的仲裁阶段和有效负载阶段。因此
    为了启用CAN FD比特率,必须指定第二个比特时序。

    此外,具有CAN FD功能的CAN控制器最多支持64个字节的
    有效载荷。在can_frame.can_dlc和
    canfd_frame.len用于用户空间应用程序和Linux网络内部
    层是从0到64的纯值,而不是CAN“数据长度代码”。
    数据长度代码是1:1映射到旧版中的有效负载长度
    仍然可以使用CAN帧。与总线相关的DLC映射的有效负载长度为
    仅在CAN驱动程序中执行,最好在辅助程序中执行
    函数can_dlc2len()和can_len2dlc()。

    网络可以区分CAN netdevice驱动程序功能
    设备最大传输单位(MTU):

    MTU = 16(CAN_MTU)=> sizeof(struct can_frame)=>'传统'CAN设备
    MTU = 72(CANFD_MTU)=> sizeof(struct canfd_frame)=>支持CAN FD的设备

    可以使用SIOCGIFMTU ioctl()系统调用来检索CAN设备MTU。
    NB支持CAN FD的设备还可以处理和发送旧版CAN帧。

    配置支持CAN FD的CAN控制器时,附加的“数据”比特率
    必须设置。CAN FD帧数据阶段的比特率必须为
    至少是为仲裁阶段配置的比特率。这个
    第二个比特率指定为与第一个比特率类似,但该比特率
    为“数据”比特率设置关键字以“ d”开头,例如dbitrate,
    dsample-point,dsjw或dtq和类似设置。设置数据比特率
    在配置过程中,控制器选项“ fd on”可以是
    指定在CAN控制器中启用CAN FD模式。这个控制器
    选项还将设备MTU切换为72(CANFD_MTU)。

    在国际上以白皮书形式提出的第一个CAN FD规范
    由于数据完整性的原因,需要改进CAN Conference 2012。
    因此,今天必须区分两种CAN FD实现:

    -符合ISO标准:ISO 11898-1:2015 CAN FD实施(默认)
    -不符合ISO:2012年白皮书之后的CAN FD实施

    最后,有三种类型的CAN FD控制器:

    1.符合ISO(固定)
    2.不符合ISO标准(已修复,例如m_can.c中的M_CAN IP核心v3.0.1)

    1. ISO /非ISO CAN FD控制器(可切换,例如PEAK PCAN-USB FD)

    当前的ISO /非ISO模式由CAN控制器驱动程序通过
    网络链接,并通过“ ip”工具显示(控制器选项FD-NON-ISO)。
    可以通过将“ fd-non-iso {on | off}”设置为来更改ISO /非ISO模式。
    仅可切换的CAN FD控制器。

    配置500 kbit / s仲裁比特率和4 Mbit / s数据比特率的示例:

    $ ip link set can0 up type can bitrate 500000 sample-point 0.75 \
                                   dbitrate 4000000 dsample-point 0.8 fd on
    $ ip -details链接显示can0
    5:can0:<NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast状态未知
             模式DEFAULT组默认qlen 10
    链接/可以滥交0
    可以<FD>状态ERROR_ACTIVE(berr-counter tx 0 rx 0)restart-ms 0
          比特率500000采样点0.750
          tq 50 prop-seg 14 phase-seg1 15 phase-seg2 10 sjw 1
          pcan_usb_pro_fd:tseg1 1..64 tseg2 1..16 sjw 1..16 brp 1..1024 \
          brp-inc 1
          比特率4000000 d采样点0.800
          dtq 12 dprop-seg 7 dphase-seg1 8 dphase-seg2 4 dsjw 1
          pcan_usb_pro_fd:dtseg1 1..16 dtseg2 1..8 dsjw 1..4 dbrp 1..1024 \
          dbrp-inc 1
          时钟80000000
    

    在此可切换CAN FD适配器上添加“ fd-non-iso on”的示例:
    可以<FD,FD-NON-ISO>状态ERROR-ACTIVE(berr-counter tx 0 rx 0)restart-ms 0

    6.7支持的CAN硬件

    请检查"drivers/net/can"中的"Kconfig" 文件以获取实际支持的CAN硬件列表信息。在SocketCAN项目网站上
    (请参见第7章)有更多包扩较旧的内核版本驱动。

    1. SocketCAN资源

    Linux CAN / SocketCAN项目资源(项目站点/邮件列表)
    在Linux源代码树的MAINTAINERS文件中被引用。
    搜索CAN NETWORK [LAYERS | DRIVERS]。

    8.鸣谢(Credits)

    Oliver Hartkopp(PF_CAN内核,过滤器,驱动程序,bcm,SJA1000驱动程序)
    Urs Thuermann(PF_CAN内核,内核集成,套接字接口,原始,vcan)
    Jan Kizka(RT-SocketCAN内核,Socket-API协调)
    Wolfgang Grandegger(RT-SocketCAN内核和驱动程序,Raw Socket-API评论,
    CAN设备驱动程序接口,MSCAN驱动程序)
    Robert Schwebel(设计评论,PTXdist集成)
    Marc Kleine-Budde(设计审查,内核2.6清理,驱动程序)
    贝内迪克特·斯潘杰(评论)
    Thomas Gleixner(LKML评论,编码风格,发布提示)
    Andrey Volkov(内核子树结构,ioctl,MSCAN驱动程序)
    Matthias Brukner(第一个SJA1000 CAN网络设备实施方案,2003年第二季度)
    Klaus Hitschler(PEAK驱动程序集成)
    Uwe Koppe(采用PF_PACKET方法的CAN网络设备)
    Michael Schulze(驱动程序层环回要求,RT CAN驱动程序审查)
    Pavel Pisa(位时序计算)
    Sascha Hauer(SJA1000平台驱动程序)
    Sebastian Haas(SJA1000 EMS PCI驱动程序)
    Markus Plessing(SJA1000 EMS PCI驱动程序)
    每个达伦(SJA1000 Kvaser PCI驱动程序)
    Sam Ravnborg(评论,编码样式,kbuild帮助)

    https://elinux.org/CAN_Bus
    https://github.com/linux-can/can-utils
    https://www.kernel.org/doc/Documentation/networking/can.txt
    ============================================================================

    相关文章

      网友评论

          本文标题:Linux SocketCAN说明文档-can.txt

          本文链接:https://www.haomeiwen.com/subject/ktjtjhtx.html