最近调试Windows平台下的PCIe网络驱动程序时,发现了中断不被处理的情况,怀疑中断丢失。随后在调试过程中将问题定位在如下两个方面。
DMA写重复启动
我们在Windows下使用WDF框架开发PCIe驱动的DMA读写功能。驱动要启动一次DMA传输包括两个步骤
初始化DMA传输对象
执行DMA传输
初始化DMA传输对象时,应将本次DMA要传输的数据缓冲区的地址和长度写入该对象,并向其注册用于配置并启动DMA传输的回调函数PCIeEvtProgramWriteDma。该回调函数会获取缓冲区地址和长度,通过PIO方式配置PCIe Bar空间上的寄存器,以通知硬件启动DMA传输。
执行DMA传输时,驱动仅需调用WDF框架的WdfDmaTransactionExecute函数,操作系统就会调用上一步注册的回调函数对硬件进行配置并启动DMA传输。
正常来讲,驱动调用一次WdfDmaTransactionExecute函数,相应地操作系统应调用一次回调函数进行硬件配置。但我们更换硬件平台(CPU+FPGA)后,DMA写流程出现了严重问题,具体表现为:前者的一次调用可能会对应着后者的多次调用,且每次回调函数都会完整执行并触发DMA写完成中断,从而造成了驱动的中断状态机被打乱,直接表现是后续的DMA写开始中断丢失,无法正常启动DMA写。
如下,图1是驱动调用WdfDmaTransactionExecute函数的次数与操作系统调用回调函数的次数不一致的截图。
图1 DebugMonito监测
其中,5658(5576+82+0)为驱动调用WdfDmaTransactionExecute函数的次数,5664为操作系统调用回调函数的次数。二者之间差6就是操作系统重复调用的次数。
我们尝试将操作系统多出来的调用回调函数的次数跳过,即仅保留第一次调用。硬件侧可以正常完成这次DMA传输,并触发DMA写完成中断。但驱动去查询DMA传输对象时,发现此次DMA传输并未处于完成状态,即无法正常接收数据。至此,我们猜测,操作系统多次调用回调函数的原因是其认为配置过程出错才重新进行配置,直至最后一次成功。而硬件侧并不会感知到这种错误,每次都正常启动DMA写并触发DMA写完成中断,导致驱动的中断状态机跑飞。
问题排查到这里,我们无法深入到闭源的Windows操作系统内部去探究错误原因了。所以思路一转,我们尝试能否为中断状态机提供一些保障机制。
驱动的中断状态机
为了方便调试,我们在中断处理程序中添加了许多关键的调试日志信息,结果在其中发现了端倪。
图2 日志打印记录
观察图2中的日志,发现两个中断延迟处理函数MPHandleInterrupt在并行执行。在这个过程中,用于临时拷贝中断寄存的变量Adapter->IsrCode_dpc被覆盖重写。覆盖的直接后果是,前者已读取到的寄存的中断,后者覆盖后就无法由中断延迟处理程序进行处理。
这种现象显然是不合理的。为了解决这个问题,我们为MPHandleInterrupt函数内部加锁,防止MPHandleInterrupt并行执行。通过这种方式,中断寄存被覆盖的现象不再发生。
审核编辑:汤梓红
-
寄存器
+关注
关注
31文章
5377浏览量
121394 -
接口
+关注
关注
33文章
8728浏览量
152105 -
WINDOWS
+关注
关注
4文章
3584浏览量
89481 -
PCIe
+关注
关注
15文章
1268浏览量
83322 -
dma
+关注
关注
3文章
566浏览量
101100
原文标题:PCIe接口中断驱动寄存器被覆盖问题的发现与解决
文章出处:【微信号:HXSLH1010101010,微信公众号:FPGA技术江湖】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
基于DWC2的USB驱动开发-控制传输中断相关寄存器
![基于DWC2的USB<b class='flag-5'>驱动</b>开发-控制传输<b class='flag-5'>中断</b>相关<b class='flag-5'>寄存器</b>](https://file1.elecfans.com/web2/M00/8D/8B/wKgZomS9UAOANWTFAAAxMxJuNTY487.jpg)
寄存器移位时,数据不会被覆盖吗?
求教:关于DM8168的PCIe寄存器
如何选择51单片机的中断寄存器组
![如何选择51单片机的<b class='flag-5'>中断寄存器</b>组](https://file.elecfans.com/web1/M00/8E/E9/pIYBAFy21K6AFyujAAPIAjQFeEA892.png)
STC学习:中断相关寄存器
![STC学习:<b class='flag-5'>中断</b>相关<b class='flag-5'>寄存器</b>](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
串口中断服务函数的触发
![串<b class='flag-5'>口中断</b>服务函数的触发](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
STM32串口通信相关寄存器和中断回调函数
![STM32串口通信相关<b class='flag-5'>寄存器</b>和<b class='flag-5'>中断</b>回调函数](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
U54内核中断控制和状态寄存器
![U54内核<b class='flag-5'>中断</b>控制和状态<b class='flag-5'>寄存器</b>](https://file1.elecfans.com/web2/M00/A7/0C/wKgaomUiClCAYXatAAJwvh19Wzs021.jpg)
CPSR寄存器和APSR寄存器的组成
![CPSR<b class='flag-5'>寄存器</b>和APSR<b class='flag-5'>寄存器</b>的组成](https://file1.elecfans.com/web2/M00/A9/81/wKgaomUx9ouAWofzAAALnAx1HZw790.png)
评论