DSP

Windows DMA驱动调试

2019-07-13 20:16发布

        本文记录我调试微软官方提供的一个PCI驱动sample程序的过程。 一、开发环境和资源下载 1,在win10 X64操作系统下,安装VS2015+WDK10。(参考我前面的驱动开发入门篇) 2,使用TI6655 DSP开发板,点击打开链接 3,下载微软官方发布在github上的驱动samples,点击打开链接,选择其中的“General/PLX9x5x”这个工程。 4,参考微软关于windows dma技术的文档,点击打开链接,该文档即以上面的工程代码为实例。 5,参考程序员博客:点击打开链接
二、调试过程 1,使用VS2015直接编译PLX9x5x工程,需选择debug模式和X64环境。         该工程分为sys和test两个模块,前者是驱动代码,后者是一个应用程序。 2,该工程中的inf文件(实际工程中是“.inx”,编译后会生产inf),其GUID和代码的public.h中的不一致,需修改为一致。这是唯一需要修改的地方。 3,将DSP开发板的venID和devID修改与inf文件中一致,在DSP侧修改即可。修改后,可以在“Windows设备管理”中查看。 (windows键+R,打开CMD,然后输入“devmgmt.msc”即可打开设备管理器;右键目标设备,选择属性,可以看详细信息,其中“硬件ID”即inf中需要填写一致的内容)
执行完以上操作,即可安装驱动,但此时驱动安装后显示不正确。实际上是没有配置DSP的“配置空间”。 4,在驱动的各个Routine中添加"KdPrint“打印信息,使用debugview查看驱动加载过程中的函数调用。 5,在init.c文件中的preparehardware函数中,扫描到memory resource后的地方,添加DSP配置空间的配置操作(调用DDK提供的写寄存器函数)。 // // Parse the resource list and save the resource information. // for (i=0; i < WdfCmResourceListGetCount(ResourcesTranslated); i++) { desc = WdfCmResourceListGetDescriptor( ResourcesTranslated, i ); if(!desc) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, "WdfResourceCmGetDescriptor failed"); return STATUS_DEVICE_CONFIGURATION_ERROR; } switch (desc->Type) { case CmResourceTypeMemory: bar = NULL; if (foundSRAM && !foundSRAM2 && desc->u.Memory.Length == 0x400000) { SRAM2BasePA = desc->u.Memory.Start; SRAM2Length = desc->u.Memory.Length; foundSRAM2 = TRUE; bar = "BAR3"; KdPrint(("BAR3 found. ")); } if (foundRegs && !foundSRAM && desc->u.Memory.Length == 0x100000) { SRAMBasePA = desc->u.Memory.Start; SRAMLength = desc->u.Memory.Length; foundSRAM = TRUE; bar = "BAR2"; KdPrint(("BAR2 found. " )); } if (!foundRegs && desc->u.Memory.Length == 0x1000) { regsBasePA = desc->u.Memory.Start; regsLength = desc->u.Memory.Length; foundRegs = TRUE; bar = "BAR0"; KdPrint(("BAR0 found. ")); } TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, " - Memory Resource [%I64X-%I64X] %s", desc->u.Memory.Start.QuadPart, desc->u.Memory.Start.QuadPart + desc->u.Memory.Length, (bar) ? bar : "" ); KdPrint(("desc->u.Memory.Start is %x, desc->u.Memory.length is %x ", desc->u.Memory.Start, desc->u.Memory.Length)); break; 以上代码作用:扫描资源列表,获取windows操作系统为device分配的memory资源(可以再设备管理器的属性-》资源中看到)。保存系统分配的几块memory的基地址和长度。 6,将系统分配的空间基址和长度进行转换 // Map in the Registers Memory resource: BAR0 // DevExt->RegsBase = (PUCHAR) LocalMmMapIoSpace(regsBasePA, regsLength); if (!DevExt->RegsBase) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " - Unable to map Registers memory %08I64X, length %d", regsBasePA.QuadPart, regsLength); return STATUS_INSUFFICIENT_RESOURCES; } DevExt->RegsLength = regsLength; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, " - Registers %p, length %d", DevExt->RegsBase, DevExt->RegsLength ); // // Set seperated pointer to PCI9656_REGS structure. // DevExt->Regs = (PPCI9656_REGS) DevExt->RegsBase; DevExt->Bar0Regs = (PBAR0_REGS)DevExt->RegsBase; // // Map in the SRAM Memory Space resource: BAR1 // DevExt->SRAMBase = (PUCHAR) LocalMmMapIoSpace(SRAMBasePA, SRAMLength); if (!DevExt->SRAMBase) { TraceEvents(TRACE_LEVEL_ERROR, DBG_PNP, " - Unable to map SRAM memory %08I64X, length %d", SRAMBasePA.QuadPart, SRAMLength); return STATUS_INSUFFICIENT_RESOURCES; } DevExt->SRAMLength = SRAMLength; TraceEvents(TRACE_LEVEL_INFORMATION, DBG_PNP, " - SRAM %p, length %d", DevExt->SRAMBase, DevExt->SRAMLength );
7,DSP的“Configure空间”配置
// configure dsp bar { i = 0; WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_bar, i); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_start_lo, regsBasePA.u.LowPart); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_start_hi, regsBasePA.u.HighPart); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_offset, PCIE_BASE_ADDRESS); } { i = 1; WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_bar, i); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_start_lo, SRAMBasePA.u.LowPart); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_start_hi, SRAMBasePA.u.HighPart); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_offset, MSMC_START); } { i = 2; WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_bar, i); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_start_lo, SRAM2BasePA.u.LowPart); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_start_hi, SRAM2BasePA.u.HighPart); WRITE_REGISTER_ULONG((PULONG)&DevExt->Bar0Regs->ib_info[i].ib_offset, DDR_START); } DSP配置正确,此时再加载驱动,即显示运行正常。(DSP的配置可以根据芯片资料配置) 6,测试DMA读操作,需先注释init.c中的中断调用部分代码和read.c中的DMA操作硬件部分的代码。 7,添加相关的打印。 8,将error的初始值由FALSE改为TRUE,从而可以执行后面的completerequest操作,推出该Routine。 执行完以上操作,可以运行test工程,来查看read过程的函数调用(debugview)。 暂时调试到该步骤。
四、DMA配置 其实际就是将CommonBuffer的物理地址告诉DSP
三、经验总结 1,在驱动工程中,不要放其他inf文件,VS会优先编译inf文件,而不编译inx文件,会反复报编译错误。 2,用F5运行test程序时,报”createfile“失败。查看getlasterror,返回值为5——拒绝访问,这是权限不够引起的。需要以管理员身份运行VS或改程序。(应用程序掉系统函数失败,查看getlasterror非常重要) 3,需要禁用数字签名,参考我之前的相关博客。