转自http://www.xuebuyuan.com/2055253.html

MCP2515是一SPI转CAN总线的芯片,对于CPU来说,CPU就是主设备,SPI就是从设备,所以在内核里,MCP2515就是一个SPI设备,而SPI设备在内核中的结构是对应的,是一个spi控制器对应一个SPI设备,也就是一个spi_master对应一个spi设备,而SPI设备在内核中,尤其是新的内核中(新的内核越来越注重分层和分离的结构),则是在驱动中填充spi_driver驱动信息,在板载中填充spi_board_info信息.

要移植好SPI设备,有几点是要注意的.

1,make menuconfig中,CONFIG_SPI_S3C54XX和SPI_SPIDEV这两个及其相关的选项需要打开,因为第一个是spi控制器(驱动在dev-spi.c里),第二个就是SPI设备.

2,当然作为主角的MCP251x.c的驱动选项页当然要打开,内核中,MCP251X.C这个源码已经包含,在drivers/net/can下,检查下Makefile和Kconfig,然后menuconfig里打开编译选项,这一步大概也不会有什么问题.唯一要注意的是在此源码中,需要改一下DEVICE_NAME这个宏,要跟下面提到的modalias一致,因为这是用来match用的.

3,SPI控制器好了,SPI设备驱动有了,那就还差的是SPI控制器配置,SPI的设备信息等的填充了.在/arch/arm/mach-exynos/下的machine_init函数所在源码文件中添加填充

static struct s3c64xx_spi_csinfo spi0_csi[]=
//这个结构体用来设置片选引脚的
{
[0] = {
.line = //片选引脚
.set_level = gpio_set_value,
.fb_delay = 0x2,
},
};
static struct mcp251x_platform_data mcp251x_info
//这个结构体用来设置振荡器频率的,至于剩下的参数要不要设,需要具体看原理图的接线情况,头文件在
//\include\linux\can\platform\mcp251x.h
static struct spi_board_info spi0_board_info[]=
//这个结构体用来配置SPI设备,也就是对应MCP251X.c这个设备驱动用的,注意modalias要对上.
{
.modalias = ,
//要跟mcp251x.c上的DEVICE_NAME宏对上
.max_speed_hz = ,//CPU支持最高50MHz,但MCP2515芯片最高只支持到10MHZ,这里要好好权衡一下
.bus_num = ,
//SPI总线的选择,CPU提供3条SPI总线
.chip_select = ,//SPI总线上第几个设备的选择
.mode = SPI_MODE_0,//关于CPOL CPHA这2个值得选择,有4种模式 00 01 10 11
.platform_data = &mcp251x_info,//传给mcp251x.c驱动用的参数,就是上面的一个结构体.
.controller_data = &spi0_csi[0],//上面的一结构体,片选所用
.irq = ,//mcp2515芯片有一中断脚连到CPU,把复用后的中断量复制在此
}

这三个结构体填充完后(记得加上相应的头文件),就在static struct platform_device上添加初始化用的设备的变量exynos_device_spi的地址,这是给machine_init函数在添加这三个变量的时候用的,

struct clk *sclk = NULL;
struct clk *prnt = NULL;
struct device *spi0_dev = &exynos_device_spi0.dev;
sclk = clk_get(spi0_dev, "dout_spi0");
if (IS_ERR(sclk))
dev_err(spi0_dev, "failed to get sclk for SPI-0\n");
prnt = clk_get(spi0_dev, "mout_mpll_user");
if (IS_ERR(prnt))
dev_err(spi0_dev, "failed to get prnt\n");
if (clk_set_parent(sclk, prnt))
printk(KERN_ERR "Unable to set parent %s of clock %s.\n",
prnt->name, sclk->name);

clk_set_rate(sclk, 10 * 1000 * 1000);
clk_put(sclk);
clk_put(prnt);

if (!gpio_request(片选引脚宏地址, 片选引脚名)) {
gpio_direction_output(片选引脚宏地址, 1);
s3c_gpio_cfgpin(片选引脚宏地址, S3C_GPIO_SFN(1));
s3c_gpio_setpull(片选引脚宏地址, S3C_GPIO_PULL_UP);
exynos_spi_set_info(0, EXYNOS_SPI_SRCCLK_SCLK,
ARRAY_SIZE(spi0_csi));
}
spi_register_board_info(spi0_board_info, ARRAY_SIZE(spi0_board_info));

而这里主要是注册SPI设备和SPI的时钟配置,配置好这些后正常的话就已经把mcp2515的can0设备驱动移植好了.
如果在这里出了问题,不防先设置好spidev.c的驱动,先调好spi的控制器,再把spidev替换成mcp2515.

4,CAN总线在新版本的内核中,并不是以字符设备的形式出现的,原因内核也有说明,主要是因为内核把CAN设备看成了网络设备(当然由于CAN设备的特殊性,CAN是没有IP地址可言的),需要用到socketcan协议,所以要想运行CAN总线,那么就要再menuconfig上打开can的协议(打开项在Networking support-->CAN bus subsystem support下).

5,内核部分完成后,就到Android部分了,由于不是字符设备,不能对其进行简单的读写操作,所以要用到2个工具,iproute2 和 canutil
iproute2在安卓源码上就有,external/iproute2,
而canutil则在网上可以下到,而是用canutil内的命令,还需要用到libsocketcan的库.

调试总结:
在刚开始调试的时候,spi在内核中的框架并不熟悉,困惑于spidev.c和mcp251x.c之间的关系怎么处理,spi的设备怎么设置时钟,为什么mcp251x.c驱动调出来之后再spi下的目录里没有mcp251x的字符设备可供调用等等.
其实spidev跟mcp251x是处于同一位置的spi设备,都由spi控制器控制,或许是可以在spi0_board_info结构体填充chip_select的时候填上排序的序号,可是最后没有用上,因为spidev不是一个实质的设备.而spi下没有mc251x的字符设备供调用是因为mcp251x的驱动节点在net/can0里,意味着内核把它注册为网络设备.这里在调试的时候最好还是先用spidev来先调好spi控制器,因为spidev的驱动提供了可调用的 spi下的字符设备节点,而在内核中,已经提供了spi设备的测试代码在document/spi下,在编译好后放到开发板上,并将spi发送接收的2条线接上,那么正常的情况下spi就能实现自收自发,这时再去调试mcp251x.c的驱动,就可以不用担心spi在系统上出太大问题了(不过关于时钟这一部分,需要好好地配置).
然后再测试can接口的时候,iproute2这个工具出现过bitrate这个参数无法辨认的情况,其实是在iproute2/ip目录下对iplink_can.c并没有实际调用,归根到底,是在编译android的时候,某些iplink_can.c内某些头文件没有顺利调用导致最后ip命令的参数不支持can,最后吧头文件的include写成了相对地址来调用,就可以了.
而对于canutil这个工具,要顺利编译好,也经过了一些波折,自己用的编译器比较多,环境变量不全,是个挺麻烦的问题,最后自己添加了环境变量,同时无视了伯克利相关的库后,勉强编译成功了cansend candump canecho和cansequence四个工具去调用.
现在,使用ip link set can0 type can bitrate xxx这些命令来设置波特率,用cansend和candump来发送接收,能用示波器看到波形了,但是数据在接收那边还没能出来,这个在之后得后续更新原因.

6、本文主要验证Linux-imx_share\Documentation\spi目录下spidev_test.c的测试例程,能否正常控制SPI接口。在命令行下输入ifconfig -a,已经出现can0信息



SPI,MCP2515调试总结相关推荐

  1. RK3288平台 SPI接口调试步骤

    RK3288平台 SPI接口调试步骤 代码路径 drivers/spi/spi.c                             spi驱动框架         drivers/spi/sp ...

  2. MCP2515调试笔记----初始化注意事项

    在调试基于F103单片机的MCP2515时,怎么调试都不正常,用的还是以前调试过的代码,隔了一段时间后再重新运行就不行了: 于是单步运行调试,没想到,单步运行调试竟然成功了:于是想到是延时的问题,在初 ...

  3. SPI/I2S调试心得与经验总结

    一.调试中首先检查SPI使能总线是否正确: 检查时序(现有时钟,后片选拉低),接收时必须有发送才能有时钟 二.对照flash芯片手册查看SPI时序 三.检查状态位 1.查询标志位: 1)while(S ...

  4. (30)SPI接口调试丢数据解决(FPGA不积跬步101)

    1)遇到问题 FPGA与微处理器进行数据交互用到了SPI接口总线,SPI总线已经很成熟了,网上也有好多开源代码.但是,项目开发调试中也遇到SPI通信丢帧验证问题. 2)解决方法 a.设计思路为:SPI ...

  5. android spi串口调试,PIC入门3,SPI通信和串口调试实验

    原标题:PIC入门3,SPI通信和串口调试实验 MSSP模块工作于SPI主控方式,这个可以直接在实验板上执行. 程序: //适合3EPIC实验板,配置PIC的MSSP模块工作于SPI主控方式下, // ...

  6. STM32环境下AS5048A14位磁旋转编码器SPI通讯调试记录——我学到的东西、遇到的问题、解决的过程

    ❤ 2019.3.16 事情是这样的. 在很多天以前,老师接了个项目,问我有没有意向,我谨慎的表达了我对新事物的好奇心,对新知识的求知欲,同时又委婉的表达了我的能力有限的实际情况,然后我以为事情就这么 ...

  7. rv1126平台spi屏调试

    我们使用的rv1126平台,屏ic ST7789,硬件使用6bit,由于不是8bit的,所以显示的颜色没有那么丰富 1.硬件原理图 2.dts配置 &rgb {status = "o ...

  8. BF609 CCES下的SPI驱动调试--就这样被它折磨了一周

    在CCES环境下,ADI 自带了驱动接口函数,为驱动调试省下一大杯子事:但是这为人熟知的SPI,在调试过程中还是遇到了挫折,几度想撞墙: 最大的折磨:死机. 实际的SPI驱动接口是全双工功能的,所以传 ...

  9. MCP2515调试经验01

    MCP2515有三个CAN发送缓冲区,可以通过TXBnCTRL中的TXP[1:0]配置 发送优先级,当两个或者3个缓冲区配置相同优先级时,拥有最大缓冲区编号的缓冲区优先发送.这可能造成缓冲区0的消息发 ...

最新文章

  1. 达沃斯议程对话会:张亚勤解读人工智能发展 3R 原则
  2. tensorflow中Tensorboard的用法
  3. 毕业设计:基于Springboot实现求职招聘,校园招聘系统
  4. Hadoop组件基本操作
  5. 学习笔记(3.23)
  6. storm 动态设置并发度
  7. MySQL数据库备份工具mysqldump的使用(转)
  8. 汇编语言-010(循环移位ROL,ROR 、进位循环进位RCL,RCR 、有符号数溢出 、双精度移位SHLD,SHRD、SHL和ADD计算 、位运算应用)
  9. Spring Boot(十四):spring boot整合shiro-登录认证和权限管理
  10. Python学习---Django的基础操作180116
  11. Array.of()方法
  12. 35 岁财务自由的小马哥,我想跟他学学!
  13. 计算机三级嵌入式系统易错题总结
  14. 腾讯没有梦想,阿里没有盟友?
  15. python语法学习第七天--文件
  16. Axure9桌面无法显示图标
  17. window下ruby的下载与gem安装
  18. 网络随堂笔记2(计算机网络下三层硬件及拓扑结构)
  19. Unity 实现简单的人物对话系统
  20. U盘安装Linux系统

热门文章

  1. 【转】Unity实现镜头自由移动,第一人称移动
  2. Vue.js 详细介绍
  3. postfix exmail 邮件系统
  4. Dart 虚拟机运行原理
  5. 市场营销策划的原则及主要步骤
  6. 2080Ti深度学习环境配置及常用软件安装
  7. 合格的建筑木方具备哪些特征
  8. CFTC主席:区块链和加密货币是改变当今市场的两个关键因素
  9. 新手建站指南 让你少走弯路
  10. 快速添加管家婆软件里的商品条码(标准条码库)