您的位置:首页 > 运维架构 > Linux

linux下的SPI模块驱动使用

2017-09-28 10:18 274 查看
转载地址:http://blog.sina.com.cn/s/blog_9542cec30102w332.html

由于linux的驱动都有很好的框架性,但是对刚开始学习的人来说,在不太懂框架的基础之下学习是很麻烦的事,网上很多都把这个框架给完整性分析了一下,但是具体怎么要能用,也没有怎么说,这里我总结一下。

1、驱动分为平台驱动、控制器驱动、设备驱动、设备。

2、拿到一个开发板后,烧上系统,那我们基本上就有了平台驱动、控制器驱动。设备驱动基本都有的,官方实现了一个设备驱动,文件是spidev.c,它是一个设备驱动,它会在开机之后自动注册一个主设备号为153的字符设备。

3、当注册了SPI设备到系统中时,会根据名字进行匹配,如果名字是spidev则会调用 spidev.c中的probe函数,随后会在/dev/device/下面生成如spidevx.x的设备文件,通过该设备文件即可操作SPI设备。

4、如何注册SPI设备到系统。在kernel/arch/arm/mach-xxxx,xxx是板子芯片型号,我用的事 mach-smdk6410.c。在里面找到spi_board_info结构体位置,例如:

static struct spi_board_info __initdata forlinx6410_mc251x_info[]  = {
{
.modalias = "mcp2515",
.platform_data = &mcp251x_info,
.irq = IRQ_EINT(16),
.max_speed_hz = 10*1000*1000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data=&s3c64xx_spi1_csinfo,
},
};

本结构体就是SPI的板级信息,会在后面被spi_register_board_info()调用,随后在系统中注册这个设备。

我们需要做的是添加我们自己的信息

static struct spi_board_info __initdata forlinx6410_mc251x_info[]  = {
{
.modalias = "mcp2515",
.platform_data = &mcp251x_info,
.irq = IRQ_EINT(16),
.max_speed_hz = 10*1000*1000,
.bus_num = 1,
.chip_select = 0,
.mode = SPI_MODE_0,
.controller_data=&s3c64xx_spi1_csinfo,
},

 .modalias = "spidev", //用来匹配设备驱动,SPI的设备驱动叫spidev
 .max_speed_hz = 10*1000*1000, //最大速率 
 .bus_num = 0, //在(0)号总线上
 .chip_select = 0, //使用片选spi0_cs0
 .mode = SPI_MODE_0, //SPI模式
 .controller_data=&s3c64xx_spi0_csinfo,//控制器信息 },
};

其中的static struct s3c64xx_spi_csinfo s3c64xx_spi0_csinfo = {

  .fb_delay=0x3,

  .line=S3C64XX_GPC(3),//这个是片选控制引脚

  .set_level=cs_set_level,

};

然后编译内核下载开发板上,重新启动过后就能后在/dev下面看到spidev0.0设备文件。

猜想:

写一个模块,收到填写该结构体,然后调用spi_register_board_info()来注册。我没有试过,应该是可以的。

5、使用的时候在用户应用空间中就使用open打开设备文件即可使用。

需要在封装一次。由于spidev.c仅提供数据接收与发送,但是对于具体的SPI怎么发的好像没有做。

因此我们具体的收发函数应该在此分装为如下

int fd;

fd=open(device, O_RDWR);

读函数

输入:fd文件描述符,addr读的地址,read_data读出来数据存放的地址

输出:成功操作的字节数,这个没有做好,需要改

unsigned char read_reg(int fd,unsigned char addr,unsigned char *read_data)
{
int ret=0;
addr=addr<<1;
addr=addr|0x80;
ret=write(fd,&addr,sizeof(unsigned char));
ret|=read(fd,read_data,sizeof(unsigned char));
return ret;
}

写函数

unsigned char write_reg(int fd,unsigned char addr,unsigned data)
{
int ret=0;
unsigned char buff[2]={0};
buff[0]=addr<<1;
buff[0]=buff[0]&0x7f;
buff[1]=data;
ret=write(fd,&buff,sizeof(buff));
return ret;
}

然后其他具体操作看我们的实际需要了,以上两个就可以正确读写了,你可以先用读函数读取设备各个寄存器的默认值,来观察读取是否正确。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: