转载地址:http://blog.csdn.net/chenliang0224/article/details/51236499

Linux spi驱动架构由三部分构成:SPI核心层、SPI控制器驱动层、和SPI设备驱动程序。

1.SPI核心层:

SPI核心层是Linux的SPI核心部分,提供了核心数据结构的定义、SPI控制器驱动和设备驱动的注册、注销管理等API。其为硬件平台无关层,向下屏蔽了物理总线控制器的差异,定义了统一的访问策略和接口;其向上提供了统一的接口,以便SPI设备驱动通过总线控制器进行数据收发。

2.SPI控制器驱动程序:

SPI控制器驱动层,每种处理器平台都有自己的控制器驱动,属于平台移植相关层。它的职责是为系统中每条SPI总线实现相应的读写方法。在物理上,每个SPI控制器可以连接若干个SPI从设备。在系统开机时,SPI控制器驱动被首先装载。一个控制器驱动用于支持一条特定的SPI总线的读写。一个控制器驱动可以用数据结构struct spi_master来描述

在include/liunx/spi/spi.h文件中,在数据结构struct spi_master定义如下:

struct spi_master {

struct device   dev;

s16         bus_num;

u16         num_chipselect;

int         (*setup)(struct spi_device *spi);

int         (*transfer)(struct spi_device *spi, struct spi_message *mesg);

void        (*cleanup)(struct spi_device *spi);

}

SPI控制器不用关心设备的具体功能,它只负责把上层协议驱动准备好的数据按SPI总线的时序要求发送给SPI设备,同时把从设备收到的数据返回给上层的协议驱动,因此,内核把SPI控制器的驱动程序独立出来。SPI控制器驱动负责控制具体的控制器硬件,诸如DMA和中断操作等等,因为多个上层的协议驱动可能会通过控制器请求数据传输操作,所以,SPI控制器驱动同时也要负责对这些请求进行队列管理,保证先进先出的原则 。

[cpp] view plaincopy print?
  1. 01.-->nuc970_spi0_probe(struct platform_device *pdev)   //完成如下的初始化
  2. 02.    -->1. init_completion(&hw->done); //完成量初始化
  3. 03.    -->2. hw->bitbang.setup_transfer = nuc970_spi0_setupxfer; //设置spi的寄存器参数
  4. 04.        2.1 nuc970_spi0_update_state(spi, t);       //更新传输模式
  5. 05.        2.2 nuc970_spi0_setup_txbitlen(hw, hw->pdata->txbitlen);  //字节发送长度
  6. 06.        2.3 nuc970_tx_edge(hw, hw->pdata->txneg); //发送边沿
  7. 07.        2.4 nuc970_rx_edge(hw, hw->pdata->rxneg); //接受边沿
  8. 08.        2.5 nuc970_set_clock_polarity(hw, hw->pdata->clkpol); //空闲时的时钟极性
  9. 09.        2.6 nuc970_send_first(hw, hw->pdata->lsb);    //字节传输顺序,0-高bit先传输
  10. 10.    -->3. hw->bitbang.chipselect  = nuc970_spi0_chipsel;  //芯片选择,目前同一个spi总线下面芯唐支持2个从设备
  11. 11.        3.1 nuc970_slave_select(spi, 0);    //BITBANG_CS_INACTIVE
  12. 12.        3.2 nuc970_slave_select(spi, 1);    //BITBANG_CS_ACTIVE
  13. 13.    -->4. hw->bitbang.txrx_bufs = nuc970_spi0_txrx;   //这个函数很重要!负责spi驱动与底层寄存器数据的发
  14. 14.                            //送、接收,这里直接发送,通过中断接收数据(第7.2点),
  15. 15.                            //发送与接收的桥梁是通过“完成量”完成的(第1.点)
  16. 16.        4.1 nuc970_spi0_gobusy(hw);     //发送完数据进入忙等待
  17. 17.        4.2 wait_for_completion(&hw->done);  //等待完成量(第7.2.1),否则进入休眠等待
  18. 18.    -->5. hw->bitbang.master->setup  = nuc970_spi0_setup;  //spi0设置
  19. 19.    -->6. platform_get_resource(pdev, IORESOURCE_MEM, 0) //获取寄存器的IO资源
  20. 20.        6.1 hw->ioarea = request_mem_region(hw->res->start,resource_size(hw->res), pdev->name);  //资源申请
  21. 21.        6.2 hw->regs = ioremap(hw->res->start, resource_size(hw->res)); //资源映射
  22. 22.    -->7. hw->irq = platform_get_irq(pdev, 0);    //获取中断资源
  23. 23.        7.1 request_irq(hw->irq, nuc970_spi0_irq, 0, pdev->name, hw);     //申请中断功能
  24. 24.        7.2 nuc970_spi0_irq(int irq, void *dev) //注意这个终端函数很重要,它负责接收底层spi寄存器上传的数据(与第4点相反)
  25. 25.            7.2.1 complete(&hw->done);   //中断接收数据完成,置“完成量”标志,唤醒第4.2
  26. 26.    -->8. nuc970_init_spi(hw);   //spi初始化
  27. 27.        8.1 clk_prepare(hw->clk);
  28. 28.        8.2 clk_enable(hw->clk);
  29. 29.        8.3 spin_lock_init(&hw->lock);
  30. 30.        8.4 nuc970_tx_edge(hw, hw->pdata->txneg);
  31. 31.        8.5 nuc970_rx_edge(hw, hw->pdata->rxneg);
  32. 32.        8.6 nuc970_send_first(hw, hw->pdata->lsb);
  33. 33.        8.7 nuc970_set_sleep(hw, hw->pdata->sleep);
  34. 34.        8.8 nuc970_spi0_setup_txbitlen(hw, hw->pdata->txbitlen);
  35. 35.        8.9 nuc970_spi0_setup_txnum(hw, hw->pdata->txnum);
  36. 36.        8.10 nuc970_set_divider(hw);
  37. 37.        8.11 nuc970_enable_int(hw);
  38. 38.    -->9. spi_bitbang_start(&hw->bitbang);
  39. 39.        9.1 INIT_WORK(&bitbang->work, bitbang_work); //初始化工作队列,绑定工作队列处理的函数
  40. 40.        9.2 bitbang_work(struct work_struct *work)  //工作队列处理函数
  41. 41.        9.3 status = bitbang->setup_transfer(spi, t);    //设置spi寄存器参数,函数初始化见第2.点,函数内容见第2.1~2.6
  42. 42.        9.4 bitbang->chipselect(spi, BITBANG_CS_ACTIVE); //
  43. 43.        9.5 master->transfer = spi_bitbang_transfer; //这个函数很重要,下面的第7.点将被调用
  44. 44.        9.6 bitbang->txrx_bufs(spi, t);      //发送、接收数据,见第4.点初始化,这个函数很重要!!!

3、SPI设备驱动程序:

这里要注意struct spi_device *spi 该spi的参数是通过arch/arm/mach-nuc970.c struct spi_device att7022e = {...};中进行定义的,在注册att7022e设备驱动的时候,检测到板级文件中存在该设备名就调用att7022e_prope函数。

att7022e.c  //没有使用内核自带的设备驱动spidev.c,而是自己编写的设备驱动att7022.c,具体实现细节,略...

执行流程如下:

[cpp] view plaincopy print?
  1. 01. -->1 att7022e_read_reg() //发送、接收消息, 将调用spi.c核心层
[cpp] view plaincopy print?
  1. 02. -->2 spi_write_then_read(spi,txbuf, n_tx, rxbuf, n_rx)
  2. 03. -->3 spi_sync(spi, &message)
  3. 04. -->4 __spi_sync(spi, message, 0)
  4. 05. -->5 spi_async_locked(spi, message)
  5. 06. -->6 __spi_async(spi, message)
  6. 07. -->7 master->transfer(spi, message)   //回调函数初始化见上9.5
  7. 08.     -->7.1 queue_work(bitbang->workqueue, &bitbang->work); //这个工作队列很重要,当数据加入队列后,它将调用下面接口
  8. 09.         -->7.1.1 bitbang_work(struct work_struct *work)  //该函数是在在工作队列中初始化的,见上9.1
  9. 10.         -->7.1.2 bitbang->txrx_bufs(spi, t)   //最终发送、接收消息,调用上面的9.6
  10. 11.         -->7.1.3 wait_for_completion(&hw->done); //发送消息结束后等待数据接收,是通过下面的中断产生
  11. 12.         -->7.1.4 nuc970_spi0_irq(int irq, void *dev) //见上7.2中断初始化

Linux spi驱动框架之执行流程-nuc970-att7022相关推荐

  1. linux spi不使用框架,Linux spi驱动框架之执行流程

    Linux spi驱动架构由三部分构成:SPI核心层.SPI控制器驱动层.和SPI设备驱动程序. 1.SPI核心层: SPI核心层是Linux的SPI核心部分,提供了核心数据结构的定义.SPI控制器驱 ...

  2. Linux SPI驱动框架(1)——核心层

    概述   linux SPI驱动框架主要分为核心层,控制器驱动层以及设备驱动层.具体结构可参考下图   图中,最下层是硬件空间,SPI总线控制器,总线控制器负责硬件上的数据交互.内核空间中,需要有对应 ...

  3. Linux SPI驱动框架(2)——控制器驱动层

    SPI控制器驱动层   上节中,讲了SPI核心层的东西,这一部分,以全志平台SPI控制器驱动为例,对SPI控制器驱动进行说明. SPI控制器驱动,即SPI硬件控制器对应的驱动,核心部分需要实现硬件SP ...

  4. Linux SPI驱动框架(3)——设备驱动层

    SPI设备驱动层   Linux SPI驱动框架(1)和(2)中分别介绍了SPI框架中核心层,和控制器驱动层.其实实际开发过程中,不是IC原厂工程师比较少会接触控制器驱动层,设备驱动层才是接触比较多的 ...

  5. i.MX6ULL驱动开发 | 13 - Linux SPI 驱动框架

    Linux SPI 驱动框架分为两部分: SPI总线控制器驱动:SOC的 SPI 控制器外设驱动 SPI设备驱动:基于SPI总线控制器驱动编写,针对具体的SPI从机设备 一.SPI总线控制器驱动 基于 ...

  6. i.MX6ULL驱动开发 | 14 - 基于 Linux SPI 驱动框架读取ICM-20608传感器

    本系列文章驱动源码仓库,欢迎Star~ https://github.com/Mculover666/linux_driver_study. 一.ICM20608 1. 简介 InvenSense 的 ...

  7. SPI驱动框架源码分析

     SPI驱动框架源码分析 2013-04-12 16:13:08 分类: LINUX SPI驱动框架源码分析 SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设 ...

  8. Linux驱动修炼之道-SPI驱动框架源码分析(上)

    Linux驱动修炼之道-SPI驱动框架源码分析(上)   SPI协议是一种同步的串行数据连接标准,由摩托罗拉公司命名,可工作于全双工模式.相关通讯设备可工作于m/s模式.主设备发起数据帧,允许多个从设 ...

  9. imx6 通过移植XRM117x(SPI转串口)对Linux中的SPI驱动框架进行分析

    最近分析了一下Linux 中的SPI驱动框架,将自己的理解总结一下,不足之处还请斧正! 1.SPI通信基础知识 SPI(Serial Peripheral Interface)是一种串行(一次发送1b ...

最新文章

  1. 不是python对文件的读操作方法的是-python的文件操作方法
  2. 精通python-轻松打造11周精通python计划(完结) | 软件库
  3. spring boot 集成Mybatis时 Invalid bound statement (not found)
  4. Penn Treebank Tags做点小翻译 (上篇)
  5. 最好用的10款手机库存管理软件,我来教你怎么选
  6. call function中的 exporting/importing/changing
  7. 康师傅就“水源事件”发声明 称矿物质水合标
  8. python的中介效应 调节效应
  9. C++表达式语句实训 对 26 个大写英文字母进行循环加密,输入一个大写英文字母(明文)和一个整数秘钥,输出用秘钥对该大写英文字母加密后的结果(密文)。
  10. 实习日记——Day24
  11. 骨传导耳机对听力有危害吗,骨传导耳机会不会伤害耳朵
  12. 什么是 “VLAN” ?
  13. appium-desktop Capability
  14. 数独-图片定位分割数字
  15. 深度学习系列46:人脸图像超分GFP-GAN
  16. oracle数据库中的虚拟表,Oracle10g中的虚拟专用数据库(VPD)
  17. Linux服务器之间文件同步 inotify+Unison
  18. 在ros中使用opencv启动例程 rosrun robot_vision cv_bridge_test.py 遇到的问题
  19. 小学计算机教学的趣味性,小学数学课堂趣味性研究论文
  20. PayCloud 支付宝支付转账功能发布 V1.0

热门文章

  1. 只有迷信的人,没有迷信的知识
  2. AGV三种导航方式,苏州凌鸟带你走进AGV世界
  3. 李永乐老师讲一个量子计算机,别再只知道罗翔了!网上最受欢迎的14位老师,个个让人“开天眼”!...
  4. Excel 单元格 输入内容后 背景自动变色
  5. rust哪个护甲高_《废土2》全部武器护甲资料及代码
  6. EMOTET,URSNIF,DRIDEXBitPaymer之间的关联性分析
  7. Django 基础(6)-路由Routers-SimpleRouter-DefaultRouter、 action装饰器、URL路径参数
  8. 《纽约客》特写Jeff Dean与Sanjay:谷歌唯二11级工程师,同一台电脑上写代码
  9. neko vm 数据包装翻译
  10. js自定义打印网页内容