> ## Documentation Index
> Fetch the complete documentation index at: https://dragonwingdocs.qualcomm.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CAN

export const tdA = {
  border: "1px solid #ddd",
  padding: "10px 14px",
  textAlign: "left",
  verticalAlign: "top"
};
export const thAeq = {
  border: "1px solid #ddd",
  padding: "10px 14px",
  textAlign: "center",
  backgroundColor: "#f5f5f5",
  fontWeight: "600",
  color: "#333"
};
export const tblA = {
  borderCollapse: "collapse",
  width: "100%",
  fontSize: "14px",
  tableLayout: "fixed"
};

控制器局域网（CAN）是一种基于消息的串行协议。术语 CAN 和 CAN 总线在同一语境中使用。CAN 的优势如下：

* 使用 CSMA/CD 方法和逐位竞争机制在位级别感知总线并传输消息。
* 每条消息都被分配一个优先级。优先级最高的消息始终控制总线仲裁。由于仲裁基于位，因此存在显性和隐性位电平。
* 任何节点都可以随时发送数据，没有主从节点之分。
* 所有数据都通过两条（差分对）线路传输：CAN\_H 线和 CAN\_L 线。
* CAN 节点使用位同步进行同步，其中每个位时间被划分为四个时间份额（time quanta）段。
* 通过基于消息的协议实现多个节点之间的通信，无需大量布线。
* 通过包括检测、发信和纠正在内的错误管理来确保数据安全。

<Note>
  **注意**

  * QCS6490 和 QCS5430 中默认启用 CAN。
  * Dragonwing IQ-9075、Dragonwing IQ-8275 和 Dragonwing IQ-615 不支持 CAN。
</Note>

## **CAN 功能**

CAN 协议支持以下功能。

* 基于优先级的多控制器总线访问
* 基于内容的非破坏性仲裁
* 通过全帧传输进行广播
* 通过接收过滤进行多播帧传输
* 远程数据请求
* 配置灵活性
* 全网络数据一致性
* 错误检测和错误发信
* 自动重传在传输过程中失去仲裁、缺少应答或遇到错误的帧
* 识别节点临时错误与永久性节点故障之间的差异，并自动停用故障节点

## **CAN 架构**

MCP2517 是一个外部可配置的 CAN 控制器，可通过 SPI 线路访问。SPI 接口支持高达 20 MHz，并支持 Mode0,1。该控制器连接到一个 QUP 模块，其中 SE3 配置为 4 引脚 SPI 操作。SPI 控制器连接到一个收发器（MCP2561xxx），收发器再连接到 CAN 总线。SPI 控制器和 CAN 收发器的电源输入来自 SoC。

<Frame>
  <img src="https://mintcdn.com/qualcomm-prod/rpHTx_a6zriKQll9/System/Interfaces/images/CAN_architecture.png?fit=max&auto=format&n=rpHTx_a6zriKQll9&q=85&s=a24dcd27e1675ab5ca42072960783e6c" alt="CAN 架构" width="766" height="274" data-path="System/Interfaces/images/CAN_architecture.png" />
</Frame>

<p align="center"><strong>图：CAN 架构</strong></p>

用户应用程序与 SocketCAN 提供的网络接口进行通信。软件驱动程序是 Linux 中 SPI 核心模块的客户端，QUP\_SPI 驱动程序在该模块中注册。实际硬件通过 SPI 引脚连接。

<Frame>
  <img src="https://mintcdn.com/qualcomm-prod/rpHTx_a6zriKQll9/System/Interfaces/images/CAN_software_stack.png?fit=max&auto=format&n=rpHTx_a6zriKQll9&q=85&s=b16c0bf876440eab9017a622e475f37d" alt="CAN 软件栈" width="670" height="666" data-path="System/Interfaces/images/CAN_software_stack.png" />
</Frame>

<p align="center"><strong>图：CAN 软件栈</strong></p>

## **CAN API**

有关 CAN 公共 API，请参阅 [https://www.kernel.org/doc/Documentation/networking/can.txt](https://www.kernel.org/doc/Documentation/networking/can.txt)。

## **CAN 示例和工具**

下表列出了用于显示、记录、生成和重放 CAN 流量的 SocketCAN 用户空间实用程序和工具。

**表：**

**SocketCAN 实用程序**

<table style={tblA}>
  <thead>
    <tr>
      <th style={thAeq}>实用程序</th>
      <th style={thAeq}>描述</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={tdA}>`candump`</td>
      <td style={tdA}>用于显示、过滤 CAN 数据并将其记录到文件。</td>
    </tr>

    <tr>
      <td style={tdA}>`canplayer`</td>
      <td style={tdA}>用于重放 CAN 日志文件。</td>
    </tr>

    <tr>
      <td style={tdA}>`cansend`</td>
      <td style={tdA}>用于发送单个帧。</td>
    </tr>

    <tr>
      <td style={tdA}>`cangen`</td>
      <td style={tdA}>用于生成（随机）CAN 流量。</td>
    </tr>

    <tr>
      <td style={tdA}>`cansniffer`</td>
      <td style={tdA}>用于显示 CAN 数据内容差异（仅限 11 位 CAN ID）。</td>
    </tr>
  </tbody>
</table>

要下载 CAN 实用程序，请参阅 [https://github.com/linux-can/can-utils](https://github.com/linux-can/can-utils)。

有关 CAN 驱动程序文件的信息，请参阅 `kernel/drivers/net/can/spi/mcp251xfd/mcp251xfd-core.c`。

### **CAN 分析仪 - PCAN-USB FD**

PCAN-USB FD 是一款多功能的 CAN 数据包/消息嗅探器，可以作为任何 CAN 总线上的节点运行，支持灵活的数据速率。它可用于通过 USB 在主机上嗅探和发送 CAN 数据包。主要特性如下：

* PCAN-View GUI 工具
  * 提供根据用户需求嗅探和发送 CAN 数据包的便捷方式。
  * 在开发和测试期间监控和调试 CAN 数据包。
* PCAN-USB FD 接口
  * 可轻松连接到 CAN FD 和 CAN 网络。
  * 紧凑的塑料外壳，适用于移动应用。
  * 高达 500 V 的电气隔离将 PC 与 CAN 总线解耦。
* CAN FD 标准
  * 具有更高的数据传输带宽。
  * 每个 CAN FD 帧最多可传输 64 个数据字节（而不是 8 个）。
  * 支持高达 12 Mbit/s 的比特率。
  * 向下兼容 CAN 2.0 标准。
  * CAN FD 节点可插入现有 CAN 网络，无需 CAN FD 扩展。

**硬件设置**

1. 连接到 DB9 连接器。
   * PCAN 上有一个 DB9 连接器，任何标准 DB9 连接器都可以插入其中。
2. 连接到 Qualcomm 设备。
   * 引出 CAN\_H、CAN\_L 和 GND 线。
   * 将这些线连接到两个 120 Ω 的终端电阻。
3. 连接 CAN\_H、CAN\_L 和接地。

<Frame>
  <img src="https://mintcdn.com/qualcomm-prod/rpHTx_a6zriKQll9/System/Interfaces/images/CAN_connections.png?fit=max&auto=format&n=rpHTx_a6zriKQll9&q=85&s=62cb3bdfab142434760210fd9760ebdd" alt="CAN 连接" width="696" height="233" data-path="System/Interfaces/images/CAN_connections.png" />
</Frame>

<p align="center"><strong>图：CAN 连接</strong></p>

4. 连接外部终端电阻。

<Note>
  **注意**

  该设备没有内置 120 Ω 终端电阻。这一点至关重要，因为某些工具提供了对终端电阻的内置支持。
</Note>

<Frame>
  <img src="https://mintcdn.com/qualcomm-prod/rpHTx_a6zriKQll9/System/Interfaces/images/CAN_Terminating_resistor.png?fit=max&auto=format&n=rpHTx_a6zriKQll9&q=85&s=e29768e344e5981bbc43a0a54b5d1a60" alt="CAN 终端电阻" width="645" height="267" data-path="System/Interfaces/images/CAN_Terminating_resistor.png" />
</Frame>

<p align="center"><strong>图：CAN 终端电阻</strong></p>

下图显示了已连接的硬件。

<Frame>
  <img src="https://mintcdn.com/qualcomm-prod/rpHTx_a6zriKQll9/System/Interfaces/images/CAN_device_connection.png?fit=max&auto=format&n=rpHTx_a6zriKQll9&q=85&s=005cfb4d22c6950e19d78d12ac7b4ce5" alt="CAN USB FD、外部电阻和设备连接" width="768" height="498" data-path="System/Interfaces/images/CAN_device_connection.png" />
</Frame>

<p align="center"><strong>图：CAN USB FD、外部电阻和设备连接</strong></p>

## **启动 CAN 接口**

在构建 CAN 驱动程序并将其加载到内核后，以下命令序列会发送数据以确认 CAN 节点是否已启动。可以使用下表中列出的命令启动或停止 CAN 节点。

<Note>
  **注意**

  所有网络设备均使用 `ifconfig -a`。
</Note>

**表：**

**CAN 命令**

<table style={tblA}>
  <thead>
    <tr>
      <th style={thAeq}>操作说明</th>
      <th style={thAeq}>命令</th>
    </tr>
  </thead>

  <tbody>
    <tr>
      <td style={tdA}>检查 can 节点编号</td>
      <td style={tdA}>`ifconfig -a`</td>
    </tr>

    <tr>
      <td style={tdA}>设置 125 kbps 的比特率</td>
      <td style={tdA}>`ip link set can0 up type can bitrate 125000`</td>
    </tr>

    <tr>
      <td style={tdA}>启动 CAN</td>
      <td style={tdA}>`ip link set can0 up`</td>
    </tr>

    <tr>
      <td style={tdA}>停止 CAN</td>
      <td style={tdA}>`ip link set can0 down`</td>
    </tr>

    <tr>
      <td style={tdA}>检查 CAN 配置</td>
      <td style={tdA}>`ip -details link show can0`</td>
    </tr>

    <tr>
      <td style={tdA}>CAN 内部环回</td>
      <td style={tdA}>`ip link set can0 up type can bitrate 500000 loopback on`</td>
    </tr>

    <tr>
      <td style={tdA}>CAN FD 内部环回</td>
      <td style={tdA}>`ip link set can0 up type can bitrate 1000000 dbitrate 5000000 fd on loopback on`</td>
    </tr>

    <tr>
      <td style={tdA}>发送 CAN FD 帧</td>
      <td style={tdA}>`cansend can0 213##311223344`</td>
    </tr>
  </tbody>
</table>

要启动任何 CAN 节点，必须定义总线的比特率，或者在总线速率已可用的情况下进行配置。此配置可确保 CAN 节点已启动并处于活动状态。有关 CAN 实用程序的更多详细信息，请参阅 [https://manpages.debian.org/testing/can-utils/index.html](https://manpages.debian.org/testing/can-utils/index.html)。

### **发送和接收数据**

`CAN-Utils` 文件中提供了一些实用程序。SocketCAN 使 CAN 节点能够发送和接收数据。SocketCAN API 也可用于自定义应用程序。

* 使用 11 位 ID 发送数据
  ```text theme={null}
  cansend can0 7AF#11.22.33.44.55.66.aa.ff
  ```
* 使用 29 位 ID 发送数据
  ```text theme={null}
  cansend can0 111FFFFF#aa.00.cc.aa.33.61.aa.ab
  ```
* 查看 can0 节点上当前传入的数据
  ```text theme={null}
  candump can0
  ```

## **配置 CAN 接口**

SocketCAN 是 CAN 协议在 Linux 上的实现。SocketCAN 使用 Berkeley 套接字 API 和 Linux 网络栈，并将 CAN 设备驱动程序实现为网络接口。CAN 套接字 API 的设计尽可能与 TCP/IP 协议相似，使熟悉网络编程的用户能够轻松学习如何使用 CAN 套接字。

### **初始化硬件**

驱动程序会初始化并配置底层硬件模块。初始化在调用 `driver's _probe()` 函数之后进行。

```text theme={null}
static struct spi_driver mcp251xfd_driver = {
    .driver = {
        .name = DEVICE_NAME,
        .pm = &mcp251xfd_pm_ops,
        .of_match_table = mcp251xfd_of_match,
    },
    .probe = mcp251xfd_probe,
    .remove = mcp251xfd_remove,
    .id_table = mcp251xfd_id_table,
};
 
static int mcp251xfd_probe(struct spi_device *spi)
{
    struct net_device *ndev;
    struct mcp251xfd_priv *priv;
[..]
ndev = alloc_candev(sizeof(struct mcp251xfd_priv),
                MCP251XFD_TX_OBJ_NUM_MAX);
    if (!ndev)
        return -ENOMEM;
 
    SET_NETDEV_DEV(ndev, &spi->dev); // The SPI node is set as the parent node to the network device. 
 
    ndev->netdev_ops = &mcp251xfd_netdev_ops;
[..]
    err = mcp251xfd_register(priv);
};
```

## **调试 CAN 问题**

可以使用 `ftrace` 工具调试 CAN 问题。MCP2517 驱动程序支持 `dev_coredump()` API。

## **CAN 示例**

有关 CAN 示例，请参阅 [https://github.com/linux-can/can-utils/blob/master/README.md](https://github.com/linux-can/can-utils/blob/master/README.md)。
