GPIO 控制器驱动程序的中断同步

GPIO 控制器驱动程序可以调用 GPIO_CLX_AcquireInterruptLockGPIO_CLX_ReleaseInterruptLock 方法来获取和释放 GPIO 框架扩展 (GpioClx) 在内部实现的中断锁。 在 IRQL = PASSIVE_LEVEL 运行的驱动程序代码可以调用这些方法,以同步到 gpioClx 中 (ISR) 中断服务例程。 GpioClx 将单独的中断锁专用于 GPIO 控制器中的每个引脚组。

如果 GPIO 控制器的硬件寄存器是内存映射的,则 GpioClx 中的 ISR 在 DIRQL 上调用某些驱动程序实现的事件回调函数;GpioClx 在PASSIVE_LEVEL调用其余回调函数。 访问寄存器库的被动级回调函数可能需要使用中断锁来同步到在 DIRQL 上运行且访问相同寄存器的回调函数。

例如,被动级别 CLIENT_EnableInterruptCLIENT_DisableInterrupt 回调函数修改影响在 DIRQL 上运行的其他与中断相关的回调例程操作的硬件设置。 CLIENT_EnableInterruptCLIENT_DisableInterrupt函数通常使用库中断锁来同步其寄存器访问。

GpioClx 自动序列化 DIRQL 中发生的与中断相关的回调和 I/O 相关回调。 GpioClx 在 DIRQL 调用回调函数之前获取目标库的中断锁,并在函数返回后释放锁。 在 DIRQL 中调用的回调函数尝试通过调用 GPIO_CLX_AcquireInterruptLock 重新获取银行中断锁是 错误的

同样,GpioClx 会自动序列化PASSIVE_LEVEL发生的回调。 GpioClx 在内部实现每个库的等待锁。 GpioClx 在PASSIVE_LEVEL调用回调函数之前获取目标库的等待锁,并在函数返回时释放该锁。 对于内存映射 GPIO 控制器,GpioClx 代表驱动程序管理银行等待锁,但不允许驱动程序显式获取和释放锁。

但是,对于非内存映射 GPIO 控制器, GPIO_CLX_AcquireInterruptLockGPIO_CLX_ReleaseInterruptLock 获取并释放等待锁而不是中断锁。 GpioClx 为 GPIO 控制器中的每个引脚组实现单独的等待锁。 由于寄存器不是内存映射的,因此所有与中断相关的和 I/O 相关的回调函数在PASSIVE_LEVEL调用,以便它们可以使用 I/O 请求通过串行总线(如 I²C)访问寄存器。 GpioClx 在调用其中一个回调函数之前获取目标库的等待锁,并在函数返回后释放锁。

非内存映射控制器的回调函数尝试通过调用 GPIO_CLX_AcquireInterruptLock 重新获取银行等待锁是 错误的。 但是,回调函数外部的被动级别驱动程序代码可以调用 GPIO_CLX_XxxInterruptLock 方法以同步到回调函数。 由于 GpioClx 在 PASSIVE_LEVEL 调用所有与中断相关的和 I/O 相关的回调函数,因此库等待锁有效地取代了非内存映射控制器的库中断锁。

非内存映射控制器的另一个选项是让控制器驱动程序实现一组等待锁。 与 GpioClx 实现的等待锁相比,这些等待锁可能使回调例程能够对共享资源执行更精细的锁定和解锁。

在调用 CLIENT_QueryControllerBasicInformation 回调例程期间,GPIO 控制器驱动程序向 GpioClx 报告控制器寄存器是否为内存映射。 有关详细信息,请参阅 CLIENT_CONTROLLER_BASIC_INFORMATION 中的 MemoryMappedController 标志的说明。

有关中断锁和等待锁的详细信息,请参阅 使用框架锁

下表提供了有关在 DIRQL(而不是PASSIVE_LEVEL寄存器是否为内存映射)调用的回调函数的更多详细信息。 表后面的说明说明了被动级别回调函数何时应使用中断锁。

为了支持配置为中断输入的 GPIO 引脚,GPIO 控制器驱动程序实现了一组事件回调函数,以通过这些引脚管理中断请求。 在下表中,中间列指示如果 GPIO 控制器的硬件寄存器是内存映射的,则调用函数的 IRQL。 最右边的列指示在寄存器未进行内存映射且必须通过串行总线访问的情况下调用函数的 IRQL。

回调函数 如果内存映射 (MemoryMappedController = 1) ,则为 IRQL 如果串行访问的 IRQL (MemoryMappedController = 0)

CLIENT_EnableInterrupt

CLIENT_DisableInterrupt

PASSIVE_LEVEL

(请参阅注释 1.)

PASSIVE_LEVEL

(请参阅注释 2.)

CLIENT_ClearActiveInterrupts

CLIENT_MaskInterrupts

CLIENT_QueryActiveInterrupts

CLIENT_QueryEnabledInterrupts

CLIENT_ReconfigureInterrupt

CLIENT_UnmaskInterrupt

DIRQL

(请参阅注释 3.)

PASSIVE_LEVEL

(请参阅注释 4.)

CLIENT_PreProcessControllerInterrupt

DIRQL

(请参阅注释 5.)

DIRQL

(请参阅注释 6.)

备注

  1. GpioClx 在调用此回调函数之前不会获取库中断锁。 如有必要,回调函数可以获取库中断锁,以同步与在 DIRQL 上运行的回调函数共享的寄存器的访问。

  2. GpioClx 使用PASSIVE_LEVEL调用的其他与中断相关的和 I/O 相关的回调函数序列化对此回调函数的调用。 因此,回调函数不应尝试获取银行等待锁。

  3. GpioClx 在调用此回调函数之前获取库中断锁,并在函数返回后释放锁。 因此,回调函数不应尝试获取库中断锁。

  4. GpioClx 使用PASSIVE_LEVEL调用的其他与中断相关的和 I/O 相关的回调函数序列化对此回调函数的调用。 因此,回调函数不应尝试获取银行等待锁。

  5. GpioClx 在调用此回调函数之前获取库中断锁,并在函数返回后释放锁。 因此,回调函数不应尝试获取库中断锁。

  6. GpioClx 在调用此回调函数之前不会获取库中断锁。 GPIO 控制器驱动程序负责提供可能需要的任何同步。

为了支持配置为数据 I/O 引脚的 GPIO 引脚,GPIO 控制器驱动程序实现一组事件回调函数,以通过这些引脚管理 I/O 操作。 在下表中,中间列指示如果 GPIO 控制器的硬件寄存器是内存映射的,则调用函数的 IRQL。 最右边的列指示在寄存器未进行内存映射且必须通过串行总线访问的情况下调用函数的 IRQL。

回调函数 如果内存映射 (MemoryMappedController = 1) ,则为 IRQL 如果串行访问的 IRQL (MemoryMappedController = 0)

CLIENT_ConnectIoPins

CLIENT_DisconnectIoPins

PASSIVE_LEVEL

(请参阅注释 1.)

PASSIVE_LEVEL

(请参阅注释 2.)

CLIENT_ReadGpioPins

CLIENT_ReadGpioPinsUsingMask

CLIENT_WriteGpioPins

CLIENT_WriteGpioPinsUsingMask

DIRQL

(请参阅注释 3.)

PASSIVE_LEVEL

(请参阅注释 4.)

备注

  1. GpioClx 在调用此回调函数之前不会获取库中断锁。 如有必要,回调函数可以获取中断锁,以同步与在 DIRQL 上运行的回调函数共享的寄存器的访问。

  2. GpioClx 通过PASSIVE_LEVEL调用的其他与中断相关的和 I/O 相关的回调函数序列化对此回调函数的调用。 因此,回调函数不应尝试获取银行等待锁。

  3. GpioClx 在调用此回调函数之前获取库中断锁,并在函数返回后释放锁。 因此,回调函数不应尝试获取库中断锁。

  4. GpioClx 通过PASSIVE_LEVEL调用的其他与中断相关的和 I/O 相关的回调函数序列化对此回调函数的调用。 因此,回调函数不应尝试获取银行等待锁。

若要设置 GPIO 控制器以执行 I/O 和中断操作,GPIO 控制器驱动程序实现一组事件回调函数来初始化控制器。 在下表中,中间列指示如果 GPIO 控制器的硬件寄存器是内存映射的,则调用函数的 IRQL。 最右侧的列指示在寄存器未进行内存映射且必须通过串行总线访问时调用函数的 IRQL。

回调函数 如果内存映射的 IRQL (MemoryMappedController = 1) IRQL(如果以串行方式访问) (MemoryMappedController = 0)

CLIENT_PrepareController

CLIENT_ReleaseController

CLIENT_StartController

CLIENT_StopController

CLIENT_QueryControllerBasicInformation

CLIENT_QuerySetControllerInformation

PASSIVE_LEVEL

(请参阅注释 1.)

PASSIVE_LEVEL

(请参阅注释 2.)

备注

  1. 当 GpioClx 调用任何这些回调函数时,库中断锁不可用。 因此,这些回调函数不应尝试获取库中断锁。

  2. 调用这些回调函数时,GpioClx 库等待锁不可用。 因此,驱动程序不应尝试获取银行等待锁以同步到这些回调函数。

为了使 GPIO 控制器能够更改设备电源状态,GPIO 控制器驱动程序实现了一组事件回调函数,以便在这些更改期间保存和还原硬件设置。 在下表中,中间列指示如果 GPIO 控制器的硬件寄存器是内存映射的,则调用函数的 IRQL。 最右侧的列指示在寄存器未进行内存映射且必须通过串行总线访问时调用函数的 IRQL。

回调函数 如果内存映射的 IRQL (MemoryMappedController = 1) IRQL(如果以串行方式访问) (MemoryMappedController = 0)

CLIENT_RestoreBankHardwareContext

CLIENT_SaveBankHardwareContext

DIRQL 或 HIGH_LEVEL

(请参阅 Notes.)

不支持。

备注

  • 对于常规 F 状态转换:保存/还原回调函数是使用 GPioClx 在 DIRQL 中持有的库中断锁调用的。 因此,这两个回调函数都不应尝试获取库中断锁。
  • 对于关键的 F 状态转换:调用电源引擎插件 (PEP) 来保存和还原 GPIO 状态时,将调用保存/还原回调。 保存/还原回调函数在HIGH_LEVEL最后一个处理器处于空闲状态的上下文中调用,这发生在平台深度空闲转换序列的后期。 因此,这两个回调函数都不应尝试获取库中断锁。

有关 F 状态的详细信息,请参阅 组件级电源管理。 有关 PEP 的详细信息,请参阅 PoFxPowerControl

其他回调函数

若要使 GPIO 控制器支持特定于控制器的操作,GPIO 控制器驱动程序实现 CLIENT_ControllerSpecificFunction 事件回调函数。 在下表中,中间列指示如果 GPIO 控制器的硬件寄存器是内存映射的,则调用函数的 IRQL。 最右侧的列指示在寄存器未进行内存映射且必须通过串行总线访问时调用函数的 IRQL。

回调函数 如果内存映射的 IRQL (MemoryMappedController = 1) IRQL(如果以串行方式访问) (MemoryMappedController = 0)

CLIENT_ControllerSpecificFunction

PASSIVE_LEVEL

(请参阅注释 1.)

PASSIVE_LEVEL

(请参阅注释 2.)

备注

  1. 在调用此回调函数之前,GpioClx 不会获取库中断锁。 如有必要,回调函数可以获取库中断锁,以同步与在 DIRQL 运行的回调函数共享的寄存器的访问。

  2. GpioClx 通过PASSIVE_LEVEL调用的其他与中断相关的和 I/O 相关的回调函数序列化对此回调函数的调用。 因此,回调函数不应尝试获取银行等待锁。