我使用带有 PiCAN 板的 Raspberry Pi,该板使用 MCP2515 CAN 控制器。
我使用 SocketCAN 通过我编写的应用程序读取和写入 CAN 消息。
运行几周后没有出现问题,控制器现在处于“已停止”状态。
STOPPED 状态和 BUS-OFF 状态有什么区别?
如果 CAN 总线上发生太多错误,设备是否会进入 BUS-OFF 状态,并且如果将设备设置为关闭(ip link set canX down),设备是否会进入 STOPPED 状态?
还有其他方法可以让设备进入 STOPPED 状态吗?我无法找到我的应用程序如何设置设备的方法。
ip -details -statistics link show can0
3: can0: <NOARP,ECHO> mtu 16 qdisc pfifo_fast state DOWN mode DEFAULT group default qlen 10
link/can promiscuity 0
can state STOPPED restart-ms 100
bitrate 250000 sample-point 0.875
tq 250 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
clock 8000000
re-started bus-errors arbit-lost error-warn error-pass bus-off
0 0 0 146 139 0 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
RX: bytes packets errors dropped overrun mcast
787700920 151606570 24 0 24 0
TX: bytes packets errors dropped carrier collsns
6002905 5895301 0 0 0 0
我在 NXP iMX6 上运行的应用程序遇到了 STOPPED 问题。启动许多应用程序时会发生这种情况,所有 CAN 设置都是新鲜的。更改设置是接口关闭、更改、接口打开的顺序。在 CAN 内核模块中,这最终会导致大量的 close 和 open 调用。有一次,open 开始不断失败,在 canconfig 或 ip link 中报告 STOPPED 状态。只有重新启动才有帮助。
NXP iMX6 使用内核的 flexcan 模块,在我们使用的内核 (toradex_4.14-2.3.x-imx) 中,该模块在调用 pm_runtime_get_sync() 时存在问题:即使返回值为正,它也会认为失败。其他模块仅以这种方式解释负值。
所以我改变了flexcan模块,到目前为止它可以工作。我在下面引用我的补丁。即使 Raspberry Pi 使用其他模块或内核版本,您也可以检查是否存在相同的问题。
祝你好运, 索伦
From 1142dfb7b9f26e5882724689e2d110d09479714e Mon Sep 17 00:00:00 2001
From: Solon
Date: Mon, 28 Aug 2023 08:11:56 +0200
Subject: [PATCH] can: flexcan: handle pm_runtime_get_sync() errors
Modelled after other can modules. Only negative return values from
pm_runtime_get_sync() are considered errors and lead to a call to
pm_runtime_put_noidle() to sync the power management for the next call.
---
drivers/net/can/flexcan.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c
index 550ae1f8b318..a8a40ef59c70 100644
--- a/drivers/net/can/flexcan.c
+++ b/drivers/net/can/flexcan.c
@@ -1479,8 +1479,11 @@ static int flexcan_open(struct net_device *dev)
int err;
err = pm_runtime_get_sync(priv->dev);
- if (err)
+ if (err < 0) {
+ pm_runtime_put_noidle(priv->dev);
+ dev_err(priv->dev, "%s: pm_runtime_get_sync failed(%d)\n", __func__, err);
return err;
+ }
err = open_candev(dev);
if (err)
@@ -1855,7 +1858,8 @@ static int flexcan_probe(struct platform_device *pdev)
pm_runtime_enable(&pdev->dev);
err = pm_runtime_get_sync(&pdev->dev);
if (err < 0) {
- dev_err(&pdev->dev, "pm_runtime_get failed(%d)\n", err);
+ pm_runtime_put_noidle(&pdev->dev);
+ dev_err(&pdev->dev, "%s: pm_runtime_get_sync failed(%d)\n", __func__, err);
goto failed_rpm_disable;
}
--
2.30.2
您需要熟悉CAN总线设备的ERROR ACTIVE、ERROR PASSIVE、BUS OFF错误状态,以及何时需要手动重启CAN通信。
所有相关信息都可以在以下链接之一找到: