Linux驱动开发、20-SPI子系统分析

来源:互联网 发布:知乎 编程电脑配置要求 编辑:程序博客网 时间:2024/05/16 00:40

SPI总线

基础概念:

 

SPI(Serial Peripheral Interface,串行外围设备接口)总线,串行 主-从接口;很多集成与微控制器内部。

 

四线制,全双共模式,速度达到几兆,四线分别为:

SCLK(Serial Clock):串行时钟

CS(Chip Select):片选,有些写着SS

MISO(Master In Slave out):主设备输入,从设备输出

MOSI(Master Out Slave in):主设备输出,从设备输入

 

架构图解:

 

 

数据传输过程:

 

主节点通过 MOSI 线输出数据,从节点在SIMO 处从主节点读取数据。同时,也在通过SOMI 输出MSB(最高位),主节点会在MISO处读取从节点的数据,整个过程将一直持续,直至交换完所有数据;也就是所主从实现数据交换既为一次传输过程

 

总线时序:

 

CPOL极性:决定时钟空闲时为高电平还是低电平
CPOL=0CLK空闲时是低电平,CLK有效时是高电平
CPOL=1CLK空闲时是高电平,CLK有效时是低电平
决定何时进行数据采样(读取)
CPHA=0:一个时钟的上升沿采样
CPHA=1:第一个时钟的下降沿采样

 

根据CPOLCPHA的不同组合,SPI被分为4种模式

 

SPI0传输时序

 

TQ210 SPI控制器编程步骤:芯片手册900

 

 

Linux SPI总线子系统

架构

 

1. SPI核心
SPI控制器驱动和设备驱动之间的纽带,它提供了SPI控制器驱动和设备驱动的注册、 注销方法等。
2.SPI控制器驱动
SPI控制器的驱动实现。
3. SPI设备驱动
SPI从设备的驱动实现。

 

典型客户驱动程序:

1、SPI核心注册设备驱动:如在prob函数中:

#include<linux/spi/spi.h>

static struct spi_driver my_spidriver =

{

.driver =

{

.name = “myspi”,

.bus = &spi_bus_type,

.owner = THIS_MODULE,

}

.prob = myspidevice_prob,

.remove = _devexit_p(myspidevice_remove),

};

spi_register_driver(my_spidriver ); /*SPI核心注册,在SPI总线挂载驱动*/

 

SPI核心创建对应于此设备的spi_device结构,当调用注册的驱动方法时,将此结构作为调用参数。

2、数据传输结构

 

 * I/O INTERFACEbetween SPI controller and protocol drivers

 * Protocol drivers use a queue of spi_messages, each transferring data

 * between the controller and memory buffers.

struct spi_transfer

 

 * struct spi_message - one multi-segment SPI transaction

struct spi_message

 

关系图解:

 

3、SPI消息构造

 

a、spi_message_init(struct spi_message *m) /*分配一条消息空间,并初始化 链表头*/

 

bspi_message_add_tail(struct spi_transfer *t, struct spi_message *m)  /*将数据加入链表*/

 

4、数据通讯

 

spi_sync():等待操作完成

spi_async():当数据传输完成时,异步触发对注册的回调程序的调用,如SPI中断处理函数、sysf方法或者定时器处理程序

 

5、SPI数据传输例子

 

#include<linux/spi/spi.h>

 

struct spi_device *spi;

struct spi_transfer *t;

struct spi_message sm;

 

unsigned char *command_buff; /*数据传输空间*/

int len; /*数据长度*/

 

/*1、初始化SPI消息链表*/

spi_message_init(&sm);

 

/*2、填充传输数据*/

t.tx_buf = command_buff;

t.len = len;

 

/*3、把传输数据加入SPI消息队列*/

spi_message_add_tail(t, &sm);

 

/*4、阻塞请求传输,将数据提交给SPI控制器*/

spi_sync(spi,&sm);

 

SPI控制器驱动:spi_s3c64xx.c,移植和I2C类似,不过这次比较简单,将内核配置,选择64XXSPI驱动就行了

 

平台型驱动,控制器初始化在捕获函数中进行,数据传输在中断中进行,桥接控制器和设备的数据结构,平台资源初始化对应在:dev-spi.c文件中,和6410使用同一个驱动

 

struct s3c24xx_spi {

/* bitbang has to be first */

struct spi_bitbang  bitbang;

struct completion  done;

 

void __iomem *regs;

int  irq;

int  len;

int  count;

 

struct fiq_handler  fiq_handler;

enum spi_fiq_mode  fiq_mode;

unsigned char  fiq_inuse;

unsigned char  fiq_claimed;

 

void (*set_cs)(struct s3c2410_spi_info *spi,

  int cs, int pol);

 

/* data buffers */

const unsigned char *tx;

unsigned char *rx;

 

struct clk *clk;

struct resource *ioarea;

struct spi_master *master;

struct spi_device *curdev;

struct device *dev;

struct s3c2410_spi_info *pdata;

};

 

 

SPI控制器和SPI设备驱动的函数联系

 

(国嵌入图)

0 0
原创粉丝点击