1. 学习目标
- 理解 CAN 总线工作原理
理解 CAN 总线结构:
CAN_H
CAN_L
以及通信方式:
广播通信
优先级仲裁
帧结构
- 理解 Linux CAN 子系统架构
理解 Linux CAN 驱动结构:
User Space
│
▼
SocketCAN
│
▼
CAN Network Driver
│
▼
CAN Controller
- 理解 CAN 核心结构
掌握核心对象:
can_device
net_device
can_frame
- 能编写基础 CAN 驱动
掌握核心 API:
register_candev
alloc_candev
can_put_echo_skb
- 能使用用户空间工具测试 CAN
掌握工具:
ip
candump
cansend
2. CAN 总线简介
CAN 是一种:
多主机通信总线
信号线:
CAN_H
CAN_L
结构:
User Space
│
▼
SocketCAN
│
▼
CAN Network Driver
│
▼
CAN Controller
特点:
广播通信
高可靠性
实时性强
CAN 帧结构
标准 CAN 帧:
| ID | DLC | DATA | CRC |
示例:
ID = 0x123
DATA = 8 bytes
3. Linux CAN 子系统架构
Linux CAN 子系统结构:
User Space
│
▼
Socket API
│
▼
SocketCAN
│
▼
CAN Network Driver
│
▼
CAN Controller Driver
Linux 将 CAN 设备当作:
网络设备
例如:
can0
can1
4. SocketCAN
SocketCAN 是 Linux CAN 框架。
作用:
统一 CAN 通信接口
用户程序使用:
socket()
访问 CAN。
例如:
socket(PF_CAN, SOCK_RAW, CAN_RAW)
5. CAN 核心结构
CAN 子系统核心结构:
net_device
can_device
can_frame
6. can_frame
CAN 数据帧结构:
struct can_frame
{
canid_t can_id;
__u8 can_dlc;
__u8 data[8];
};
字段:
can_id CAN ID
can_dlc 数据长度
data 数据
7. net_device
Linux CAN 设备本质是:
网络设备
结构:
struct net_device
系统设备:
can0
can1
8. CAN 驱动核心结构
CAN 驱动核心对象:
can_priv
net_device
can_ops
can_priv
can_priv 表示:
CAN 设备私有数据
结构:
struct can_priv
{
struct can_bittiming bittiming;
};
用于:
波特率配置
can_ops
CAN 驱动操作接口:
start
stop
transmit
9. CAN 驱动注册流程
CAN 驱动基本流程:
分配 net_device
│
初始化 can_priv
│
register_candev
│
生成 canX
流程图:
CAN Driver
│
▼
alloc_candev
│
▼
register_candev
│
▼
can0
10. CAN 数据发送
发送 CAN 帧:
write(socket)
驱动流程:
User Space
│
send()
│
SocketCAN
│
Driver
│
Hardware
驱动函数:
ndo_start_xmit
11. CAN 数据接收
接收流程:
CAN Hardware
│
▼
IRQ
│
▼
Driver
│
▼
netif_rx
│
▼
SocketCAN
│
▼
User Space
12. CAN 驱动示例
简单 CAN 驱动结构:
static int my_can_open(struct net_device *dev)
{
printk("can open\n");
return 0;
}
static int my_can_close(struct net_device *dev)
{
printk("can close\n");
return 0;
}
static const struct net_device_ops my_can_ops =
{
.ndo_open = my_can_open,
.ndo_stop = my_can_close,
};
注册:
dev = alloc_candev(sizeof(struct my_priv), 1);
dev->netdev_ops = &my_can_ops;
register_candev(dev);
13. 用户空间 CAN 工具
Linux 提供 CAN 工具:
ip
candump
cansend
配置 CAN
启动 CAN:
ip link set can0 up type can bitrate 500000
发送 CAN
cansend can0 123#11223344
接收 CAN
candump can0
14. Device Tree 描述 CAN
CAN 控制器通常通过 Device Tree 描述。
示例:
can@4000
{
compatible = "my-can";
reg = <0x4000 0x100>;
interrupts = <10>;
};
15. CAN 子系统结构总结
Linux CAN 子系统结构:
User Space
│
▼
SocketCAN
│
▼
CAN Driver
│
▼
CAN Hardware
核心结构:
net_device
can_device
can_frame
16. 驱动常见问题
CAN 无法发送
原因:
CAN 未启动
CAN 数据错误
原因:
波特率不匹配
17. 总结
Linux CAN 子系统核心结构:
SocketCAN
│
▼
CAN Driver
│
▼
CAN Hardware
核心对象:
net_device
can_device
can_frame
最重要原则:
CAN 驱动 = SocketCAN + Network Device
18. Q&A
18.1 基础理解
-
CAN 为什么适合汽车通信?
-
CAN 总线为什么抗干扰?
18.2 Linux 架构
-
为什么 Linux 把 CAN 当作网络设备?
-
SocketCAN 的作用是什么?
18.3 驱动流程
-
alloc_candev 做了什么?
-
register_candev 的作用是什么?