本项目中RK3399PRO由于没有原生can控制器,因此需要用到转接芯片;本次使用的mcp251x芯片,SPI转CAN;
报错信息描述
使用的can启动设置命令如下
ip link set can0 down
ip link set can0 type can bitrate 500000
ip link set can0 up
执行到第三条也就是can0 up的时候会报错
root@bionic:~# ip link set can0 up
RTNETLINK answers: Invalid argument
解决思路
应用层使用ip命令最终也是会调用到驱动中的相关函数,既然如此,那就去查一下驱动吧,可以看见注册了一个net_device_ops操作方法结构体,这个结构体中函数指针指向的函数就是上层操作的时候调用的函数,当执行ip link set can0 up的时候就会去调用ops结构体中的open函数,所以猜测问题肯定出在mcp251x_open这个函数中;
如果直接波特率都不设置呢,执行会有什么结果呢?果然,会报刚才的报错,查看一下打印log,提示是波特率没有设置,所以这里可以得出初步结论net_device_ops中的open指针指向的函数如果返回的不是0,那么就会报这个错误;
为了验证这个想法,可以执行在open多加几条打印函数,看看会卡在哪里,按照步骤复现之后果然第一次执行并没有完整的走完整个open函数,所以问题已经很明确了,定位到执行出错的函数查看是什么原因导致的错误。
通过继续加打印,定位到问题出在下图所示的函数中,在这个函数中,读取can的状态出了问题,那为什么第二次读取的时候就能正常读取呢?
通过打印发现读取的值第一次是0xff显然不正确,再次执行指令读取到的值是0x80为什么会出现这种情况呢?是spi出了问题还是这个芯片第一次读取数据有问题呢?
由于spi是soc原生控制器直出,问题的概率很低,所以排查方向优先放在mcp251x芯片上;在出问题的这个函数中,是对芯片做了一个复位操作,并且等待5ms之后去读复位状态,那么是不是问题就出在这个等待时间上,查看datasheet中并没有相关的定义,尝试加长延时时间到15ms;
烧录之后再次测试问题解决!!!