当前位置: 首页 > news >正文

Linux SPI子系统跟踪打印

主要跟踪复杂容易出现误解的函数,忽略spi_init()函数,这个函数主要注册bus以及class,基本上不会出错。主要打印查看以下函数:

主机层初始化

#defineSPI_LOG(fmt,...)\printk(KERN_ERR"[SPI-IMX] %s: "fmt"\n",__func__,##__VA_ARGS__)

开始时调用

SPI_LOG("probe start");

从设备树读取cs信息并初始化

ret=of_property_read_u32(np,"fsl,spi-num-chipselects",&num_cs);SPI_LOG("num_cs=%d",num_cs);intcs_gpio=of_get_named_gpio(np,"cs-gpios",i);SPI_LOG("cs[%d]=%d",i,cs_gpio);

查看寄存器的基地址

spi_imx->base=devm_ioremap_resource(&pdev->dev,res);SPI_LOG("base=%p",spi_imx->base);

打印获取到的中断号

irq=platform_get_irq(pdev,0);if(irq<0){ret=irq;gotoout_master_put;}SPI_LOG("irq=%d",irq);

打印SPI时钟

spi_imx->spi_clk=clk_get_rate(spi_imx->clk_per);SPI_LOG("spi_clk=%lu",spi_imx->spi_clk);

打印DMA初始化结果

if((spi_imx->devtype_data==&imx51_ecspi_devtype_data||spi_imx->devtype_data==&imx6ul_ecspi_devtype_data)&&spi_imx_sdma_init(&pdev->dev,spi_imx,master,res))dev_err(&pdev->dev,"dma setup error,use pio instead\n");elseSPI_LOG("spi_imx: dma setup ok");

打印probe结果

SPI_LOG("probed successfully");

编译后结果

可以看出probe成功初始化。
除此以外,probe函数中还进行了bitbang的初始化以及控制器向核心层设备的注册
在核心层的注册函数中加入

of_register_spi_devices(master);SPI_CORE_LOG("devcice registered\n");

可以看到成功创建了设备:

这样总线上就已经挂载了主机设备,现在来看看用户驱动如何通过总线与主机设备匹配上的。

用户驱动注册

当用户驱动调用spi_register_driver()注册到内核时,总线核心代码会遍历挂在 SPI 总线上的所有设备,并调用这个函数来判断设备和驱动是否匹配

这里使用insmod注册驱动,可以发现

用户驱动注册后,APP便要调用write和read函数来操作,这个操作都是通过同步传输实现的。
同时注意到,linux内核初始化时

说明设备被添加到总线上时,也会与编译进入内核的驱动进行匹配。

同步通信

根据代码分析spi_sync函数最终会调用__spi_sync函数
首先绑定完成量

然后会在__spi_queued_transfer中将message加入队列尾部

随后,调用__spi_pump_messages来调用底层硬件来发送,注意到这里的bool类型 is kworker为false,通过看注释发现其取消了使用线程来发送,这是为了节省上下文切换的空间,如果是异步的话就是会调用线程

需要注意的是,sync和async都会调用这个函数,唯一的区别是,这个函数sync是自己调用的,为了节约时间,将任务分配给了kworker去做,而async全部都交给kworker去执行。

在__spi_pump_messages中插入

可以注意到,在sync中,并没有代码发送信号量完成,这时我们要观察硬件代码,通过代码分析,实际上spi-imx只提供了xfer函数,主要发送还是有bitbang框架实现,所以在bitbang框架中加入





可以看到最后bitbang还调用了spi.c中的函数,用来发送完成量,在完成量函数中也加入消息完成log,接下来我们来看主机层主要实现的函数

在函数中加入log

只有数据量大的时候才会用DMA

最后会调用push来推送数据,并等待xfer_done完成量,在push中加入以下log


这里的xfer_done完成量会在中断中调用,同时,中断还会接收消息


![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/78cfd731baf2428989eeb49933f9bb56.png
可以发现代码确实如分析所反应的一样,通过pump来调用bitbangbitbang调用transfer,然后调用push,最后引起主机层中断,在中断中处理读取数据,并发送完成xfer_done标志,当bitbang完成后,就会发送完成complete标志给sync函数,最终完成一次同步信息传输,同时调用kworker来清理,同时上面的ASYNC标识后面会解释。

可以看出上文中并没有使用到kworker,因为sync为了避免上下文切换直接发送了消息,接下来将驱动中的sync替换为async,并进行分析:

异步通信


这里之前分析sync的时候已经查看过了,唯一不同的是这里会将pump_messages加入kworker中驱动

这里的pump_messages被绑定为如下函数,可以看出这个函数我们之前在SYNC中就被调用过了,但是当时其并没有输入true

在这里加入kwoker清空的情况

后面的过程就与SYNC相似了,直接用之前写好的log

将驱动中的读取SYNC换成ASYNC,结果为

staticvoidicm20608_spi_complete(void*arg){structcompletion*done=arg;complete(done);}staticinticm20608_read_regs(structicm20608_dev*dev,u8 reg,void*buf,intlen){intret;unsignedchartxdata[1];unsignedchar*rxdata;structspi_messagem;structspi_transfert;structspi_device*spi=(structspi_device*)dev->private_data;DECLARE_COMPLETION_ONSTACK(done);rxdata=kzalloc(len+1,GFP_KERNEL);if(!rxdata)return-ENOMEM;txdata[0]=reg|0x80;memset(&t,0,sizeof(t));t.tx_buf=txdata;t.rx_buf=rxdata;t.len=len+1;spi_message_init(&m);spi_message_add_tail(&t,&m);m.complete=icm20608_spi_complete;m.context=&done;ret=spi_async(spi,&m);if(ret)gotoout;wait_for_completion(&done);memcpy(buf,rxdata+1,len);out:kfree(rxdata);returnret;}



可以看出除了开始化过程其他与SYNC一致。

http://www.jsqmd.com/news/542231/

相关文章:

  • 微信小程序分包反编译全攻略:用wxappUnpacker处理master和sub-xxx.wxapkg
  • 153饮食营养管理信息系统-springboot+vue
  • 依然似故人_孙珍妮Z-Image-Turbo镜像部署:Xinference模型API限流配置
  • OpenClaw安全防护方案:ollama-QwQ-32B本地化部署的风险控制
  • OpenClaw私有化部署Qwen3-VL:30B:飞书助手配置指南
  • AI显微镜-Swin2SR基础教程:理解‘细节重构技术’对AI生成图的价值
  • 开源鸿蒙横竖屏切换
  • Super Qwen Voice World效果惊艳:‘金币数量’HUD实时反映生成计数
  • 如何高效批量下载抖音内容:从单视频到用户主页的完整解决方案
  • Apache IoTDB Web Workbench:告别命令行,拥抱可视化时序数据库管理新时代
  • 达摩院PALM春联模型多场景落地:政务大厅自助春联机解决方案
  • Qwen3-ASR-0.6B惊艳效果:藏语、维吾尔语等少数民族语言识别案例
  • 零基础玩转OpenClaw:Qwen3-32B镜像实现首个自动化任务
  • 快速掌握文本编码:ESFT-token-code-lite入门指南
  • 短效代理是什么?它有什么用?一文讲清定义、特点与应用价值
  • 百度网盘非会员限速如何破解?这个开源工具让你下载速度提升3倍!
  • SDMatte图像预处理建议:曝光校正、去噪、锐化对抠图质量影响量化分析
  • YOLO系列专栏(一):YOLO 2026 数据集增强 | 图像 + 标签同步增强,多方法高效实现
  • 像素时装锻造坊应用场景:Metaverse虚拟形象像素皮肤批量定制服务
  • 79.单词搜索
  • ubuntu22.04环境鸿蒙全仓代码编译配置
  • Gemma-3 Pixel Studio镜像免配置:开箱即用的12B多模态推理工作站
  • Vite项目实战:解决monaco-editor中文汉化失败的3种方法(附最新语言包下载)
  • 从输入网址到访问服务器响应返回客户端
  • 155农村事务管理与交流平台系统-springboot+vue+微信小程序
  • 功能齐全的屏幕截图C++实现详解(附源码)
  • 智能周报生成器:OpenClaw+百川2-13B自动汇总工作成果
  • 156湖南交通工程学院学生就业信息系统-springboot+vue
  • 告别理论!用Cobalt Strike实战红日靶场:从蚁剑上线到SMB Beacon横向移动的避坑指南
  • 什么时候会触发FullGC