编辑
2025-03-03
记录知识
0
请注意,本文编写于 116 天前,最后修改于 59 天前,其中某些信息可能已经过时。

目录

一:can的驱动
二:命令
2.1 查看can的状态
2.2 设置can的采样点
2.3 开启can测试
2.3 开启can回环测试
2.4 接收和发送信息
2.5 调试can数据
2.6 确定can的错误帧
2.7 日志
2.8 中断上下文
2.9 提高can中断的实时响应

CAN(Controller Area Network)是一种有效支持分布式控制或实时控制的串行通信网络。CAN总线是一种在汽车上广泛采用的总线协议,被设计作为汽车环境中的微控制器通讯,公司项目逐渐朝车载领域发展,而车载领域使用can的场景越来越多,这里分析一下can的调试技巧,有助于排查can总线的问题

一:can的驱动

drivers/net/can/rockchip/rockchip_can.c drivers/net/can/rockchip/rockchip_canfd.c

rk3588有两个can驱动,均可通过设备树自由选择,默认可选canfd通讯,则设备树如下配置

can0: can@fea50000 { compatible = "rockchip,can-2.0"; reg = <0x0 0xfea50000 0x0 0x1000>; interrupts = <0 341 4>; clocks = <&cru 112>, <&cru 111>; clock-names = "baudclk", "apb_pclk"; resets = <&cru 185>, <&cru 184>; reset-names = "can", "can-apb"; pinctrl-names = "default"; pinctrl-0 = <&can0m0_pins>; tx-fifo-depth = <1>; rx-fifo-depth = <6>; status = "disabled"; }; &can0 { assigned-clocks = <&cru 112>; assigned-clock-rates = <200000000>; status = "okay"; };

真的can总线,默认可以调整其时钟的频率,默认是200M。如遇到分频不精确,可以调整时钟源为其他值,从而提高can总线的采样点

二:命令

2.1 查看can的状态

ip -details -statistics link show can0 2: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10 link/can promiscuity 0 minmtu 0 maxmtu 0 can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 1 bitrate 250000 sample-point 0.868 tq 40 prop-seg 42 phase-seg1 43 phase-seg2 13 sjw 1 rockchip_canfd: tseg1 1..128 tseg2 1..128 sjw 1..128 brp 1..256 brp-inc 2 clock 99000000 re-started bus-errors arbit-lost error-warn error-pass bus-off 12020 0 0 12132 3438 12450 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 RX: bytes packets errors dropped overrun mcast 320320 40040 0 0 0 0 TX: bytes packets errors dropped carrier collsns 0 0 0 12020 0 0

这里有如下信息可以着重看到

a.state can总线的状态 b.bitrate 比特率 c.sample-point 采样点 d.TX,RX 数据包状态

2.2 设置can的采样点

ip link set can0 type can tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1

通过设置如上参数,可以修改can的采样,也可以直接设置比特率来自动计算采样点

ip link set can0 type can bitrate 250000

2.3 开启can测试

ip link set can0 down ip link set can0 up type can bitrate 250000 ip link set can0 up while true do cansend can0 00000000#0000000000000000 done

上述命令可以直接打开can0设备,并发送默认数据

2.3 开启can回环测试

ip link set can0 down ip link set can0 up type can bitrate 250000 loopback on ip link set can0 up while true do cansend can0 00000000#0000000000000000 done

上述可以直接测试can的回环

2.4 接收和发送信息

# 接收can信息 candump can0 > can_recv.log & # 发送can信息 cansend can0 123#1122334455 cansend can0 5A1#11.2233.44556677.88 cansend can0 1F334455#1122334455667788

2.5 调试can数据

因为can的数据通过net skb上报,所以解析skb数据即可确定接收和发送的can数据信息。如下函数

static void skb_dump(struct sk_buff *skb, struct net_device *dev){ int i = 0; if(!skb || !dev){ pr_err("%s: bad param\n",__FUNCTION__); goto out; } printk(KERN_CONT "Kylin:Can packets(len=%d): ",skb->len); for (i = 0; i < skb->len; i++){ printk(KERN_CONT "%02x", *(skb->data + i)); } printk(KERN_CONT "\n"); out: return; }

然后只需要将skb_dump函数加入接收可发送的处理中即可。

2.6 确定can的错误帧

对于接收到的can中断,主要有如下中断

#define RX_FINISH_INT BIT(0) #define TX_FINISH_INT BIT(1) #define ERR_WARN_INT BIT(2) #define RX_BUF_OV_INT BIT(3) #define PASSIVE_ERR_INT BIT(4) #define TX_LOSTARB_INT BIT(5) #define BUS_ERR_INT BIT(6) #define RX_FIFO_FULL_INT BIT(7) #define RX_FIFO_OV_INT BIT(8) #define BUS_OFF_INT BIT(9) #define BUS_OFF_RECOVERY_INT BIT(10) #define TSC_OV_INT BIT(11) #define TXE_FIFO_OV_INT BIT(12) #define TXE_FIFO_FULL_INT BIT(13) #define WAKEUP_INT BIT(14)

而关于BUS_ERR的错误,有如下情况

#define BIT_ERR 0 #define STUFF_ERR 1 #define FORM_ERR 2 #define ACK_ERR 3 #define CRC_ERR 4

对应情况可以进去调试即可。

2.7 日志

关于netdev_dbg的日志,可以通过如下步骤

a. #define DEBUG 在驱动内部定义 b. 设置日志等级为8

而其他的netdev_*日志,可直接设置日志等级为8即可查看,如

dmesg -n8

2.8 中断上下文

针对can的问题,可以先确定中断

cat /proc/interrupts | grep can

查看硬件中断是否正常

然后再确定软中断

cat /proc/softirqs CPU0 CPU1 CPU2 CPU3 CPU4 CPU5 CPU6 CPU7 HI: 2834 1 1 3 0 0 0 0 TIMER: 7791 33602 36340 57451 22095 6063 31674 5003 NET_TX: 2596 9 7 2 1 3870 2639 3561 NET_RX: 33128 100 36 307 141 3876 2662 21700 BLOCK: 7154 17766 14324 14861 13713 2332 2492 1812 IRQ_POLL: 0 0 0 0 0 0 0 0 TASKLET: 160 2 1 2 1 1 75 3 SCHED: 85621 59461 52573 172213 82530 16771 32225 13479 HRTIMER: 0 0 0 0 0 0 0 0 RCU: 77962 44178 37468 71517 57343 36644 33600 27705

确定NET_RX是否正常,如不正常,则can驱动内的netif_rx调用太频繁

2.9 提高can中断的实时响应

1)dts中去掉所有:cpu-idle-states = <&CPU_SLEEP>; 2)设置成性能模式:echo performance > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor 3)绑定can的中断到一个特定的cpu上: irq_set_affinity_hint(ndev->irq, get_cpu_mask(num_online_cpus() - 1));