和菜鸟一起学linux总线驱动之初识spi驱动主要结构

       既然知道了协议了,那么就可以开始去瞧瞧linux kenerl中的spi的驱动代码了,代码中有很多的结构体,还是对主要的结构体先做个了解吧,那样才可以很好的理解驱动。主要是include/linux/spi.h

 

首先是SPI的主机和从机通信接口,也就是SPI总线,

extern struct bus_type spi_bus_type;

bus_type定义在linux/device.h

 

struct bus_type {const char              *name;     //总线的名字struct bus_attribute *bus_attrs;struct device_attribute    *dev_attrs;struct driver_attribute    *drv_attrs; //总线上的device和driver的匹配,匹配成功返回非0值int (*match)(struct device *dev, struct device_driver *drv);int (*uevent)(struct device *dev, struct kobj_uevent_env *env);//当新的device或driver加到总线上的时候,调用driver中的probe函数经行匹配int (*probe)(struct device *dev);int (*remove)(struct device *dev);void (*shutdown)(struct device *dev);int (*suspend)(struct device *dev, pm_message_t state);int (*resume)(struct device *dev);const struct dev_pm_ops *pm;struct subsys_private *p;
};

 

SPI设备

 

struct spi_device {struct device          dev;struct spi_master    *master;    //SPI控制器u32                max_speed_hz;  //最大时钟频率u8                  chip_select;     //片选u8                  mode;          //SPI模式
#define    SPI_CPHA     0x01                     /* clock phase */
#define    SPI_CPOL     0x02                     /* clock polarity */
#define    SPI_MODE_0       (0|0)                     /* (original MicroWire) */
#define    SPI_MODE_1       (0|SPI_CPHA)
#define    SPI_MODE_2       (SPI_CPOL|0)
#define    SPI_MODE_3       (SPI_CPOL|SPI_CPHA)
#define    SPI_CS_HIGH      0x04                     /* chipselect active high? */
#define    SPI_LSB_FIRST    0x08                     /* per-word bits-on-wire */
#define    SPI_3WIRE   0x10                     /* SI/SO signals shared */
#define    SPI_LOOP     0x20                     /* loopback mode */
#define    SPI_NO_CS   0x40                     /* 1 dev/bus, no chipselect */
#define    SPI_READY  0x80                     /* slave pulls low to pause */u8                  bits_per_word;              //一次传输的bits,可以是8、16、32,默认是8int                 irq;                 void               *controller_state;void               *controller_data;        char               modalias[SPI_NAME_SIZE];  //别名,用于device和driver的匹配
};


 

 

SPI驱动

 

struct spi_driver {const struct spi_device_id *id_table;int                 (*probe)(struct spi_device *spi);  //绑定驱动和SPI设备int                 (*remove)(struct spi_device *spi);void               (*shutdown)(struct spi_device *spi);int                 (*suspend)(struct spi_device *spi, pm_message_t mesg);int                 (*resume)(struct spi_device *spi);struct device_driver         driver;
};


 

SPI主控制器

 

struct spi_master {struct device   dev;   //驱动的设备接口struct list_head list;        //SPI控制器的链表头s16                bus_num;    //总线号/* chipselects will be integral to many controllers; some others* might use board-specific GPIOs.*/u16                num_chipselect;    //SPI设备的片选号u16                dma_alignment;     //dma模式  /* spi_device.mode flags understood by this controller driver */u16                mode_bits;         /* other constraints relevant to this driver */u16                flags;#define SPI_MASTER_HALF_DUPLEX    BIT(0)           /* can't do full duplex */
#define SPI_MASTER_NO_RX   BIT(1)           /* can't do buffer read */
#define SPI_MASTER_NO_TX    BIT(2)           /* can't do buffer write *//* lock and mutex for SPI bus locking */spinlock_t              bus_lock_spinlock;struct mutex           bus_lock_mutex;bool               bus_lock_flag;int                 (*setup)(struct spi_device *spi);   //更新SPI设备的模式和SPI设备的采样时钟int                 (*transfer)(struct spi_device *spi,    //添加一个消息到控制器的传输队列struct spi_message *mesg);void               (*cleanup)(struct spi_device *spi);};


 

SPI传输

 

struct spi_transfer {/* it's ok if tx_buf == rx_buf (right?)* for MicroWire, one buffer must be null* buffers must work with dma_*map_single() calls, unless*   spi_message.is_dma_mapped reports a pre-existing mapping*/const void       *tx_buf;    //要写的数据void        *rx_buf;                //要读的数据unsigned  len;                       //数据长度dma_addr_t    tx_dma;       //tx_buf的DMA地址dma_addr_t    rx_dma;         //rx_buf的DMA地址unsigned  cs_change:1;u8           bits_per_word;       //传输的bytes数,不选就用默认的u16         delay_usecs;                  //微秒延时,用以传输数据后,改变片选信号前u32         speed_hz;            //传输速率,不选就用默认的struct list_head transfer_list;     //传输链表,用以传输spi_message};


 

SPI消息

 

struct spi_message {struct list_head       transfers;   // struct spi_device     *spi;      //加到传输队列中的spi设备unsigned         is_dma_mapped:1;   //DMA传输控制位/* completion is reported through a callback */void               (*complete)(void *context);      //传输完成void               *context;                                    //complete函数的参数                unsigned         actual_length;             //所有成功传输字段的总长度int                 status;                                 //传输成功返回0,否则返回错误/* for optional use by whatever driver currently owns the* spi_message ...  between calls to spi_async and then later* complete(), that's the spi_master controller driver.*/struct list_head       queue;void               *state;};


 

SPI bitbang

 

struct spi_bitbang {struct workqueue_struct *workqueue;struct work_struct   work;spinlock_t              lock;struct list_head       queue;u8                  busy;u8                  use_dma;u8                  flags;             /* extra spi->mode support */struct spi_master    *master;/* setup_transfer() changes clock and/or wordsize to match settings* for this transfer; zeroes restore defaults from spi_device.*/int   (*setup_transfer)(struct spi_device *spi,struct spi_transfer *t);void (*chipselect)(struct spi_device *spi, int is_on);
#define    BITBANG_CS_ACTIVE      1     /* normally nCS, active low */
#define    BITBANG_CS_INACTIVE   0/* txrx_bufs() may handle dma mapping for transfers that don't* already have one (transfer.{tx,rx}_dma is zero), or use PIO*/int   (*txrx_bufs)(struct spi_device *spi, struct spi_transfer *t);/* txrx_word[SPI_MODE_*]() just looks like a shift register */u32  (*txrx_word[4])(struct spi_device *spi,unsigned nsecs,u32 word, u8 bits);};


        在SPI控制器里面最常用的用来处理传输的结构体spi_bitbang了。

 

SPI borad info

struct spi_board_info {/* the device name and module name are coupled, like platform_bus;* "modalias" is normally the driver name.** platform_data goes to spi_device.dev.platform_data,* controller_data goes to spi_device.controller_data,* irq is copied too*/char  modalias[SPI_NAME_SIZE];const void *platform_data;void  *controller_data;int  irq;/* slower signaling on noisy or low voltage boards */u32  max_speed_hz;/* bus_num is board specific and matches the bus_num of some* spi_master that will probably be registered later.** chip_select reflects how this chip is wired to that master;* it's less than num_chipselect.*/u16  bus_num;u16  chip_select;/* mode becomes spi_device.mode, and is essential for chips* where the default of SPI_CS_HIGH = 0 is wrong.*/u8  mode;/* ... may need additional spi_device chip config data here.* avoid stuff protocol drivers can set; but include stuff* needed to behave without being bound to a driver:*  - quirks like clock rate mattering when not selected*/
};

       控制器里会读取borad info里的参数

 

SPI gpio_platform_data

 

struct spi_gpio_platform_data {unsigned  sck;unsigned  mosi;unsigned  miso;u16         num_chipselect;};


        因为我用的比较多的是GPIO模拟的,所以还是记录下这个从platform传进来的管脚号。

 

       OK,对于SPI用到的结构体基本上已经介绍完了,那么接下来就介绍其主要函数了。

 

转载于:https://www.cnblogs.com/wuyida/archive/2012/08/29/6300060.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/377253.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统大内核和微内核_操作系统中的内核

操作系统大内核和微内核A Kernel is the central component of an Operating System. The Kernel is also said to be the heart of the Operating System. It is responsible for managing all the processes, memory, files, etc. The Kernel functions at the lowest level …

《MySQL——锁》

全局锁是什么?全局锁有什么用?全局锁怎么用? 全局锁主要用在逻辑备份过程中,对于InnoDB 引擎的库,使用–single-transaction; MySQL 提供了一个加全局读锁的方法,命令是 Flush tables with read lock (FTW…

搜索引擎Constellio及Google Search Appliances connectors

做搜索产品的时候发现国外一个同类型的产品contellio,发现功能比较强大,先记录下来 貌似可以添加文档 网站 以及数据库等不同类型的数据源 http://wiki.constellio.com/index.php/Main_Page http://www.constellio.com/ http://www.constellio.com htt…

dig下载_DIG的完整形式是什么?

dig下载DIG:副监察长 (DIG: Deputy Inspector General) DIG is an abbreviation of the Deputy Inspector General. It is a high-level position in the Indian Police Service. The officers who already offered service on Senior Superintendent of Police (SS…

分类器是如何做检测的?——CascadeClassifier中的detectMultiScale函数解读

原地址:http://blog.csdn.net/delltdk/article/details/9186875 在进入detectMultiScal函数之前,首先需要对CascadeClassifier做初始化。 1. 初始化——read函数 CascadeClassifier的初始化很简单: cv::CascadeClassifier classifier; cl…

<MySQL>何时使用普通索引,何时使用唯一索引

如果能够保证业务代码不会写入重复数据,就可以继续往下看。 如果业务不能保证,那么必须创建唯一索引。 关于查询能力 普通索引和唯一索引在查询能力上是没有很大差别的。 如:select id from T where k5 1、普通索引查找到满足条件的第一个记…

Web版OutLook,利用POP接收邮件服务器邮件

一直想做一个Web版的OutLook,所以才萌生这个想法,其实以前也接触过这方面的东西。于是上网找了找,漫天的都是Jmail来接收,好吧,既然大家都在用我也就下载下来试试了。 什么,怎么总是报错呢?原来…

abs std::abs_ABS的完整形式是什么?

abs std::absABS:防抱死制动系统 (ABS: Anti-lock Braking System) ABS is an abbreviation of the Anti-lock Braking System. It is a safety anti-skid braking system that is used on a variety of aircraft, automobiles and other land vehicles, such as mo…

ubuntu 使用

shell 命令历史搜索 : ctrl r使能 session 选择界面:安装gnome-session-fallback安装lwqq转载于:https://www.cnblogs.com/JonnyLulu/p/3600263.html

汉字速查使用方法简介

《汉字速查》(HanziSearcher)是一个支持全汉字字典和词典的检索工具。其界面如下所示。 界面上方为工具栏。 左方为字典和词典检索栏。 右方在启动时显示版权信息和作者的联系方式,在执行检索时,显示检索结果。 检索方法 汉字速查…

android jni示例_Android服务示例

android jni示例A service is a component that runs in the background for supporting different types of operations that are long running. The user is not interacted with these. These perform task even if application is destroyed. Examples include handling of…

《MySQL——选错索引,该如何做》

如果不断地删除历史数据和新增数据,MySQL有时会选错索引。 选择索引是优化器的工作,优化器优化时会考虑的因素:扫描行数、是否需要排序、是否使用临时表 MySQL通过统计索引上的基数,作为索引的区分度。 统计方法时采样统计&#x…

LPWSTR 类型的实参与const.char *类型形参不兼容

CString csPlus; CString csSummand; m_PlusNumber.GetWindowTextW(csPlus); m_Summand.GetWindowTextW(csSummand); int nPlus atoi(csPlus.GetBuffer(0)); //将编辑框文本转换成整数// int nPlus atoi(strcpy(csPlus.GetBuffer(10),"aa")); csPlus.ReleaseBu…

空间换时间,把递归的时间复杂度降低到O(2n)

递归算法的时间复杂度除非只有前两项,否则都不是线性的,并且相当耗费内存。我们用最常见的的fibonacci数列来说明: function fibonacci(n){if( n 0 || n 1){return n;} else {return fibonacci(n - 1) fibonacci(n - 2);} } 这是一种最常见…

scala char_Scala中的Char数据类型

scala charScala Char数据类型 (Scala Char Data Type) Character (char) in Scala is a data type that is equivalent to 16-bit unsigned integer. The character data type stores a single character. It can be an alphabet, numbers, symbols, etc. The character takes…

《MySQL——给长字符串加索引》

对于长字符串,可用如下方式建立索引: (1)前缀索引 (2)字符串倒叙前缀索引 (3)添加hash字段并在hash字段上加索引 (4)字段拆分(一个字段可拆分为两…

[蓝桥杯历届试题] 欧拉与鸡蛋

大数学家欧拉在集市上遇到了本村的两个农妇,每人跨着个空篮子。她们和欧拉打招呼说两人刚刚卖完了所有的鸡蛋。 欧拉随便问:“卖了多少鸡蛋呢?” 不料一个说:“我们两人自己卖自己的,一共卖了150个鸡蛋,虽然…

Python元组练习

Here, we are covering following Python tuple exercises, 在这里,我们将介绍以下Python元组练习 , Creating & printing a tuple 创建和打印元组 Unpacking the tuple into strings 将元组解包成字符串 Create a tuple containing the letters of…

傻瓜教你看清MVC内部执行流程之ViewData数据传输,轻松学MVC--①目了然篇(待续)

1.首先在执行到Controller里面的action(方法)时,执行到最后会调用一个View()-->此方法是Controller的一个方法 源代码: View Code protected internal ViewResult View(){return View(null /* viewName */, null /* masterName */, null /* model */);} 2.然后继续调用自己…

《MySQL——count()逻辑》

count()用法 count()语义:该函数为一个聚合函数,对于返回的结果集一行行地判断,如果count函数地参数不是NULL,累计值就加1,否则不加。最后返回累计值。 所以count(*),count(主键id)和count(1)都表示返回满足条件地结果…