Linux spi驱动框架之执行流程
来源:互联网 发布:手机棋牌源码 编辑:程序博客网 时间:2024/05/21 09:51
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控制器驱动同时也要负责对这些请求进行队列管理,保证先进先出的原则 。
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设备驱动程序:
这里要注意struct spi_device *spi 该spi的参数是通过arch/arm/mach-nuc970.c struct spi_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驱动框架之执行流程
- Linux spi驱动框架之执行流程-nuc970-att7022
- Linux驱动修炼之道-SPI驱动框架源码分析
- Linux驱动修炼之道-SPI驱动框架源码分析
- Linux驱动修炼之道-SPI驱动框架源码分析
- Linux SPI驱动框架剖析
- linux中spi驱动框架
- Linux SPI驱动框架剖析
- Linux SPI设备驱动框架
- linux spi驱动与应用调用流程
- Linux SPI驱动之笔记
- 嵌入式linux之SPI驱动
- 和菜鸟一起学linux总线驱动之初识spi驱动数据传输流程
- 和菜鸟一起学linux总线驱动之初识spi驱动数据传输流程
- Linux下spi驱动开发理论框架
- 65 linux spi设备驱动之spi LCD屏驱动
- Linux驱动修炼之道-SPI驱动框架源码分析(上)
- MyEclipse 导入的项目WEB-INF文件夹变成包的解决方案
- [待完成]移动端SO加固-简单梳理[待完成]
- 带你实现开发者头条APP(四)---首页优化(加入design包)
- 经验总结
- mysql 普通索引 唯一索引的创建与效率比较
- Linux spi驱动框架之执行流程
- Windows编程学习之路--框架介绍
- ADO.NET
- 用java写计算器
- 《LeetBook》leetcode题解(19):Remove Nth Node From End of List[E]——双指针解决链表倒数问题
- Uva 10905 Children's Game
- 技术分析之CSS+div
- ubuntu安装ftp服务器——vsftpd,实现ftp传输文件
- PHP学习中遇到的小坑