前言
Linux i2c子系统源码分析--Apple的学习笔记源码分析过,那么接下来就分析下spi的。从makefile来看spi要比i2c的结构简单。但是看源码的时候特别是发送函数一开始会混乱,没找到函数注册的地方。后来网上查了资料后,原来我kthread相关的API不清楚导致我快速看关键函数时候没注意到关联关系。
一,kthread学习
简单来说可以理解为我之前学习c++时候自己做的线程池的概念。它有一个worker就是一个线程池,把work挂入到worker后,就由worker线程池来调度运行了。
二,spi子系统源码分析
首先思考一个问题,看i2c的时候没有用到内核线程kthread,或者说kthread可能用到了,但是不是重点内容,为什么spi中它很重要呢?为什么要用这样的设计。我思考了下因为spi传输速度快,所以一般使用fifo并且开启DMA,而不像i2c用个thread中断即可解决。
好了,言归正传,我其实想通过对比i2c来学习。
-
比如i2c它的omap芯片级别的probe函数中会调用core中的register函数来注册设备。是否spi也如此?答案是的。probe函数会调用spi_register_controller,此函数里面会创建设备device_add,然后会调用初始化工作线程spi_controller_initialize_queue包括spi_pump_messages绑定到工作线程中。同时会注册
ctlr->transfer_one_message = spi_transfer_one_message;
-
i2c的probe函数会给adapter适配器注册每个芯片的algo传输算法(就是底层和芯片寄存器设置相关的的发送函数啦)。答案是的。
它比i2c简单,没有适配器的概念。直接在master中的chip注册发送函数master->transfer_one = omap2_mcspi_transfer_one;
-
发送函数使用了内核线程,函数关系如下
spi_sync
-->spi_queued_transfer
---->__spi_queued_transfer里面会调用kthread_queue_work(&ctlr->kworker, &ctlr->pump_messages);
开启内核工作线程spi_pump_messages
spi_pump_messages中调用
-->__spi_pump_messages
----> ctlr->transfer_one_message里面会调用ctlr->transfer_one(ctlr, msg->spi, xfer);而这个回调函数就是omap probe函数中注册的。 -
linux的spi有spi_transfer是最小单位包含在spi_message中。message可以当然任务控制对象,而transfer可以当做数据对象。所以任务装载数据去控制发送,所以transfer包含在message中,我是这样理解的哈~
网友评论