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

1.SPI核心层:

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

2.SPI控制器驱动程序:

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

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

structspi_master {

structdevice   dev;

s16         bus_num;

u16         num_chipselect;

int(*setup)(structspi_device *spi);

int(*transfer)(structspi_device *spi,structspi_message *mesg);

void(*cleanup)(structspi_device *spi);

}

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

01.-->nuc970_spi0_probe(struct platform_device *pdev) //完成如下的初始化

02. -->1. init_completion(&hw->done); //完成量初始化

03. -->2. hw->bitbang.setup_transfer = nuc970_spi0_setupxfer; //设置spi的寄存器参数

04. 2.1 nuc970_spi0_update_state(spi, t); //更新传输模式

05. 2.2 nuc970_spi0_setup_txbitlen(hw, hw->pdata->txbitlen); //字节发送长度

06. 2.3 nuc970_tx_edge(hw, hw->pdata->txneg); //发送边沿

07. 2.4 nuc970_rx_edge(hw, hw->pdata->rxneg); //接受边沿

08. 2.5 nuc970_set_clock_polarity(hw, hw->pdata->clkpol); //空闲时的时钟极性

09. 2.6 nuc970_send_first(hw, hw->pdata->lsb); //字节传输顺序,0-高bit先传输

10. -->3. hw->bitbang.chipselect = nuc970_spi0_chipsel; //芯片选择,目前同一个spi总线下面芯唐支持2个从设备

11. 3.1 nuc970_slave_select(spi, 0); //BITBANG_CS_INACTIVE

12. 3.2 nuc970_slave_select(spi, 1); //BITBANG_CS_ACTIVE

13. -->4. hw->bitbang.txrx_bufs = nuc970_spi0_txrx; //这个函数很重要!负责spi驱动与底层寄存器数据的发

14. //送、接收,这里直接发送,通过中断接收数据(第7.2点),

15. //发送与接收的桥梁是通过“完成量”完成的(第1.点)

16. 4.1 nuc970_spi0_gobusy(hw); //发送完数据进入忙等待

17. 4.2 wait_for_completion(&hw->done); //等待完成量(第7.2.1),否则进入休眠等待

18. -->5. hw->bitbang.master->setup = nuc970_spi0_setup; //spi0设置

19. -->6. platform_get_resource(pdev, IORESOURCE_MEM, 0) //获取寄存器的IO资源

20. 6.1 hw->ioarea = request_mem_region(hw->res->start,resource_size(hw->res), pdev->name); //资源申请

21. 6.2 hw->regs = ioremap(hw->res->start, resource_size(hw->res)); //资源映射

22. -->7. hw->irq = platform_get_irq(pdev, 0); //获取中断资源

23. 7.1 request_irq(hw->irq, nuc970_spi0_irq, 0, pdev->name, hw); //申请中断功能

24. 7.2 nuc970_spi0_irq(int irq, void *dev) //注意这个终端函数很重要,它负责接收底层spi寄存器上传的数据(与第4点相反)

25. 7.2.1 complete(&hw->done); //中断接收数据完成,置“完成量”标志,唤醒第4.2

26. -->8. nuc970_init_spi(hw); //spi初始化

27. 8.1 clk_prepare(hw->clk);

28. 8.2 clk_enable(hw->clk);

29. 8.3 spin_lock_init(&hw->lock);

30. 8.4 nuc970_tx_edge(hw, hw->pdata->txneg);

31. 8.5 nuc970_rx_edge(hw, hw->pdata->rxneg);

32. 8.6 nuc970_send_first(hw, hw->pdata->lsb);

33. 8.7 nuc970_set_sleep(hw, hw->pdata->sleep);

34. 8.8 nuc970_spi0_setup_txbitlen(hw, hw->pdata->txbitlen);

35. 8.9 nuc970_spi0_setup_txnum(hw, hw->pdata->txnum);

36. 8.10 nuc970_set_divider(hw);

37. 8.11 nuc970_enable_int(hw);

38. -->9. spi_bitbang_start(&hw->bitbang);

39. 9.1 INIT_WORK(&bitbang->work, bitbang_work); //初始化工作队列,绑定工作队列处理的函数

40. 9.2 bitbang_work(struct work_struct *work) //工作队列处理函数

41. 9.3 status = bitbang->setup_transfer(spi, t); //设置spi寄存器参数,函数初始化见第2.点,函数内容见第2.1~2.6

42. 9.4 bitbang->chipselect(spi, BITBANG_CS_ACTIVE); //

43. 9.5 master->transfer = spi_bitbang_transfer; //这个函数很重要,下面的第7.点将被调用

44. 9.6 bitbang->txrx_bufs(spi, t); //发送、接收数据,见第4.点初始化,这个函数很重要!!!

3、SPI设备驱动程序:

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

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

执行流程如下:

01.-->1 att7022e_read_reg() //发送、接收消息, 将调用spi.c核心层

02.-->2 spi_write_then_read(spi,txbuf, n_tx, rxbuf, n_rx)

03.-->3 spi_sync(spi, &message)

04.-->4 __spi_sync(spi, message, 0)

05.-->5 spi_async_locked(spi, message)

06.-->6 __spi_async(spi, message)

07.-->7 master->transfer(spi, message) //回调函数初始化见上9.5

08.-->7.1 queue_work(bitbang->workqueue, &bitbang->work); //这个工作队列很重要,当数据加入队列后,它将调用下面接口

09.-->7.1.1 bitbang_work(struct work_struct *work) //该函数是在在工作队列中初始化的,见上9.1

10.-->7.1.2 bitbang->txrx_bufs(spi, t) //最终发送、接收消息,调用上面的9.6

11.-->7.1.3 wait_for_completion(&hw->done); //发送消息结束后等待数据接收,是通过下面的中断产生

12.-->7.1.4 nuc970_spi0_irq(int irq, void *dev) //见上7.2中断初始化

linux spi不使用框架,Linux spi驱动框架之执行流程相关推荐

  1. Linux驱动框架之framebuffer驱动框架

    1.什么是framebuffer? (1)framebuffer帧缓冲(一屏幕数据)(简称fb)是linux内核中虚拟出的一个设备,framebuffer向应用层提供一个统一标准接口的显示设备.帧缓冲 ...

  2. linux pcie驱动框架_Linux设备驱动框架设计

    引子 Linux操作系统的一大优势就是支持数以万计的芯片设备,大大小小的芯片厂商工程师都在积极地向Linux kernel提交设备驱动代码.能让这个目标得以实现,这背后隐藏着一个看不见的技术优势:Li ...

  3. linux驱动程序混合架构,嵌入式系统最小驱动框架(类似linux驱动程序架构)(示例代码)...

    2010年就打算把linux里的驱动框架核心代码抠出来的,但是由于懒而且linux代码量大,一直下不了手.最近调试的intel curie里驱动架构也类似linux,代码就少多了,由于工作需要不得不梳 ...

  4. Linux 有/无设备树下 platform_driver 驱动框架

    文章目录 platform 驱动框架 platform 设备框架 有设备树下驱动开发注意事项 宏___一行代码创建 platform_driver platform 驱动框架 首先,定义一个 plat ...

  5. 驱动框架5——基于驱动框架写led驱动

    以下内容源于朱有鹏<物联网大讲堂>课程的学习整理,如有侵权,请告知删除. 五.基于驱动框架写led驱动1 1.分析 (1)参考哪里?  drivers/leds/leds-s3c24xx. ...

  6. 驱动框架2——内核驱动框架中LED的基本情况、初步分析

    以下内容源于朱有鹏嵌入式课程的学习,如有侵权,请告知删除. 一.内核驱动框架中LED的基本情况 1.相关文件 (1)drivers/leds目录 驱动框架规定的LED这种硬件的驱动应该待的地方. (2 ...

  7. ThinkPHP框架开发的应用的标准执行流程

    用户URL请求 调用应用入口文件(通常是网站的index.php) 载入框架入口文件(ThinkPHP.php) 记录初始运行时间和内存开销 系统常量判断及定义 载入框架引导类(Think\Think ...

  8. 西数加密linux,Symantec PGP Desktop pgpwded.sys内核驱动任意代码执行漏洞

    发布日期:2012-12-24 更新日期:2012-12-27 受影响系统: Symantec PGP Desktop 10.2.0 Build 2599 描述: ------------------ ...

  9. 学习Struts--Chap02:Struts2框架各个功能模块和程序执行流程的介绍

    1.Struts2的系统架构: 2.架构中不同Key的作用介绍: servlet Filters:过滤器链,client的全部请求都要经过Filter链的处理. Struts Core:Struts2 ...

  10. Linux V4l2驱动 -- 框架概述

    V4l2框架简述 1 硬件 常用的电脑摄像头是USB接口,主流的智能手机摄像头是MIPI接口,另外还有像树莓派等硬件使用的CSI接口的设备.常用的智能手机Camera采用的MIPI接口,电路框架以及电 ...

最新文章

  1. ACMNO.26 C语言-字符统计2 编写一函数,由实参传来一个字符串,统计此字符串中字母、数字、空格和其它字符的个数,在主函数中输入字符串以及输出上述结果。 只要结果,别输出什么提示信息。
  2. 12. MySQL简单使用
  3. Nginx配置pathinfo
  4. bugku ctf 杂项 啊哒 writeup || foremost的安装
  5. python基础学习[python编程从入门到实践读书笔记(连载三)]:django学习笔记web项目
  6. 自然语言处理-nltk学习(一)
  7. box2d 遍历世界中 body 的方法
  8. 带有Guice的富域模型
  9. OSI七层模型详解-开放系统互联参考模型详解
  10. 怎样查询2021高考模拟成绩,2021年高三一模二模三模哪个成绩更接近高考成绩,看看网友是怎么评论...
  11. Windows Server 2016 Technical Preview 4 (x64) 简体中文版下载!
  12. [USACO 07DEC]Best Cow Line, Gold
  13. 使用github+hexo搭建静态博客
  14. 定制一个winCE5.0操作系统
  15. 神经网络计算棒怎么用,英特尔神经网络计算棒
  16. win7下l2pt/sec 的789报错解决
  17. LA 3406 Bingo *
  18. 暴露在公网环境下主机的安全防护
  19. 如何在QEMU上执行iOS并启动一个交互式bash shell,内含整个安装流程并且提供了相关工具(二)
  20. 干货来袭!手动搭建高可用的Redis5-0分片集群

热门文章

  1. Getting started with Bitcoin
  2. 从头算和密度泛函理论_PHP Laravel教程–如何从头开始构建关键字密度工具
  3. dropbox免费容量_免费课程:使用ES6和Dropbox构建费用管理器
  4. 容纳10万人服务器多少钱_令人尴尬的故事:为什么我的服务器只能容纳10名玩家...
  5. mysql和oracle的mybatis操作
  6. 计算机支持的游戏化教学,初中信息技术教学中游戏化教学的应用探究
  7. Python爬虫必备技能,Xpath提取数据规格详解
  8. 用Python爬取Bilibili视频,难吗?
  9. HTML和CSS进阶
  10. 万字长文带你从零开始认识机器学习