spislave及master接口驱动及传输时序_第1页
spislave及master接口驱动及传输时序_第2页
spislave及master接口驱动及传输时序_第3页
spislave及master接口驱动及传输时序_第4页
spislave及master接口驱动及传输时序_第5页
已阅读5页,还剩7页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、spislave及master接口驱动及传输时序spislave当区动spislave驱动在kernel中可以主要参考spidev.c,这是一个字符驱动,可以匹配kernel中的多个名称为“spidevl勺spi设备,分析这个文件,主要有以下几个重点:1 .如何编写多设备公用驱动2 .如何封装读写请求到spi框架层3 .spimessage请求如何分发至Umaster自spi_board_info或者spimaster注册后,两者就已经完成了匹配的工作,spislave驱动不关心任何匹配的细节,它只需要完成与spislave的匹配,就可以通过slave进而找到master。这里是通过spi_r

2、egister_driver(&spidev_spi_driver);注册进kernel,而后spi框架进行namematch,再调用probe,完成关于设备的一些成员初始化操作。下面针对上面的三个问题,进行分析这个驱动,spi设备全局链及保护信号量:staticLIST_HEAD(device_list);staticDEFINE_MUTEX(device_list_lock);相对与设备的驱动数据:structspidev_datadev_tdevt;/设备号spinlock_tspi_lock;/spi结构体的pin锁structspi_device*spi;structlist_hea

3、ddevice_entry;/挂接至Udevice_liststructmutexbuf_lock;/保护数据的lockunsignedusers;/使用者u8*buffer;/实际数据区,由open时进行动态分配,release时释放;spi中任何会由多个使用者访问的区域,都需要使用锁保护,如这里的users,个人觉得需要使用原子变量而不应该简单的使用整形。在probe的时候,首先分配spidev_data,并初始化其spi/device_entry/buf_lock/spi_lock,查找一个可用的bit用作次设备号,创建设备spidevbusnum.cs挂到全局链中,并将私有数据spid

4、ev_data放至Udev-p-driver_data中。open时,从inode中获取dev_t,然后对比整个链,找到目标数据spidev_data,放至Ufile-private_data中,并分配缓存读写时,直接从file中获取对应的spidev_data数据,然后通过spidevice来传递spi请求。以上主要是数据如何传递的问题。SPI读写请求的封装很简单,如下:staticinlinessize_tspidev_sync_write(structspidev_data*spidev,size_tlen)structspi_transfert=.tx_buf=spidev-buffe

5、r,.len=len,);structspi_messagem;spi_message_init(&m);spi_message_add_tail(&t,&m);returnspidev_sync(spidev,&m);staticinlinessize_tspidev_sync_read(structspidev_data*spidev,size_tlen)structspi_transfert=.rx_buf=spidev-buffer,.len=len,;structspi_messagem;spi_message_init(&m);spi_message_add_tail(&t,&m)

6、;returnspidev_sync(spidev,&m);注寸装的同步函数:staticssize_tspidev_sync(structspidev_data*spidev,structspi_message*message)DECLARE_COMPLETION_ONSTACK(done);intstatus;message-context=spin_lock_irq(&spidev-spi_lock);if(spidev-spi=NULL)status=-ESHUTDOWN;elsestatus=spi_async(spidev-spi,message);spin_unlock_irq(

7、&spidev-spi_lock);if(status=0)status=message-status;if(status=0)status=message-actual_length;returnstatus;只需要调用spi_async就可以完成数据读取/写入的操作。这个函数在内部真正做了什么?如何分发/回调?我们走一遍代码:首先master内部有两个锁:spinlock_tbus_lock_spinlock;【用于异步】spi_asyncstructmutexbus_lock_mutex;【用于同步】spi_sync对于不同的场景,需要对master进行不同类型的加锁,异步:spin_l

8、ock_irqsave(&master-bus_lock_spinlock,flags);ret=_spi_async(spi,message);message-spi=spi;message-status=-EINPROGRESS;returnmaster-transfer(spi,message);spin_unlock_irqrestore(&master-bus_lock_spinlock,flags);同步:message-context=if(!bus_locked)mutex_lock(&master-bus_lock_mutex);status=spi_async_locked

9、(spi,message);if(!bus_locked)mutex_unlock(&master-bus_lock_mutex);if(status=0)status=message-status这里即在kernel内部完成了同步的工作,不需要像spidev那样需要自己等待完成量,使用的是bus_lock_mutex内部与异步的调用方式一致:spin_lock_irqsave(&master-bus_lock_spinlock,flags);ret=_spi_async(spi,message);spin_unlock_irqrestore(&master-bus_lock_spinlock

10、,flags);从这里可以看出,同步与异步没有本质差别,只是多了一个完成量的操作而已。最终调用的函数为:master-transfer(spi,message);这个函数将在spimaster中分析。在spislave侧需要熟悉传输的参数的每个域的功能,才能很好的完成工作structspi_transferconstvoid*tx_buf;/非dma发送地址void*rx_buf;/非dma读取地址unsignedlen;/tx/rxbufffersizedma_addr_ttx_dma;/若spi_message.is_dma_mappedB位,为transfer的dmaaddressdma

11、_addr_trx_dma;/若spi_message.is_dma_mappedB位,为read的dmaaddressunsignedcs_change:1;/传输完成后,修改cs信号u8bits_per_word;/长度,优先覆盖spi_board_info的设置(32)u16delay_usecs;/传输后继续传输或者cs结束传输的中间时隙u32speed_hz;/本次传输的速度,可以优先覆盖spi_board_info里的设置structlist_headtransfer_list;/挂接至Uspi_message上的连接体;structspi_messagestructlist_he

12、adtransfers;/transfer链structspi_device*spi;对应的spi设备unsignedis_dma_mapped:1;/是否启动dma功能void*context;/回调参数unsignedactual_length;/传输的真正长度intstatus;/0,成功structlist_headque;/driver使用void*state;每个域的使用方法,这里直接看起来并不明确,必须结合master的驱动spimaster当区动SPI设备资源:staticstructresources3c_spi0_resource=0=DEFINE_RES_MEM(S3c2

13、4XX_PA_SPI,SZ_32),1=DEFINE_RES_IRQ(IRQ_SPI0),;structplatform_devices3c_device_spi0=.name=s3c2410-spi,.id=0,.num_resources=ARRAY_SIZE(s3c_spi0_resource),.resource=s3c_spi0_resource,.dev=.dma_mask=&samsung_device_dma_mask,.coherent_dma_mask=DMA_BIT_MASK(32),;staticstructresources3c_spi1_resource=0=DEF

14、INE_RES_MEM(S3c24XX_PA_SPI1,SZ_32),1=DEFINE_RES_IRQ(IRQ_SPI1),;structplatform_devices3c_device_spi1=.name=s3c2410-spi,.id=1,.num_resources=ARRAY_SIZE(s3c_spi1_resource),.resource=s3c_spi1_resource,.dev=.dma_mask=&samsung_device_dma_mask,.coherent_dma_mask=DMA_BIT_MASK(32),;在此之间,走过了一些弯路学了verilog/mode

15、lsim,在之前一直不明白的事情在逐渐的尝试中获得了新的认识,硬件的ipcore的工作是由clock来驱动的,而不是软件意义上的过程,在同步时钟的上升/下降沿中进行数据处理,移位等在SPI的ipcore设计中,主要有三个模块:1. clockgenerate2. datashift3. registercontrol首先通过AP过来的系统时钟及设备能够支持的最大时钟频率,计算出对应的最接近的分频系数,而模块1就是根据这个分频系数来通过系统的源clock产生对应的目标clock。【因为对于SPII杯需要独立的精确的晶振】生成了与slave同步的clock之后,输出到模块2,模块2负责具体的发送数

16、据功能。具体的采数发数时序见第三节。而registercontrol则负责所有的可配置接口,如:分频系数,支持位宽,FIFO深度,支持的片选数,以及相应的MSB/LSB设置选项。在SPI的协议中,最大的误区在于master与slave之间的私有协议:SPImaster的本生设计中并不支持具体的传输协议,而是简单的提供了一个传输数据的通路,而协议则是由实现的slave端,以及slave端驱动来决定的。下面来总结这个数据发送与接收的具体过程:读指定地址:read(addr,&value,len);1 .配置相关读取操作的寄存器2 .slave驱动封装协议CMD【描述base+addr+len+fl

17、ags3 .拉下slave对应在master上的cs【低电平有效】4 .发送指定位宽cmd到slave端【由master来驱动,而slave只需要发送数据到对应fifo并启动发送即可】5 .slave端接收到指定的cmd,在MISO线上回应对应的数据6 .slave驱动从master的fifo中等待数据,当master读取到对应的线上数据,并放于FIFO中7 .读取到数据,拉高CS/*makesureleniswordunits*/intgps_spi_read_bytes_test3(u32len,u32addr,u32*data,boolsys,u32base)u32read_cmd2;l

18、ocal_spi_init();read_cmd0=SPI_READ_CMD(len,addr2+base);spi_assert_function(0);local_spi_write(u8*)read_cmd,4);local_spi_read(u8*)data,4);spi_assert_function(1);return0;写指定地址:write(addr,&value,len);intgps_spi_write_bytes_test2(u32len,u32addr,u32data)u32write_cmd2,one_read;local_spi_init();write_cmd0=

19、SPI_WRITE_SYS_CMD(len*1,addr2);write_cmd1=data;spi_assert_function(0);local_spi_write(u8*)write_cmd,8);spi_assert_function(1);return0;一些读写的实现细节:intlocal_spi_read(u8*buf,u32size)/*waitfordata*/while(reg-sts2&(0x1READ_TIME_OUT)gotoread_exit;*p=(u32)reg-txd;p+;/*iftxfifoisnotfull*/while(reg-sts2&(0x16);writel(*p,SPRD_SPI1_BASE);p+;/*bitlenis4*/以上为master驱动需要实现传输的一些流程spi传输时序问题主要关注两个参数:CPOLClock初始电平(0:低电平,1:高电平)CPHA采样位置(0:第一个跳变边沿,1

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论