Linux内核Socket CAN中文文档 联系客服

发布时间 : 星期六 文章Linux内核Socket CAN中文文档更新完毕开始阅读c7eae43b5a8102d276a22f91

在本地回环功能开启的情况下,所有的发送帧都会被回环到在相应CAN接口上注册了同样CAN-ID(和发送帧的相同)的套接字上。发送CAN帧的套接字被假设不想接收自己发送的CAN帧,因此在发送套接字上的回环功能默认是关闭的。可以在需要的时候改变这一默认行为:

int recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */

setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &recv_own_msgs, sizeof(recv_own_msgs));

(yll:下面三小节没有内容)

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

-----------------------------------------------

4.3 面向连接的传输协议 (SOCK_SEQPACKET) ----------------------------------------------------

4.4 无连接的传输协议 (SOCK_DGRAM)

---------------------------------------------

5. Socket CAN核心模块 ==============

CAN套接字的核心模块实现了PF_CAN协议族。CAN协议模块在核心模块运行后加载。CAN核心模块为协议模块提供了申请需要的ID的接口(参考3.1小节)。

5.1 can.ko模块的参数 -------------------------

- stats_timer: 为了计算CAN套接字的统计信息(比如最近一秒的帧数和每秒最大的帧数),can.ko调用一个定时间隔为1秒的定时器,默认情况下这个定时器是开启的。这个定时器也可以在模块参数中传入stattimer=0来禁止。

- debug : (removed since SocketCAN SVN r546)

5.2 procfs接口 -----------------

就像3.1节描述的那样,CAN套接字核心借助于一些带有过滤规则的队列向CAN协议模块传递接收到的CAN帧。可以在procfs中查看这些接收队列的的过滤规则和匹配规则的次数。所有的条目都包了设备名和协议模块标识:

foo@bar:~$ cat /proc/net/can/rcvlist_all

receive list 'rx_all': (vcan3: no entry) (vcan2: no entry) (vcan1: no entry)

device can_id can_mask function userdata matches ident vcan0 000 00000000 f88e6370 f6c6f400 0 raw (any: no entry)

(yll补充:function是一个函数指针,userdata是一个void *指针,所以这两个值打印出来没有太大意义)

在这个例子中,这个应用程序接收所有vcan0上传输的数据.

rcvlist_all - 没有过滤规则的队列 rcvlist_eff - 扩展帧(EFF)的队列 rcvlist_err - 错误帧队列 rcvlist_fil - 通过过滤规则的队列 rcvlist_inv - 未通过过滤规则的队列 rcvlist_sff - 标准帧的队列

在/proc/net/can中还有另外一些文件:

stats - CAN套接字核心的统计信息(接收/发送的帧数,匹配率等) reset_stats - 复位统计信息

version - 打印CAN套接字核心的版本和ABI的版本

5.3 写一个自己的CAN协议模块

-----------------------------------

要在PF_CAN中增加一个新的协议,必须在include/linux/can.h中为新的协议增加相应的定义。包含include/linux/can.h这个文件便可以使用增加的原型和定义。内核除了提供了注册CAN协议和CAN设备的通知列表的功能,也提供了在一个特定CAN接口上注册感兴趣的CAN帧或者发送CAN帧的功能。

can_rx_register - 在一个特定接口上注册希望接收到的CAN帧的信息 (yll:这个函数的定义在内核的net/can/af_can.c中) can_rx_unregister - 注销上面的申请

can_send - 发送CAN帧(可以选择是否开启本地回环)

详细的信息请参考内核中的源码net/can/af_can.c、net/can/raw.c、net/can/bcm.c。

6. CAN网络驱动

==========

编写一个CAN网络设备驱动要比写一个CAN字符设备驱动要容易的多。和编写其它网络设备驱动类似,你只要处理以下事宜:

- TX :将套接字缓冲区的CAN帧发送到CAN控制器 - RX :从CAN控制器的CAN帧读取到套接字缓冲区

Documentation/networking/netdevices.txt中是网络设备驱动的例子。下面将会介绍CAN网络设备驱动的一些独有特性。

6.1 常见设置 ---------------

dev->type = ARPHRD_CAN; /* the netdevice hardware type */ dev->flags = IFF_NOARP; /* CAN has no arp */ dev->mtu = sizeof(struct can_frame);

结构体can_frame是PF_CAN协议族套接字缓冲区的数组载体。

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核心内置的过滤规则集合允许对每个套接字独立的设置多个过滤规则。因此使用硬件过滤属于嵌入式系统中“手动调整”的范畴。从2002年开始笔者一直使用拥有四路SJA1000 CAN控制器的MPC603e @133MHz,总线负载虽然很高,但是到目前为止还没有什么问题。

6.4 虚拟的CAN驱动 (vcan) ------------------------------

和网络回环设备一样,vcan提供一个虚拟的本地CAN接口。CAN中一个有效的地址包括:

- 一个有效的CAN标识符(CAN ID)

- 这个CAN标识符将要发往的总线(比如 can0).

所以在一般的应用场景中往往需要多个vcan接口。

vcan接口允许在没有控制器硬件的情况下进行发送和接收。vcan网络设备的命名一般采用?vcanX?,比如can1 vcan2等。当编译为单独的模块的时候,vcan驱动的模块名为vcan.ko。