rk3288 android7.1.2 can功能调试一

前言

        rk3288芯片没有can数据线路,但是客户提出需求要用can通信,硬件就设计了一个简易的转接板,在spi通信线路下挂了一个mcp2515模块,实现spi转can通信。

1、mcp2515电路设计

can收发器

 

2、kernel配置

当前rk3288 kernel源码中已有mcp2515驱动代码,只需打开内核配置即可

kernel/arch/arm/configs/rockchip_defconfig
    +CONFIG_CAN=y
    +CONFIG_CAN_MCP251X=y

 设备树配置

+&spi1 {
+	status = "okay";
+
+	can0: can@0 {
+		compatible = "microchip,mcp2515";
+		pinctrl-names = "default";
+		pinctrl-0 = <&can0_pins>;
+		reg = <0>;
+		clocks = <&clk16m>;
+		spi-max-frequency = <10000000>;
+		interrupt-parent = <&gpio8>;
+		interrupts = <3 IRQ_TYPE_EDGE_FALLING>;
+	};
+};
+
+	clk16m: clk16m {
+		compatible = "fixed-clock";
+		#clock-cells = <0>;
+		clock-frequency = <16000000>;
+	};
+		can0 {
+			can0_pins: can0_pins {
+				rockchip,pins = <8 3 RK_FUNC_GPIO &pcfg_pull_none>;
+			};
+		};

调试遇到问题:

问题1:mcp2515驱动加载失败

 在内核启动过程中,会概率性出现can0节点加载失败问题,分析源码发现,在读取mcp2515模块寄存器是会读取失败,为排除硬件问题,个人买了一个独立的mcp2515模块,经测试发现与硬件工程师设计的模块出现同一问题,猜测可能是驱动问题,检查spi引脚定义,发现当前spi与isp节点下的gpio引脚有复用,考虑到当前系统并未用到isp功能,随即关闭isp节点,修复此问题

 &isp {
-	status = "okay";
+	status = "disabled";
         gpios-cifpower1 = <&gpio2 12 GPIO_ACTIVE_HIGH>;
         gpios-cifpower2 = <&gpio2 13 GPIO_ACTIVE_HIGH>;
 	pinctrl-0 = <&isp_mipi &cifpower_gpio>;
-- 

问题2:can0 节点启动失败

调试时发现在执行ifconfig can0 up命令是,会低概率的出现can设备open失败的情况,再次执行命令可以正常启动can设备,在git代码仓库中查找到kernel4.4源码关于mcp2515驱动更新部分,发现有处理过这种情况,随即将该补丁移植过来

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/drivers/net/can?h=linux-4.4.y&id=62db62a4313444a69f640a3250cef4646c2aceeb

@@ -627,7 +627,7 @@ static int mcp251x_setup(struct net_device *net, struct mcp251x_priv *priv,
 static int mcp251x_hw_reset(struct spi_device *spi)
 {
 	struct mcp251x_priv *priv = spi_get_drvdata(spi);
-	u8 reg;
+	unsigned long timeout;
 	int ret;
 
 	/* Wait for oscillator startup timer after power up */
@@ -640,11 +640,20 @@ static int mcp251x_hw_reset(struct spi_device *spi)
 
 	/* Wait for oscillator startup timer after reset */
 	mdelay(MCP251X_OST_DELAY_MS);
-	
-	reg = mcp251x_read_reg(spi, CANSTAT);
-	if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
-		return -ENODEV;
 
+	/* Wait for reset to finish */
+	timeout = jiffies + HZ;
+	while ((mcp251x_read_reg(spi, CANSTAT) & CANCTRL_REQOP_MASK) !=
+	       CANCTRL_REQOP_CONF) {
+		usleep_range(MCP251X_OST_DELAY_MS * 1000,
+			     MCP251X_OST_DELAY_MS * 1000 * 2);
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(&spi->dev,
+				"MCP251x didn't enter in conf mode after reset\n");
+			return -EBUSY;
+		}
+	}
 	return 0;
 }

Guess you like

Origin blog.csdn.net/qq_32645109/article/details/121261422