背景资料:
我目前有一个连接USB端口的硬件设备。硬件设备负责将精确的周期性消息发送到各种网络上,而这些网络又连接起来。在硬件设备内部,我有两个Microchip dsPIC。有两种操作模式。
一种情况是将简单的“作业”发送到dsPIC,然后可以发送精确到0.001厘米的精确消息。这种架构不适用于更复杂的消息传递,我们需要根据PC应用程序中发生的事件发送周期性数据包。所以我们有第二种操作模式,我们的PC应用程序将发送周期性消息,而dsPIC只是简单地转换和发送。顺便说一句,所有这些对我们软件的最终用户来说都是透明的。我们的硬件设备是汽车领域的测试工具。
目前,我们使用FTDI的USB转串口芯片和FTDI Windows驱动程序将硬件与我们的PC软件连接。
问题在于,在我们从PC发送消息的模式二中,我们能够实现的最佳平均硬件范围约为1ms。我们受到Windows内核抢占。我尝试过一些“技巧”来改进诸如:
之类的东西我们所有的软件都是用C / C ++编写的。我对高级Windows编程非常熟悉和熟悉;例如IO完成,重叠I / O,无锁线程队列(实际上是设计策略),套接字,线程,信号量等......
但是,我对Windows驱动程序开发一无所知。我已经阅读了几篇关于KMDF与UDMF和WDM的论文。
我希望经验丰富的Windows内核模式驱动程序开发人员会在这里做出回应......
下一轮。我们的硬件可以选择更换FTDI芯片并使用dsPIC的USB接口,或者可能将开源Linux FTDI内容移植到Windows,并继续在我们的自定义驱动程序中使用FTDI芯片。我认为通过转到PC端的内核模式驱动程序,我可以建立一个内核驱动程序,可以更精确的间隔发送周期性消息,而不会抢占和/或可能利用DMA。
我们在我们的业务中有一个竞争对手,我认为它与他们的工具完全相似。据我所知,用户空间应用程序无法安排任何优于1ms的线程。我们目前在一个线程中使用timeGetTime。我已经体验过计时器队列(通过CreateTimerQueueTimer)而没有真正的改进。
WDM是否是实现更精确计时的正确方法?
我们的竞争对手如何实现从Windows驱动信号到硬件的非常精确的时序,并且他们确实加载了内核驱动程序(.sys),并且他们的设备通过USB2.0运行,就像我们一样。
如果要采用WDM,我是否可以就建立时序我应该研究哪些内核功能提出建议? 感谢您的阅读
答案 0 :(得分:5)
在内核模式下,您可以轻松获得以100纳秒间隔的倍数触发的DPC,而无需处理中断。 DPC不能被抢占(也被线程调度程序中断),因为线程调度程序也是DPC。中断仍然可以抢占DPC。因此,间隔值为10应该可以让您以最高精度进行回调。
但是,您无法访问许多功能,例如分页内存或DPC级别的特定线程内存空间,因为它们在任意上下文中运行。使用可以访问更多功能的APC将处理推迟到您自己的用户模式进程的上下文可能很有用。
内核线程在优先级方面没有得到任何特殊处理。从调度程序的角度来看,它们与用户线程相同。内核线程可以获得更多优先级更高的级别,但通常没有内核线程使用它们中的任何一个。我不认为你的瓶颈是线程优先。无论您的优先级数量多大都没关系,只有一个优先于其他人就足以让您成为获得最高优先级的“神线”。拥有最高优先级并不意味着你会得到持续的关注。操作系统仍会暂停你的线程以运行其他操作系统,因此不会发生量子饥饿。
关于Windows抢占行为的另一个注意事项:当异步事件(GUI点击,定时器触发器,I / O完成)发出线程信号时,Balance Set Manager会临时提升线程的优先级,以允许完成代码以更少的抢占完成它的处理。使用异步计时器处理程序应该提供足够的提升,以防止至少对量子进行抢占。我想知道为什么你的代码不属于那个窗口。但是,您似乎并不是唯一一个有计时器精度问题的人:http://www.virtualdub.org/blog/pivot/entry.php?id=272
我同意保罗关于驾驶员发展的复杂性,但只要你有充分的理由,那就不是火箭科学,而只是更多的努力。
答案 1 :(得分:1)
这是Windows内核的基本设计方面之一 - 在被动级别运行的代码(=>所有用户模式代码)受DPC影响并且中断占用时间,如果您想要1us精度,那么用UMDF或用户模式驱动程序可能无法获得它。
然而,编写内核驱动程序并不是一件轻松或便宜的事情,它甚至非常难以编写,并且确保它可以在客户的计算机上运行(很多的测试是必需的)。正确的做法将耗费大量的工程资源。
作为权宜之计,我会调查MMCSS for gt; = Vista(http://msdn.microsoft.com/en-us/library/windows/desktop/ms684247(v=vs.85).aspx) ,它可以给你足够的优先权,让你满意。
如果你真的想要走下兔洞,你应该使用KMDF。 KMDF是一个基于WDM的框架,代表了许多针对驱动程序的编码最佳实践。除非你绝对被迫,否则KMDF 始终是驾驶员的最佳选择。说实话,你几乎肯定会想要与OSR(http://www.osr.com)签订合同,或者雇用一些人(几个人?)来编写Windows驱动程序。
答案 2 :(得分:1)
您对驱动程序和内核性能的关注错过了树木的森林。房间里的大象是全速USB 2总线帧以1ms周期发生的事实。高速USB 2微帧每1/8秒发生一次。
当您通过全速USB发送数据时(就像大多数FTDI芯片一样),您的应用程序所希望的最好的是期间数据将在某个时间到达设备下一个框架。使用卸载的USB总线,传输将非常接近帧起始。您将观察它为1ms粒度,具有小的随机偏差。这正是你所看到的,也不错。例如,由于连接到同一主机的所有USB设备将同时看到帧,因此这是一种以超过微秒精度同步多个设备时钟的简单方法。您的应用程序可以做的只是发送一条消息,该消息不仅包含数据,而且在不久的将来应该发送的时间。 USB的另一个问题是无法保证何时为您的数据传输请求提供服务。毕竟,你正在与其他设备共用一辆公共汽车。
我认为你需要重新设计你的系统,而不是依赖于PC端的任何时间。应该假设在PC上运行的应用程序在时间上限于与其交互的人的性能。任何需要保证实时性能的东西必须在您的dsPIC设备上。即使是USB总线也没有削减它,因为您无法保证在多长时间内将您的请求安排在总线上。
基本上,如果您希望在Windows上保证实时性能,则必须不涉及用户模式 - 它必须所有在内核模式下运行,并且您必须使用适用于您的独家使用(或者您可以按照这种方式行事,例如通过直接在USB主机上过滤)。