Linux SocketCAN说明文档-can.txt

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
============================================================================

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 201,924评论 5 474
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,781评论 2 378
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 148,813评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,264评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,273评论 5 363
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,383评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,800评论 3 393
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,482评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,673评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,497评论 2 318
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,545评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,240评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,802评论 3 304
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,866评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,101评论 1 258
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,673评论 2 348
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,245评论 2 341

推荐阅读更多精彩内容