UCAN 协议¶
UCAN 是基于微控制器的 USB-CAN 适配器所使用的协议,该适配器集成在 Theobroma Systems 的片上系统 (System-on-Modules) 上,也可作为独立的 USB 棒使用。
UCAN 协议被设计为与硬件无关。它的模型与 Linux 在内部表示 CAN 设备的方式非常相似。所有多字节整数都以小端字节序编码。
本文档中提到的所有结构都在 drivers/net/can/usb/ucan.c
中定义。
USB 端点¶
UCAN 设备使用三个 USB 端点
- 控制端点
驱动程序在此端点上发送设备管理命令
- IN 端点
设备发送 CAN 数据帧和 CAN 错误帧
- OUT 端点
驱动程序在 OUT 端点上发送 CAN 数据帧
控制消息¶
UCAN 设备使用控制管道上的供应商请求进行配置。
为了在单个 USB 设备中支持多个 CAN 接口,所有配置命令都针对 USB 描述符中相应的接口。
驱动程序使用 ucan_ctrl_command_in/out
和 ucan_device_request_in
将命令传递给设备。
设置数据包¶
|
方向 | 供应商 | (接口或设备) |
|
命令号 |
|
子命令号 (16 位) 或 0 (如果未使用) |
|
USB 接口索引 (设备命令为 0) |
|
|
错误处理¶
设备通过停止管道来指示失败的控制命令。
设备命令¶
UCAN_DEVICE_GET_FW_STRING¶
设备到主机;可选
请求设备固件字符串。
接口命令¶
UCAN_COMMAND_START¶
主机到设备;强制
启动 CAN 接口。
- 有效负载格式
ucan_ctl_payload_t.cmd_start
mode |
|
UCAN_COMMAND_STOP¶
主机到设备;强制
停止 CAN 接口
- 有效负载格式
空
UCAN_COMMAND_RESET¶
主机到设备;强制
重置 CAN 控制器 (包括错误计数器)
- 有效负载格式
空
UCAN_COMMAND_GET¶
主机到设备;强制
从设备获取信息
子命令¶
- UCAN_COMMAND_GET_INFO
请求设备信息结构
ucan_ctl_payload_t.device_info
。有关详细信息,请参阅
device_info
字段,有关can_bittiming fields
的说明,请参阅uapi/linux/can/netlink.h
。- 有效负载格式
ucan_ctl_payload_t.device_info
UCAN_COMMAND_GET_PROTOCOL_VERSION
请求设备协议版本
ucan_ctl_payload_t.protocol_version
。当前协议版本为 3。
- 有效负载格式
ucan_ctl_payload_t.protocol_version
注意
不实现此命令的设备使用旧协议版本 1
UCAN_COMMAND_SET_BITTIMING¶
主机到设备;强制
通过发送结构 ucan_ctl_payload_t.cmd_set_bittiming
设置位定时 (详情请参阅 struct bittiming
)
- 有效负载格式
ucan_ctl_payload_t.cmd_set_bittiming
.
UCAN_SLEEP/WAKE¶
主机到设备;可选
配置睡眠和唤醒模式。驱动程序尚未支持。
UCAN_FILTER¶
主机到设备;可选
设置硬件 CAN 过滤器。驱动程序尚未支持。
允许的接口命令¶
合法设备状态 |
命令 |
新设备状态 |
---|---|---|
停止 |
SET_BITTIMING |
停止 |
停止 |
START |
已启动 |
已启动 |
STOP 或 RESET |
停止 |
停止 |
STOP 或 RESET |
停止 |
已启动 |
RESTART |
已启动 |
任何 |
GET |
无变化 |
IN 消息格式¶
USB IN 端点上的数据包包含一个或多个 ucan_message_in
值。如果多个消息在 USB 数据包中批量处理,则可以使用 len
字段跳转到下一个 ucan_message_in
值(请注意根据实际数据大小对 len
值进行健全性检查)。
len
字段¶
每个 ucan_message_in
都必须与 4 字节边界对齐 (相对于数据缓冲区的起始位置)。这意味着多个 ucan_message_in
值之间可能存在填充字节
+----------------------------+ < 0
| |
| struct ucan_message_in |
| |
+----------------------------+ < len
[padding]
+----------------------------+ < round_up(len, 4)
| |
| struct ucan_message_in |
| |
+----------------------------+
[...]
type
字段¶
type
字段指定消息的类型。
UCAN_IN_RX¶
subtype
零
从 CAN 总线接收的数据 (ID + 有效负载)。
UCAN_IN_TX_COMPLETE¶
subtype
零
CAN 设备已向 CAN 总线发送消息。它返回一个 <echo-ids, flags> 元组列表。
echo-id 从 (echo 来自先前 UCAN_OUT_TX 消息的 id) 识别帧。该标志指示传输的结果。其中,设置的位 0 表示成功。所有其他位都保留并设置为零。
流控制¶
接收 CAN 消息时,USB 缓冲区上没有流控制。驱动程序必须足够快地处理入站消息,以避免丢弃。如果设备缓冲区溢出,则会发送相应的错误帧报告此情况 (请参阅 CAN 错误处理)
OUT 消息格式¶
USB OUT 端点上的数据包包含一个或多个 struct ucan_message_out
值。如果将多个消息批量处理到一个数据包中,则设备使用 len
字段跳转到下一个 ucan_message_out 值。每个 ucan_message_out 都必须与 4 个字节对齐 (相对于数据缓冲区的起始位置)。该机制与 len 字段 中描述的相同。
+----------------------------+ < 0
| |
| struct ucan_message_out |
| |
+----------------------------+ < len
[padding]
+----------------------------+ < round_up(len, 4)
| |
| struct ucan_message_out |
| |
+----------------------------+
[...]
type
字段¶
在协议版本 3 中,仅定义了 UCAN_OUT_TX
,其他仅由旧设备 (协议版本 1) 使用。
UCAN_OUT_TX¶
subtype
要在 CAN_IN_TX_COMPLETE 消息中回复的 echo id
发送 CAN 帧。(参数:id
, data
)
流控制¶
当设备出站缓冲区已满时,它会在 OUT 管道上开始发送 NAK,直到有更多缓冲区可用。当不完整的 OUT 数据包达到某个阈值时,驱动程序会停止队列。
CAN 错误处理¶
如果启用了错误报告,则设备会将错误编码到 CAN 错误帧中(请参阅 uapi/linux/can/error.h
),并使用 IN 端点发送。驱动程序会更新其错误统计信息并将其转发。
尽管 UCAN 设备可以完全禁止错误帧,但在 Linux 中,驱动程序始终对其感兴趣。因此,设备始终以设置的 UCAN_MODE_BERR_REPORT
启动。驱动程序会为用户空间过滤这些消息。
总线关闭¶
设备不会自动从总线关闭中恢复。
总线关闭通过错误帧指示 (请参阅
uapi/linux/can/error.h
)总线关闭恢复由
UCAN_COMMAND_RESTART
启动总线关闭恢复完成后,设备会发送一个错误帧,指示它处于 ERROR-ACTIVE 状态。
在总线关闭期间,设备不发送任何帧。
在总线关闭期间,来自主机的传输请求会立即完成,并且未设置成功位。
示例对话¶
设备已连接到 USB
主机发送命令
UCAN_COMMAND_RESET
,子命令 0主机发送命令
UCAN_COMMAND_GET
,子命令UCAN_COMMAND_GET_INFO
设备发送
UCAN_IN_DEVICE_INFO
主机发送命令
UCAN_OUT_SET_BITTIMING
主机发送命令
UCAN_COMMAND_START
,子命令 0,模式UCAN_MODE_BERR_REPORT