当前位置: 首页 > news >正文

RK3568 CAN驱动配置与调试实战指南

1. 从零开始:认识RK3568的CAN控制器

大家好,我是老张,一个在嵌入式圈子里摸爬滚打了十多年的老码农。今天咱们不聊那些虚头巴脑的理论,直接上手干点实在的——给RK3568这颗国产“网红”芯片配好CAN总线驱动。我知道,很多刚接触工业控制或者汽车电子的朋友,一听到“驱动配置”、“设备树”这些词就有点发怵,觉得是Linux内核大佬们才玩得转的东西。别怕,今天我就用最“小白”的方式,带你一步步走通整个流程,保证你跟着做一遍,就能让你的RK3568板子跟其他CAN设备“对上话”。

首先,咱们得搞清楚RK3568的CAN控制器到底是个啥。简单来说,CAN(Controller Area Network)就是一种在汽车、工业自动化领域用得特别多的通信总线,它抗干扰能力强,能一根线上挂很多设备。RK3568芯片内部通常集成了两个CAN控制器,也就是我们常说的CAN1和CAN2。这两个控制器在硬件上是独立的,你可以把它们想象成两个独立的“对讲机”,可以同时跟不同的设备群组通信。我们软件工程师要做的,就是告诉Linux内核:芯片里的这两个“对讲机”硬件在哪里、怎么用、用多快的语速(波特率)说话。这个“告诉”的过程,主要就是通过修改设备树(Device Tree)文件来实现的。设备树就像一份给内核的“硬件接线图”,内核启动时按图索骥,就知道该去哪里初始化哪个硬件了。

所以,整个配置过程的核心思路非常清晰:改设备树,告诉内核CAN控制器在哪 → 编译内核,让改动生效 → 在系统里配置并测试CAN接口。听起来是不是没那么复杂了?咱们接下来就按这个思路,一步步拆解。我会把我在实际项目中踩过的坑、遇到的怪现象以及怎么解决的,都毫无保留地分享出来。你可能会发现,有些步骤跟官方文档写得不太一样,那是因为文档往往只告诉你理想路径,而实战中总会遇到点“惊喜”。准备好了吗?咱们先从最基础的硬件引脚确认开始。

2. 实战第一步:硬件引脚与设备树配置详解

配置驱动的第一步,永远是从硬件出发。你手头的RK3568开发板,CAN接口是通过哪些物理引脚引出来的?这个问题必须搞清楚,否则设备树配置就是空中楼阁。通常,核心板上的CAN控制器信号会通过排针或者连接器引到底板上,你需要找到底板原理图,确认CAN_TX(发送)和CAN_RX(接收)这两个关键信号连接到了RK3568的哪两个GPIO引脚上。

2.1 确认引脚与复用功能

这是我踩过的第一个坑:想当然地以为引脚定义是固定的。实际上,RK3568的引脚功能非常灵活,一个物理引脚可以通过内部寄存器配置成多种功能,比如普通GPIO、UART的TX,或者就是我们需要的CAN_TX。这个配置过程就叫“引脚复用”(Pin Mux)。

在你的内核源码目录下(比如linux-rockchip/arch/arm64/boot/dts/rockchip/),找到对应你板子的设备树源文件(.dts或.dtsi)。我们需要在里面找到关于CAN引脚配置的部分。通常,它会被定义成一个叫pinctrl的节点。根据你提供的原始文章线索,关键信息是can1m1_pinscan2m0_pins这两个东西。

can1m1_pins这个命名就很有讲究:“can1”指控制器1,“m1”很可能指的是复用功能选项1(Mux Function 1)。不同的复用选项(m0, m1, m2…)对应着不同的引脚。你必须根据你的实际硬件连接,去核对这个复用组(pinctrl group)里定义的引脚号,是否真的连接到了你底板上的CAN收发器芯片上。如果对不上,通信肯定失败。怎么核对?打开你的原理图,找到CAN收发器(比如TJA1050)的TXD和RXD脚,看它们连到了主控的哪个引脚,比如GPIO3_B1。然后去设备树里看can1m1_pins的定义,检查它包含的引脚是不是GPIO3_B1。这个步骤千万不能省,我见过太多人因为引脚复用没配对,调试了半天软件却发现是硬件连接没对应上。

2.2 编写与修改设备树节点

确认好引脚后,我们就可以正式修改设备树了。设备树里关于CAN控制器的节点通常已经由芯片厂商定义好了基础框架,我们需要做的是“启用”它,并设置正确的参数。下面我结合一个更详细的例子来解释:

/* 首先,确保在文件开头或包含的头文件里,有CAN控制器的定义 */ #include "rk3568-pinctrl.dtsi" // 通常引脚定义在这里面 /* 在 &i2c3, &spi1 这类同级位置,找到或添加CAN节点 */ &can1 { /* 最关键的一步:指定时钟。CAN控制器工作需要稳定的时钟源 */ assigned-clocks = <&cru CLK_CAN1>; /* 引用CAN1的时钟 */ assigned-clock-rates = <100000000>; /* 设置时钟频率为100MHz,这是CAN控制器工作的核心时钟,波特率基于此计算 */ /* 引脚控制配置,这里就用到我们之前确认的 pinctrl 组 */ pinctrl-names = "default"; /* 状态名,默认就够用 */ pinctrl-0 = <&can1m1_pins>; /* 将 can1m1_pins 这个引脚配置组应用给CAN1 */ /* 驱动兼容性设置,告诉内核用哪个驱动来匹配这个硬件 */ compatible = "rockchip,can-1.0"; // 或 "rockchip,canfd-1.0",取决于你用的驱动 /* 状态设为 okay,表示启用这个设备。如果设为 disabled,内核就会忽略它 */ status = "okay"; }; &can2 { assigned-clocks = <&cru CLK_CAN2>; assigned-clock-rates = <100000000>; pinctrl-names = "default"; pinctrl-0 = <&can2m0_pins>; // 注意,这里是 m0,可能和CAN1用的复用组不同 status = "okay"; };

这里有几个容易出错的点:

  1. 时钟设置assigned-clock-rates = <100000000>;这行里的100MHz是常见值,但不是波特率。CAN通信的波特率(比如125kbps, 500kbps)是软件后期配置的,这个100MHz是控制器的输入工作时钟,必须正确,否则后续波特率计算会全错。有些板子可能需要不同的时钟频率,务必参考核心板的硬件设计手册。
  2. compatible属性:这个属性像是一个“暗号”,内核会根据这个字符串去驱动程序列表里寻找匹配的驱动。如果写错了,内核就找不到驱动,设备就无法初始化。通常,瑞芯微的CAN驱动支持"rockchip,can-1.0"(标准CAN)和"rockchip,canfd-1.0"(CAN FD)。用哪个取决于你的硬件和驱动选择,后面会详细讲。
  3. status属性:一定要是"okay",写错一个字母或者写成"disabled",这个设备就不会被激活。

修改完设备树源文件后,需要重新编译设备树二进制文件(.dtb),并更新到开发板上。编译命令通常在内核构建目录下,比如make dtbs。把生成的.dtb文件替换掉板子上/boot目录下的旧文件,然后重启。重启后,你可以通过dmesg | grep can或者ls /sys/class/net/命令查看内核是否成功识别到了CAN设备。如果看到了can0can1这样的网络接口,恭喜你,硬件配置这关就过了。

3. 驱动选择与内核配置:标准CAN vs. CAN FD

设备树配置好,相当于给硬件搭好了舞台。接下来该演员(驱动程序)上场了。RK3568的Linux内核通常提供了两种CAN驱动,这可能是让很多新手困惑的地方:rockchip_can.crockchip_canfd.c。该用哪个?这不是一个随便二选一的问题,选错了可能会导致各种诡异的通信问题。

3.1 两种驱动的本质区别

简单来说,rockchip_can.c是标准的CAN控制器驱动,支持经典的CAN 2.0A/B协议。而rockchip_canfd.c,顾名思义,是支持CAN FD(Flexible Data-rate)协议的驱动。CAN FD是CAN的升级版,主要特点是数据传输速率更快,且一帧数据里能携带的字节数从8个最多可以扩展到64个

但这里有个非常重要的实战细节:根据瑞芯微的文档和一些社区反馈(包括你提供的原始文章里提到的),即使你只使用标准的CAN通信(不启用FD的高速模式),在某些情况下,也可能需要使用rockchip_canfd.c这个驱动。为什么呢?因为rockchip_canfd.c驱动可能包含了针对某些芯片版本或特定通信问题的修复补丁(Patch)。你原文里提到的“对can发送扩展帧概率性变成标准帧,导致接收方存在丢帧”就是一个典型问题,而解决这个问题可能需要应用一个特定的补丁,这个补丁往往就集成在rockchip_canfd.c驱动里。

所以,我的选择建议是这样的:

  • 如果你确定项目只使用经典CAN,且对稳定性要求极高,不想引入任何复杂因素:优先尝试使用rockchip_can.c驱动。它更简单,可能更稳定。
  • 如果你遇到奇怪的丢帧、帧格式错误问题,或者未来有升级到CAN FD的可能:直接使用rockchip_canfd.c驱动。这个驱动是向下兼容标准CAN的,用它来跑标准CAN通信一般没问题,而且它可能已经修复了一些已知的硬件缺陷。

3.2 内核配置与编译

选好了驱动,我们得确保内核编译时把它包含进去。进入你的内核源码目录,执行make menuconfig(或make nconfig)打开配置界面。

  1. 导航到CAN总线子系统:
    -> Networking support -> CAN bus subsystem support
  2. 确保CAN bus subsystem support被选中(按Y键,变成<*>)。
  3. 进入CAN Device Drivers
  4. 在这里找到瑞芯微的驱动选项。它们可能叫:
    • Rockchip CAN controller support(对应rockchip_can.c)
    • Rockchip CAN FD controller support(对应rockchip_canfd.c)
  5. 根据你的选择,将对应的驱动编译进内核(<*>)或者编译为模块(<M>)。对于嵌入式产品,我强烈建议直接编译进内核(<*>),这样系统启动后驱动就直接加载好了,省事。如果选为模块,你还需要手动insmod加载。
  6. 保存配置,退出,然后重新编译内核和模块:make -j$(nproc)make modules_install

编译完成后,将新的内核镜像(比如Image)和设备树文件一起更新到开发板并重启。使用lsmod | grep can可以查看加载的CAN驱动模块,如果驱动编译进内核了,这个命令可能看不到,但可以通过dmesg日志来确认驱动初始化是否成功。

4. 系统配置与基础测试:让CAN接口动起来

内核成功识别了CAN控制器,驱动也加载了,现在我们终于可以在用户空间操作CAN接口了。在Linux系统中,CAN设备被抽象成了网络接口,就像eth0wlan0一样,名字通常是can0can1。我们需要用一些工具来配置和测试它。

4.1 安装CAN工具包

首先,确保你的文件系统里安装了iproute2can-utils这两个工具包。iproute2是现代Linux管理网络接口(包括CAN)的主力工具,can-utils则提供了一系列专门用于CAN测试的命令行工具,如candump,cansend等。

在基于Debian/Ubuntu的系统上,可以这样安装:

sudo apt update sudo apt install iproute2 can-utils

如果是Buildroot或Yocto等嵌入式构建系统,需要在系统配置菜单里选中这些包并重新构建根文件系统。

4.2 配置CAN接口参数

假设我们识别到的接口是can0。在通信之前,必须设置它的波特率启动。这里我们用ip命令(来自iproute2)来操作,它比老旧的ifconfigcanconfig更强大和推荐。

  1. 停止接口(如果之前已启动):sudo ip link set can0 down
  2. 设置比特率(波特率):这是最关键的一步,通信双方(发送和接收设备)的波特率必须严格一致。
    sudo ip link set can0 type can bitrate 500000
    这里把can0的波特率设置为 500kbps(即 500000 bps)。常见的波特率还有 125000 (125k), 250000 (250k), 1000000 (1M) 等。具体用多少,要看你的其他CAN节点设备支持多少。
  3. 启动接口
    sudo ip link set can0 up
  4. 查看接口状态
    ip -details link show can0
    这个命令会输出详细状态,仔细看,里面应该会显示state UP(接口已启动),以及bitrate 500000(波特率设置正确)。如果状态是DOWN或者波特率不对,就需要检查前面的步骤。

4.3 最简单的自发自收测试

为了验证CAN通道本身是否通畅,我们可以做一个“自发自收”的环回测试。这需要将同一个CAN控制器的CAN_HCAN_L短接起来(注意:是同一个控制器的H和L短接,形成环回,不是两个控制器对接)。但更常见的测试方法是,如果你板子上有两个CAN控制器(如can0和can1),可以把它们的CAN_H连到一起,CAN_L连到一起,让它们互相通信。

假设我们连接了can0can1

  1. 打开一个终端,启动candump监听can1接口:
    candump can1
    这个命令会阻塞在这里,等待并打印所有从can1接口接收到的CAN帧。
  2. 打开另一个终端,用cansend通过can0发送一帧数据:
    cansend can0 123#1122334455667788
    这帧数据的含义是:标准帧ID为0x123,数据为8个字节0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88
  3. 如果一切正常,你会在第一个终端(运行candump的)看到类似下面的输出:
    can1 123 [8] 11 22 33 44 55 66 77 88
    这表示can1成功接收到了来自can0的数据。恭喜,你的CAN通信链路基本打通了!

5. 进阶调试与疑难杂症排查

基础测试通过了,但实际项目往往没这么顺利。下面我分享几个我实际遇到过的“坑”以及排查思路,希望能帮你节省大量时间。

5.1 常见问题与排查命令

  • 问题:ip link命令根本看不到can0can1接口。

    • 排查:这说明内核根本没识别到这个设备。第一步,检查dmesg | grep -i can的内核启动日志。看看有没有CAN控制器初始化的成功或失败信息。常见的失败原因有:
      1. 设备树配置错误status不是"okay"pinctrl引脚配置错误,compatible字符串不匹配。
      2. 时钟配置错误assigned-clock-rates设置的值不对,导致驱动初始化失败。可以尝试在设备树里暂时去掉时钟频率设置,让驱动用默认值试试。
      3. 驱动未编译:确认内核配置中确实选中了对应的CAN驱动并已编译。
  • 问题:接口能看到(state UNKNOWN),但无法up,或up后很快又down

    • 排查:这通常是物理层问题。执行ip -details -statistics link show can0,关注输出里的错误计数,比如RX errors,TX errors,bus-error等。如果bus-error在疯狂增长,几乎可以断定是波特率设置错误,或者物理连接有问题(终端电阻、线缆)。CAN总线两端(最远的两个节点)必须各接一个120欧姆的终端电阻,测量CAN_H和CAN_L之间的电阻应该在60欧姆左右。
  • 问题:能upcandump也能看到自己发的数据,但连上其他CAN设备后收不到对方数据,或者对方收不到我的数据。

    • 排查
      1. 波特率一致性:这是最最常见的原因!用示波器或者专业的CAN分析仪,测量一下总线上的实际波形,计算一下比特时间,看看和你软件设置的波特率是否一致。毫厘之差,通信即断。
      2. 帧格式:你发送的是标准帧(11位ID)还是扩展帧(29位ID)?接收方是否配置了相应的过滤器?在cansend命令中,标准帧ID直接写,扩展帧ID需要在后面加个点,如cansend can0 12345678#11
      3. 硬件问题:CAN收发器芯片(如TJA1050)是否损坏?电源是否正常?可以用万用表测量CAN_H和CAN_L对地的电压。当总线空闲时,CAN_H约2.5V,CAN_L约2.5V;有显性位时,CAN_H约3.5V,CAN_L约1.5V。

5.2 性能测试与压力测试

基础通信没问题后,你可能需要测试一下CAN总线的稳定性和性能极限。can-utils工具包里的cangencanbusload就派上用场了。

  • 生成随机流量:用cangen在后台持续生成随机的CAN帧,模拟总线负载。
    cangen can0 -g 10 -I i -L 8 &
    这个命令会在can0上以10毫秒间隔(-g 10)发送随机ID(-I i)、8字节数据(-L 8)的帧。
  • 监控总线负载率:在另一个终端运行canbusload,可以实时查看总线的利用率。
    canbusload can0 500000
    这里需要指定你设置的波特率(如500000)。它会计算当前总线上的数据量占理论最大带宽的百分比。长时间运行,观察负载率是否稳定,有没有错误帧激增。
  • 测试高负载下的稳定性:逐步减小cangen的间隔(比如到1ms),增加数据长度,观察在接近总线理论带宽时,是否会出现大量错误帧或系统卡顿。这能帮你评估当前软硬件配置的稳定性边界。

6. 深入理解:CAN FD配置与高级应用

如果你的项目对数据吞吐量有更高要求,或者需要连接支持CAN FD的新设备,那么配置CAN FD就很有必要了。CAN FD的配置比标准CAN稍复杂一些,因为涉及到两个比特率:仲裁段波特率(和标准CAN类似,用于竞争总线)和数据段波特率(用于实际传输数据,可以更高)。

6.1 设备树与驱动准备

首先,确保你使用的是rockchip_canfd.c驱动,并且在设备树中,compatible属性要设置为"rockchip,canfd-1.0"。时钟配置通常和标准CAN一样。

6.2 使用 ip 命令配置CAN FD参数

配置CAN FD接口的命令格式如下:

# 先关闭接口 sudo ip link set can0 down # 设置FD模式、仲裁段波特率(500k)和数据段波特率(2M) sudo ip link set can0 type can bitrate 500000 dbitrate 2000000 fd on # 启动接口 sudo ip link set can0 up

关键参数解释:

  • bitrate 500000:仲裁段比特率,设为500kbps。
  • dbitrate 2000000:数据段比特率,设为2Mbps。这个值可以比仲裁段高很多,但具体上限取决于你的硬件和收发器支持。
  • fd on:启用CAN FD模式。

6.3 CAN FD数据收发测试

can-utils工具同样支持CAN FD。发送CAN FD帧需要使用-f参数,并且可以指定超过8字节的数据(最多64字节)。

# 发送一帧CAN FD数据,ID为0x555,数据为16个字节 cansend can0 -f 555#00112233445566778899AABBCCDDEEFF # 接收CAN FD帧,也需要使用 -f 参数来正确解析 candump can0 -f

candump的输出中,CAN FD帧会有特殊的标记。同时,强烈建议使用支持CAN FD的硬件分析仪(如Pcan, Vector等)进行对比测试,以确保帧格式和时序完全正确。切换到FD模式后,物理信号质量要求更高,布线干扰等问题会被放大,因此稳定性测试需要更充分。

整个配置和调试过程,从硬件引脚确认到高级FD功能测试,每一步都需要耐心和细致。嵌入式开发就是这样,大部分时间都在和细节较劲。但当你看到candump终端上稳定地滚动着来自其他设备的数据时,那种成就感是非常实在的。希望这份指南能成为你手上的RK3568与外界可靠对话的一块坚实垫脚石。如果在实际操作中遇到了上面没覆盖到的问题,不妨多看看内核的dmesg日志,那里面往往藏着最直接的线索。

http://www.jsqmd.com/news/456042/

相关文章:

  • el-carousel 走马灯 自定义指示器样式:从小圆点到创意设计
  • 完全开源可控!GPT-OSS-20B部署实战,打造个人离线智能助手
  • 2025年3D工业相机技术趋势与选型指南
  • Qt无障碍功能开发:用键盘完全替代鼠标操作按钮的完整方案
  • 基于STM32H723与Si5351的散射参数测量装置设计与实现
  • Office Tool Plus最新版安装Visio全攻略(含激活失败解决方案)
  • 用Shell脚本实现瀚高数据库无人值守安装+定时备份(附日志轮转配置)
  • 从影视特效到无障碍沟通:唇语识别技术的5个落地场景与实现难点
  • PyTorch DLL缺失报错?5步搞定torch_scatter环境配置(附CUDA路径检查)
  • IEC60730 ClassB认证实战:从库文件集成到关键检测项优化
  • 华为云Stack跨VPC通信秘籍:如何用EIP实现虚拟机间高速互访?
  • SecureCRT vs CM野人版深度对比:串口调试工具选型必看的5个性能指标
  • 2024最新版:一键领取美团外卖红包的快捷指令设置教程(附避坑指南)
  • 【软件教程】PMX_Editor进阶指南:从骨骼编辑到刚体物理的实战技巧
  • 【架构解析】28nm混合域CIM:如何用对数ADC与稀疏控制实现72.12TFLOPS/W能效突破
  • 解放双手!用Magic API+Postman自动生成接口文档的5个高效技巧
  • Cesium实战:5分钟搞定动态轨迹绘制与回放(附完整代码)
  • Guohua Diffusion 环境部署保姆级教程:Ubuntu 20.04系统配置
  • 零基础玩转Sonic数字人:无需建模,用ComfyUI一键生成虚拟主播视频
  • ROS机器人开发实战:如何用TF2库搞定多传感器坐标对齐(附避坑指南)
  • 从Chandy-Lamport算法到Flink Checkpoint:图解分布式快照的演进与优化
  • Ostrakon-VL-8B在中央厨房的应用:标准化菜品分量视觉质检
  • SeqGPT-560M与Dify平台集成:打造无代码AI应用
  • SpringBoot 服务迁移至东方通 TongWeb 的实践指南
  • XU316免开发固件实战:如何用MCU配置快速打造Hi-Fi解码器(附评估板开箱)
  • MySQL 8.0性能调优实战:从慢查询到高并发的完整优化指南
  • Emotion2Vec+ Large优化指南:如何获得最佳识别效果?实用技巧分享
  • Binance高频交易实战:从服务器配置到API优化的完整避坑手册
  • Qwen3-ASR-0.6B行业落地:金融尽调访谈语音→结构化要点→风险关键词提取
  • 突破语言壁垒:XUnity AutoTranslator游戏翻译工具全场景应用指南