Blog:
CAN FD 在 iMX8 计算机模块上的应用

Friday, December 25, 2020

CAN 总线在工业、汽车行业具有非常广泛的应用,为网络中设备之间点对点通信提供一种可靠、稳定、经济的方案。伴随网络中设备节点的增加,由于 1Mbps 速率和最长数据 8 字节的限制,通信效率和总线占用问题变得愈发突出。而 CAN FD 正是为了应对这种挑战而出现。文章接下来将介绍 CAN FD 的一些新特点以及使用注意事项,最后将使用 Toradex Apalis iMX8QMVerdin iMX8M Mini 计算机模块简单演示 CAN FD 使用。

相比于传统 CAN 协议,CAN FD 最大的两个特点是采用可变速率和单帧最长 64 字节数据,另外包括控制位和 CRC 校验的变化。

图 1:传统 CAN 和 CAN FD 帧

控制位的首位由传统 CAN 的 RTR 变为 CAN FD 的 RRS,该位始终是显性(0)。第三个控制位在传统 CAN 中属于保留功能,在 CAN FD 位 FDF,位隐性(1)。FDF 位 1 时表示该帧是 CAN FD 格式。在 CAN FD 中紧随 FDF 还是一个保留功能,用于将来的扩展。BRS(Bit Rate Switch)位允许 CAN FD 帧以不同的速率进行传输。如果 BRS 为显性(0)则该帧采用和仲裁阶段(Arbitration Phase)同样的速率进行传输,既速率不发生变化。当 BRS 为隐性(1),该帧接下来的部分将以较高的速率传输。这里需要注意,并不是整个 CAN FD 帧都用高速率传输,如下图,Data Phase 从 BRS 后的 ESI 位开始到 CRC Delimiter 位结束,该阶段的数据会以较高的速率传输。

图 2: CAN FD 帧结构

ESI(Error Status Indicator)通常为显性(0)。当发送方遇到通讯异常后会将其置为隐性(1)。DLC 表示该帧中实际数据长度,为了于传统 CAN 兼容,DLC 仍然采用 4bit。当数据长度小于 8 字节时,DLC 位的数值可以直接表示数据长度,但超过 8 字节时,由于 4 个位最高只能表示 15,为了支持 CAN FD 最长 64 字节数据,这里采用了折中的表示方法。当数据不超过 8 个字节时,DLC 仍直接表示数据长度。当超过 8 个字节,只支持 12 到 64 中部分长度的数据包,而非全部的 9 到 64 任一长度。如下表所示,当 DLC 为 9 时,CAN FD 数据长度为 12 字节,DLC 为 12 时,数据长度是 24 字节。

在实际应用中最好选择上面的其中一种长度,避免通讯效率降低。如果小于某一种长度,则需要对数据进行填充,可以用 0xCC 和 0x55 作为填充字节,这样能够在总线上产生足够的波形翻转从而使 CAN 节点保持同步。

在 CAN FD 中根据数据长度会采用不同的 CRC 校验方案,当小于等于 16 字节是为 CRC-17,当数据大于 16 字节后则采用 CRC-21。CRC Delimiter 之后的格式 CAN FD 和传统 CAN 仍保持一致。

CAN FD 虽然具有更长的数据包以及更快的传输速度,但是由于引入了更多的位到帧中,帧的开销也会增加。以同样发送 1字节数据包为例,传统 CAN 2.0 标准帧和 CAN FD 标准帧具体组成如上方图 1 所示。传统 CAN 2.0 标准帧总共位 54 bit,CAN FD 为 70 bit。CAN FD 需要多消耗 16 bit 来传送同样的数据。如果 CAN FD 不采用更高的可变速率这就意味着同样的帧,CAN FD 反而会要更长的传输时间。当 CAN FD 采用可变速率,那么情况将会变得不一样。假设 CAN FD 的仲裁速率是 500 Kbps,和传统 CAN 的速率一致,而可变的数据传输速率提高 8 倍到 4 Mbps。传统 CAN 耗时为 54 bit/ 500 Kbps = 108 us。CAN FD 中 4 Mbps 的速率只用于传输从 ESI 位开始到 CRC Delimiter 位之间的数据,所以 CAN FD 耗时为 29 bit/500 Kbps + 41 bit/4 Mbps = 68 us。这里我们看到,在提高数据传输速率情况下, CAN FD 即使有更多的帧开销,帧传输时间还是减少了 40 us。更高的传输速度有利于发送节点更快得完成帧发送,减少 CAN 总线占用时间,这对越长数据的帧会更加明显,对 CAN 网络的实时性来讲是一个优势。

然而提高传输速率不仅仅是在使用的时候设置一个参数,更重要的是保障 CAN 总线物理链路层的质量。可以使用示波器观察总线上信号的质量。如果信号陡峭且清晰,可以尝试将数据传输速率提高到仲裁速率的 2 到 4 倍。测量点需要遍布总线上多个位置,信号在不同位置会有所差异。线路阻抗的一致性对信号质量至关重要。通常在总线交叉点的线缆没有发生物理尺寸变化,并采用具有相同介电常数的隔离器,阻抗会保持不变。这可以参考以太网和 USB 中使用的专门的连接器。当 CAN FD 采用较高的传输速率时,每处线路分叉,每个连接器都可能会影响阻抗,从而引起信号反射。这些反射信号的能量最终可以影响 CAN 帧每个比特位边缘的抖动。

CAN FD 最长 64 字节的数据包使用在实际应用中也需要注意。更长的帧不可避免在传输的时候会占用总线更多的时间,而这期间其他 CAN 节点则无法发送数据。对于实时性需求不高的场合,如通过 CAN 总线升级固件,长帧能够以更小的开销完成传输。而对实时性有要求的场合,对长帧的使用需要有一定的限制。对于 8 字节以下的帧, CAN FD 更高的数据传输速率可以有效降低总线占用时间,前提是物理链路层能够满足高速传输的要求。

对于应用开发 CAN FD 的使用是非常简单的。CAN FD 是可以兼容传统 CAN,这意味着原先基于传统 CAN 通信的代码可以直接运行在支持 CAN FD的设备上,但不使用任何 CAN FD 的新功能。如果需要使用 CAN FD 的可变数据速率或者超过 8 字节数据的帧,那么代码也只需做简单的修改。我们以 Linux 中 SocketCAN 为例,使用 can-utils 代码进行说明。在 cansend.c 和 candump.c 中采用 canfd_frame 结构体来存放需要发送和接收的 CAN 数据。CANFD_MAX_DLEN 为 64,对应 CAN FD 最长的 64 字节。

然后将 can socket 设置 CAN FD 格式,使用 setsockopt() 函数,设置 CAN_RAW_FD_FRAMES 参数即可。

在发送时将 struct canfd_frame frame 结构体中 len 长度参数设置 CAN FD 定义几种长度。

剩余代码中的操作可以沿用传统 CAN 模式下的方法。最后用下面命令配置 CAN 设备。这里仲裁速率为 500Kbps,CAN FD 可变数据速率为1Mbps,在结尾添加 fd on 参数启用 CAN FD。

$ ip link set can0 type can bitrate 500000 dbitrate 1000000 fd on

接下来我们将在 Apalis iMX8QM 和 Verdin iMX8M Mini 计算机模块上演示 CAN FD 通信。Apalis iMX8QM  采用 NXP i.MX8 QuadMax 处理器,可以提供 3 路 CAN 接口。Verdin iMX8M Mini 上的 i.MX8 M Mini 处理器本身并不支持 CAN 接口,我们在模块上添加了一块 MCP2518 实现 CAN 接口。

Apalis iMX8QM 和 Verdin iMX8M Mini 分别通过 Ixora 和 Dahlia 载板进行 CAN 接口互联。这两个底板上均引出了 CAN 接口,方便用户测试。

Verdin iMX8M Mini 作为发送端,依次运行下面命令,并发送 4 字节和 10 字节长度的帧。

root@verdin-imx8mm:~# ip link set can0 type can bitrate 500000 dbitrate 1000000 fd on
root@verdin-imx8mm:~# ip link set can0 up
root@verdin-imx8mm:~# cansend can0 '123##1.11223344'
root@verdin-imx8mm:~# cansend can0 '123##1.11223344556677889900'


Apalis iMX8QM 作为接收端。

root@apalis-imx8:~# ip link set can0 type can bitrate 500000 dbitrate 1000000 fd on
root@apalis-imx8:~# ip link set can0 up
root@apalis-imx8:~# candump can0
can0  123  [04]  11 22 33 44
can0  123  [12]  11 22 33 44 55 66 77 88 99 00 00 00


上面测试可以看到 Verdin iMX8M Mini 发送一帧 10 字节长度的数据,但是 Apalis iMX8QM  在收到了 12 字节的数据。这是 CAN FD 定义没有 10 字节的帧长,适合发送 10 字节的是 12 字节长度的帧。所以看到实际收到的是“11 22 33 44 55 66 77 88 99 00 00 00”这12 个字节,最后两个“00 00 ”是填充的数据。这部分填充数据来自 lib.c 代码  memset(cf, 0, sizeof(*cf)); /* init CAN FD frame, e.g. LEN = 0 */

总结

CAN FD 的新功能为满足了应用对更加高效的传输、更好实时性需求,但充分发挥这些功能还需要从应用开发到链路设计方面的优化。上面我们讨论简单地讨论一些注意事项,以及使用方法,具体的应用还要结合实际工况做调整。

参考:

https://www.microcontrol.net/en/know-how/bus-systems/can-fd/
https://www.picoauto.com/library/picoscope/can-bus-serial-protocol-decoding
https://www.can-cia.org/can-knowledge/can/can-fd/#:~:text=CAN%20FD%20data%20frames%20with,support%20remotely%20requested%20data%20frames.&text=
The%20control%20field%20comprises%20additional,the%20Classical%20CAN%20data%20frames
.
https://www.eecs.umich.edu/courses/eecs461/doc/CAN_notes.pdf
https://en.wikipedia.org/wiki/CAN_FD
https://www.kvaser.com/wp-content/uploads/2016/04/can-fd-considerations-for-different-stakeholders.pdf
https://www.kvaser.com/wp-content/uploads/2016/10/comparing-can-fd-with-classical-can.pdf

Author: 胡珊逢,FAE,韬睿(上海)
Share this on:

Leave a comment

Your email ID will be kept confidential. Required fields are marked *



* Your comment will be reviewed and then added. Thank you.

Related Blog

Latest Blog

Tuesday, May 11, 2021
Importing a Qt Project Into Torizon Using VS Code
Monday, April 26, 2021
Using a VPN on embedded Linux systems
Tuesday, March 23, 2021
Running Qt without a GPU
Have a Question?