本文为控制器局域网协议系列(又名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。
- 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)
- 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的源代码。
- 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)
- 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章)有更多包扩较旧的内核版本驱动。
- 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
============================================================================