GpioClx DDI 中的驱动程序支持方法

gpioClx) (GPIO 框架扩展从 Windows 8 开始可用。 GpioClx DDI 中系统提供的方法在 GpioClx 内核模式驱动程序中实现,Msgpioclx.sys。 此驱动程序导出 GpioClx 驱动程序支持方法的入口点。 从Windows 8开始,Msgpioclx.sys是操作系统的标准组件。

在生成时,GPIO 控制器驱动程序静态链接到 GpioClx 存根库 Msgpioclxstub.lib 中的 DDI 入口点。 在运行时,此库执行必要的驱动程序版本协商,以动态链接到Msgpioclx.sys中的相应入口点。

需要特定版本的Msgpioclx.sys的 GPIO 控制器驱动程序可以安全地链接到具有更高版本号的Msgpioclx.sys版本。 但是,此驱动程序无法链接到版本号较低的Msgpioclx.sys版本。

驱动程序注册

若要注册为 GpioClx 的客户端,GPIO 控制器驱动程序调用 GPIO_CLX_RegisterClient 方法。 通常,驱动程序从其 DriverEntry 例程调用此方法。 在此调用期间,驱动程序会将注册数据包传递给 方法。 此数据包包含指向一组驱动程序实现的事件回调函数的指针。 这些函数访问 GPIO 控制器设备中的硬件寄存器。 GpioClx 调用这些函数来处理 I/O 请求和管理中断。

GPIO 控制器驱动程序调用 GPIO_CLX_UnregisterClient 方法以取消其 GpioClx 注册。 通常,驱动程序从其 EvtDriverUnload 事件回调函数调用此方法。

设备对象初始化

若要初始化 GpioClx,GPIO 控制器驱动程序必须从其 EvtDriverDeviceAdd 回调函数调用两个 GpioClx 方法。 必须在调用 WdfDeviceCreate 方法(创建设备对象)之前调用第一个方法(GPIO_CLX_ProcessAddDevicePreDeviceCreate)。 第二种方法 GPIO_CLX_ProcessAddDevicePostDeviceCreate,必须在 WdfDeviceCreate 调用之后调用。

中断锁

大多数驱动程序实现的事件回调函数仅在 IRQL = PASSIVE_LEVEL 由 GpioClx 调用。 但是,以下列表中的回调函数在 PASSIVE_LEVEL 或 DIRQL 中调用,具体取决于 CLIENT_QueryControllerBasicInformation 回调函数提供给 GpioClx 的设备信息:

这些函数是从 gpioClx 中的 ISR) 中断服务例程调用的,该 (例程在 DIRQL 或 PASSIVE_LEVEL 中运行,具体取决于 GPIO 控制器的硬件寄存器是否进行内存映射。

CLIENT_QueryControllerBasicInformation 函数以CLIENT_CONTROLLER_BASIC_INFORMATION结构的形式提供设备信息。 如果 MemoryMappedController 标志位在此结构的 Flags 成员中设置,则 GpioClx ISR 将调用 DIRQL 上一个列表中的回调函数。 否则,ISR 会在 PASSIVE_LEVEL 调用所有驱动程序实现的回调函数。 有关此标志位的详细信息,请参阅 与中断相关的回调

GpioClx 自动同步对驱动程序实现的回调函数的调用,这些回调函数在 PASSIVE_LEVEL 运行,并且不会从 GpioClx ISR 调用。 因此,一次只能运行其中一个函数。 但是,GpioClx 不会将这些PASSIVE_LEVEL回调与 GpioClx 从其 ISR 所做的回调自动同步。 如果需要,GPIO 控制器驱动程序必须显式提供此类同步。

为了避免潜在的同步错误,GpioClx 实现了 GPIO 控制器驱动程序可以获取并释放的 中断锁 。 中断锁主要由驱动程序的 CLIENT_EnableInterruptCLIENT_DisableInterrupt 回调函数使用。 驱动程序调用 GPIO_CLX_AcquireInterruptLock 方法来获取锁,并调用 GPIO_CLX_ReleaseInterruptLock 方法来释放锁。 驱动程序从回调函数调用这些方法,该回调函数在 PASSIVE_LEVEL 调用,而不是从 GpioClx 中的 ISR 调用。 当驱动程序持有锁时,GpioClx ISR 无法运行。 驱动程序应仅短暂地持有锁,并且仅在必须与 ISR 同步的关键操作期间。

如果 GpioClx ISR 调用驱动程序实现的回调函数,则此函数不需要获取中断锁) (或释放,因为 ISR 已持有该锁 (并将) 释放它。 此函数调用 GPIO_CLX_AcquireInterruptLockGPIO_CLX_ReleaseInterruptLock 方法不起作用,但不会被视为错误。