rk3588适配MCP2515 SPI转CAN

目录

原理图部分

DTS部分

驱动的复位代码

SPI调试

测试命令

[ID 波形](#ID 波形)

spi驱动解绑

[CAN 压测](#CAN 压测)

PC单向压测0.5ms

PC单向压测1ms

单板发送

CPU占用率

协议栈

总结


原理图部分

DTS部分

\kernel\drivers\net\can\spi\mcp251x.c

除了SPI及CAN 部分,另外有INT# \RST#管脚及时钟配置,此处使用了16M。芯片本身支持8M和16M两种。

复制代码
/ {
    can3_osc: can3-osc {
        compatible = "fixed-clock";
        #clock-cells = <0>;
        clock-frequency = <16000000>;
    };
};
/* 中断引脚电气配置 */
&pinctrl {
    mcp2515 {     
    mcp2515_int_pins: mcp2515-int-pins {
        rockchip,pins = <3 RK_PC7 RK_FUNC_GPIO &pcfg_pull_none>;
    };
    };
   
};


&spi4 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = <&spi4m1_cs0 &spi4m1_pins>;  
    max-freq = <10000000>;
    
    can3: mcp2515@0 {
        status = "okay";
        compatible = "microchip,mcp2515";
        reg = <0>;
        spi-max-frequency = <10000000>;
        
        interrupt-parent = <&gpio3>;
        interrupts = <RK_PC7 IRQ_TYPE_LEVEL_LOW >;  /* GPIO3_C7 */
        
        pinctrl-names = "default";
        /* 中断引脚 pinctrl 配置 */
        pinctrl-0 = <&mcp2515_int_pins>;
        
         /* 复位引脚配置 */
      //    reset-gpios = <&gpio3 RK_PC6 GPIO_ACTIVE_HIGH>;   /* GPIO3_C6 */

        clocks = <&can3_osc>;
        vdd-supply = <&vcc_3v3_s3>;
        xceiver-supply = <&vcc_3v3_s3>;
    };
};

注意这里重点配置了低电平触发,网上有很多配置为下降沿的教程。

复位的配置被注释掉了,理由如下:

实际上该芯片支持两种复位方式,通过其中一种复位即可。

驱动的复位代码

在probe时,调用了spi 命令对芯片进行复位操作。

复制代码
static int mcp251x_hw_reset(struct spi_device *spi)
{
	struct mcp251x_priv *priv = spi_get_drvdata(spi);
	u8 value;
	int ret;

	/* Wait for oscillator startup timer after power up */
	mdelay(MCP251X_OST_DELAY_MS);

	priv->spi_tx_buf[0] = INSTRUCTION_RESET;
	ret = mcp251x_spi_write(spi, 1);
	if (ret)
		return ret;

	/* Wait for oscillator startup timer after reset */
	mdelay(MCP251X_OST_DELAY_MS);

	/* Wait for reset to finish */
	ret = mcp251x_read_stat_poll_timeout(spi, value, value == CANCTRL_REQOP_CONF,
					     MCP251X_OST_DELAY_MS * 1000,
					     USEC_PER_SEC);
	if (ret)
		dev_err(&spi->dev, "MCP251x didn't enter in conf mode after reset\n");
	return ret;
}

SPI调试

将设备配置为spidev,以便调试spi的通路

复制代码
&spi0 {
    status = "okay";
    #address-cells = <1>;
    #size-cells = <0>;
    pinctrl-names = "default";
    pinctrl-0 = <&spi0m3_cs0 &spi0m3_pins>; 
    num-cs = <1>;  /* 或按需设置,例如 <1> 只使用CS0 */

    spidev@0 {
        compatible = "rockchip,spidev";
        reg = <0>;
        spi-max-frequency = <1000000>;
    };
};

测试命令

apt-get install spi-tools

读取ID

复制代码
printf '\x9F\x00\x00\x00' | spi-pipe -d /dev/spidev0.0 -b 4 -n 1 -s 100000 |hexdump -C
00000000  00 ef 40 18                                       |..@.|
00000004

参数含义: -b (--blocksize): 数据块大小

这个参数设定一个数据块的大小,单位是字节 (Bytes)。

例如 -b 4:告诉 spi-pipe,把数据切成一个个 4字节 的小块来处理。

-n (--number): 数据块数量

这个参数设定要传输多少个这样的数据块。

例如 -n 10:表示总共要传输 10个 数据块。

特殊值 -1:一个非常有用的值,表示连续不间断地传输。这在你想用示波器长时间观察 CLK(时钟)或 CS(片选)信号时特别方便。

如下的命令在读取ID时,虽然信号MOSI量到的数据OK,但MISO无输出。

复制代码
printf '\x9F' | spi-pipe -d /dev/spidev0.0 -s 100000 | hexdump -C (命令不可行)

spi-config -d /dev/spidev0.0 -q
/dev/spidev0.0: mode=0, lsb=0, bits=8, speed=10000000, spiready=0

ID 波形

命令4B 。

第一个低电平非数据位,从第二个低电平开始0100 1011=4B

MISO 返回数据

如果此管脚仅仅是抖一下,可能是CS控制不对,不一定是硬件问题。

0x55 通过上述命令可以发个0x55 ,虽然不是正规命令,但可以分析MOSI是否正常。0x55波形如下:

spi驱动解绑

有时为了隐藏设备,避免用户误操作,可以通过如下命令卸载设备节点及重新恢复。

|---------------------------------------------------------|
| echo -n "spi0.0" > /sys/bus/spi/drivers/spi-nor/unbind |
| |
| echo -n "spi0.0" > /sys/bus/spi/drivers/spi-nor/bind |

CAN 压测

PC单向压测0.5ms

按照如下参数配置,PC发送,单板接收。单板不发送。总线负载不到30%

复制代码
ip -details -statistics link show can3
6: can3: <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 restart-ms 0
          bitrate 1000000 sample-point 0.750
          tq 125 prop-seg 2 phase-seg1 3 phase-seg2 2 sjw 1 brp 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          2          2          0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
    RX:  bytes packets errors dropped  missed   mcast
       3199969  400018     13       0       0       0
    TX:  bytes packets errors dropped carrier collsns
       1600000  200000      0       0       0       0
"

PC单向压测1ms

5从100万都没有丢包

第一次测试

第二次测试

单板发送

复制代码
cangen can0 -g 1 -I 101 -L 8 -D 1122334455667788 -x -n 100000 -p 1  (压测)

p 参数可以在发送缓存满时重试。

CPU占用率

复制代码
  2154 root      20   0   16016   9184   7300 S  28.4   0.2   1:04.92 sshd
   2045 root     -51   0       0      0      0 D  15.2   0.0   0:34.21 irq/124-spi4.0
   2207 root      20   0    2272    772    696 S  13.9   0.0   0:31.91 candump
    201 root      20   0       0      0      0 S   9.6   0.0   0:22.49 spi4

协议栈

cat /proc/net/can/stats

mcp251x_can_ist

复制代码
	if (intf & CANINTF_ERRIF) {
			/* Handle overflow counters */
			if (eflag & (EFLG_RX0OVR | EFLG_RX1OVR)) {
				if (eflag & EFLG_RX0OVR) {
					net->stats.rx_over_errors++;
					net->stats.rx_errors++;
				}
				if (eflag & EFLG_RX1OVR) {
					net->stats.rx_over_errors++;
					net->stats.rx_errors++;
				}
				can_id |= CAN_ERR_CRTL;
				data1 |= CAN_ERR_CRTL_RX_OVERFLOW;
			}
			mcp251x_error_skb(net, can_id, data1);
		}

这里即使有overrun的统计,驱动也会将报文上报的协议栈层,进而上报到数据层面。这会导致在协议栈层看到的报文数量比实际大,例如PC发送20万,有4个over错误,这时在协议栈层面看到的统计可以是20万04个。

taskset -c 7 candump -s 2 can3

echo 2 > /proc/irq/100/smp_affinity

3588 canfd

复制代码
rockchip_canfd fea50000.can can0: incorrect/missing data bit-timing

用如下命令可以解决上报错

复制代码
 ip link set can0 type can bitrate 1000000 dbitrate 4000000 fd on

ip -details -statistics link show can1
4: can1: <NOARP,UP,LOWER_UP,ECHO> mtu 72 qdisc pfifo_fast state UP mode DEFAULT group default qlen 10
    link/can  promiscuity 0 minmtu 0 maxmtu 0
    can <FD> state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 1
          bitrate 1000000 sample-point 0.747
          tq 10 prop-seg 36 phase-seg1 37 phase-seg2 25 sjw 1 brp 2
          rockchip_canfd: tseg1 1..128 tseg2 1..128 sjw 1..128 brp 1..256 brp_inc 2
          dbitrate 1000000 dsample-point 0.727
          dtq 90 dprop-seg 3 dphase-seg1 4 dphase-seg2 3 dsjw 1 dbrp 18
          rockchip_canfd: dtseg1 1..32 dtseg2 1..16 dsjw 1..16 dbrp 1..256 dbrp_inc 2
          clock 198000000
          re-started bus-errors arbit-lost error-warn error-pass bus-off
          0          0          0          0          0          0         numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535
    RX:  bytes packets errors dropped  missed   mcast
         83336   10417      0       0       0       0

CAN FD 模式在驱动层已经成功启用mtu 72can <FD>

总结

该芯片支持缓存两帧数据。如果对端发送过快,例如本例测试的0.5ms间隔,会有少量溢出及丢包(丢包只存在统计中,例如对端发送20万,本端收到19万8,有几个包丢失)

此外该芯片不支持CANFD,属于老一代芯片。对于当前的需求不友好。

实际业务的发包间隔及需求才是选型的王道。

相关推荐
楼兰公子4 天前
RK3588 + Linux7.0.3 网络工程调试错误速查手册
linux·网络·3588
时光の尘11 天前
【嵌入式大厂面经】·CAN总线常见考点(持续更新中···)
stm32·单片机·mcu·物联网·can·ack
不知秋88015 天前
PCAN-View核心功能使用手册
can·以太网·codesys·peakcan·pcan-view
嵌软小白呗20 天前
Autosar-SecOC功能详解(一)
e2e·can·autosar·crc·secoc
W.W.H.24 天前
嵌入式系统硬件接口全景图
经验分享·uart·iic·gpio·spi
zmj3203241 个月前
UDS 0x27 安全访问(种子 / 密钥 Seed-Key) 的用法、流程、算法、存储位置、安全机制
安全·can·诊断·uds·27服务
南金研高新科技(南京)有限公司1 个月前
南金研CAN数采仪助力吉利远程商用车售后问题处理
can·硬件·记录仪
我在人间贩卖青春1 个月前
SPI总线
stm32·spi
zmj3203241 个月前
工业通信--CRC校验分类及实现细节
人工智能·单片机·数据挖掘·can