zoukankan      html  css  js  c++  java
  • SPI子系统分析之一:框架

    内核版本:3.9.5

    SPI子系统概述:

    一个SPI主控制器对应一条SPI总线,当然在系统中有唯一的总线编号.

    SPI总线上有两类设备:

    • 其一是主控端,通常作为SOC系统的一个子模块出现,很多嵌入式MPU中都常常包含SPI模块;
    • 其二是受控端,例如一些SPI接口的Flash,传感器等等;

    主控端是SPI总线的控制者,通过使用SPI协议主动发起SPI总线上的会话.而受控端则被动接受SPI主控端的指令,并作出响应的响应.

    Linux目前只支持SPI主控端,不能支持SPI受控端设备.

    Linux中的SPI子系统向下直接和SPI主控设备硬件交互,读取SPI总线上的数据.向上则和FS子系统,MTD子系统,字符设备子系统等等交互,给用户空间提供访问接口.

    在SPI子系统中,包含两类设备驱动:

    • 其一称之为Controller driver,用于驱动SPI主控设备,以和SPI总线交互,读写通信数据;
    • 其二称之为Protocol driver,用于解析Controller driver读取的数据,形成有意义的协议数据.举例来说,将AT25芯片通过SPI总线和LPC3250的SPI控制器联接在一起,构成一个SPI总线通信系统.Protocol driver的作用,就是根据用户空间或者上层子系统的请求,(比如读写Flash指定地址出的数据),找到对应的SPI指令,并生成一个SPI会话帧(指令+地址+数据)数据.Controller driver的作用,就是将这个会话帧的数据通过SPI控制器的硬件,发到SPI总线上去;

    由此可见,SPI子系统中有两种设备,一种是Controller driver驱动的,称之为spi_master.另一种是由Protocol driver驱动的,称之为spi_device(个人觉得这种称法不太准确,这个设备只是协议解析设备,而非真正的spi设备).

    Linux的SPI子系统之所以采用将主机和外设分离的思想,是因为SPI主控器功能单一,只负责和SPI总线交互,读写数据.但数据的具体含义,根据SPI总线上的设备不同,而千差万别.首先主机SPI控制器是一种平台设备,它以platform的方式注册进内核,外设的信息是以boardinfo形式静态定义的,在创建spi_master时,会根据外设的bus_num和主机的bus_num是否相等,来选择是否将该外设挂接在该SPI主控制器下.

    内核一方面把SPI通信系统分成上面两个部分,另一方面创建了一个spi核心系统,用于联接这两部分.

    根据上面的分析我们知道,SPI通信的数据流大致是:

    • 用户请求=>Protocol driver分析请求,生成SPI通信帧=>Controller driver将通信帧发送到SPI总线上;
    • SPI设备传回数据=>Controller driver从SPI总线上读回=>Protocol解析通信数据并上报;

    其中Protocol和Controller之间的交互中,SPI帧是一个比较关键的数据结构.Protocol通过分析上层请求生成这种帧,并且解析这种帧得到SPI设备的响应的结果.Controller通过和SPI总线交互,收发这样的帧.在Linux内核中,这个帧通过一个叫做spi_message的结构来实现.

    在有数据请求时,Protocol解析请求生成这个帧,并发送到SPI核心子系统.SPI核心子系统通过Protocol设备的信息,找到对应的Controller设备,并将这个帧发送给Controller.Controller接受到这个帧后发送到SPI总线上,返程类似.

    spi_master/spi_device和spi_driver的关系如下:

     

    同时,SPI设备和驱动的对应关系如下:

    结合上文介绍可知,spi_master是以platform_device注册进内核的,系统会寻找其相应的platform_driver与其进行匹配,这其实就对应我们的Controller driver.

    而spi核心层所做的工作就是将这些与平台相关的部分抽象概括,抽象出所有控制器都具备的功能代码,同时向上为spiprotocol驱动提供接口比如spi_message,spi_transfer,spi_async等,具体可参见linux/spi/spi.h文件.

    本文引用:http://blog.csdn.net/wuhzossibility/article/details/7870875

    http://blog.csdn.net/vanbreaker/article/details/7733476

  • 相关阅读:
    linux学习 建立静态库,动态库,写简单的makefile
    C++中顶层const和底层const
    BDB (Berkeley DB)数据库简单介绍(转载)
    Java中Map的使用
    Spring MVC 3 深入总结
    nvl,空时的推断和取值
    java堆栈 (转)
    mybatis--面向接口编程
    HDU 4888
    socket编程——一个简单的样例
  • 原文地址:https://www.cnblogs.com/jason-lu/p/3164634.html
Copyright © 2011-2022 走看看