SPI(Serial Peripheral Interface) 是一个同步的四线制串行线,用于连接微控制器和传感器、存储器及外围设备。三条信号线持有时钟信号(SCLK,经常在10MHz左右)和并行数据线带有“主出,从进(MOSI)”或是“主进,从出(MISO)”信号。数据交换的时候有四种时钟模式,模式0和模式3是最经常使用的。每个时钟周期将会传递数据进和出。如果没有数据传递的话,时钟将不会循环。
SPI驱动分为两类:
控制器驱动:它们通常内嵌于片上系统处理器,通常既支持主设备,又支持从设备。这些驱动涉及硬件寄存器,可能使用DMA。或它们使用GPIO引脚成为PIO bitbangers。这部分通常会由特定的开发板提供商提供,不用自己写。
协议驱动:它们通过控制器驱动,以SPI连接的方式在主从设备之间传递信息。这部分涉及具体的SPI从设备,通常需要自己编写。
那么特定的目标板如何让Linux 操控SPI设备?下面以AT91SAM9260系列CAN设备驱动为例,Linux内核版本为2.6.19。本文不涉及控制器驱动分析。
board_info提供足够的信息使得系统正常工作而不需要芯片驱动加载
这样在Linux初始化时候就可以加载SPI CAN驱动。
下面来看MCP2515 CAN驱动的结构,协议驱动有点类似平台设备驱动,本文只列出框架,不涉及具体实现代码,在/driver/CAN/MCP2515.c中:
一旦进入probe(),驱动使用"struct spi_message"向SPI设备要求I/O。当remove()返回时,驱动保证将不会提交任何这种信息。
一个spi_message是协议操作序列,以一个原子序列执行。SPI驱动控制包括:
(1)当双向读写开始,是根据spi_transfer要求序列是怎样安排的。
(2)随意设定传递后的短延时,使用spi_transfer.delay_usecs设定。
(3)在一次传递和任何延时之后,无论片选是否活跃,使用spi_transfer.cs_change标志, 暗示下条信息是否进入这个同样的设备,使用原子组中最后一次传输上的spi_transfer.cs_change标志位,可能节省芯片选择取消操作的成本。