从 Windows 8 开始,由 GPIO 控制器驱动程序控制的常规用途 I/O(GPIO)引脚作为系统管理的硬件资源可供其他驱动程序使用。 GPIO I/O 引脚(配置为数据输入或数据输出的引脚)可用作新的 Windows 资源类型 、GPIO I/O 资源。 此外,GPIO 中断引脚(配置为中断请求输入的引脚)可用作普通 Windows 中断资源。
GPIO I/O 资源表示外围设备的驱动程序可以读取或写入的一组或多台 GPIO 引脚。 Windows 隐藏了有关 GPIO I/O 引脚底层实现的详细信息,以便可以编写外围设备驱动程序来操作抽象的 GPIO I/O 资源。 无论实现资源的 GPIO 控制器硬件如何,使用这些抽象资源的外围设备驱动程序都可以跨平台工作。 GPIO I/O 资源由 WDFIOTARGET 句柄表示,该句柄将此资源与拥有基础 GPIO 引脚或引脚的特定 GPIO 控制器驱动程序相关联。
通常,可以针对输入或输出配置 GPIO 控制器上的 I/O 引脚,具体取决于控制器硬件和物理连接到引脚的设备的功能。 因此,驱动程序可以打开与此引脚的逻辑连接,以进行写入或读取操作,但不能同时进行两者。 但是,此约束是由硬件施加的,而不是由 GPIO 框架扩展(GpioClx)施加的。 如果硬件允许为输入和输出配置 I/O 引脚,GpioClx 允许驱动程序为读写作打开与引脚的逻辑连接。
对于配置为中断请求输入的 GPIO 引脚,GPIO 引脚而不是中断控制器或专用中断请求线路实现中断请求的事实被操作系统完全隐藏。 GPIO 中断作为抽象中断资源提供给外围设备驱动程序。 GPIO 驱动程序堆栈和硬件抽象层(HAL)支持这些资源的抽象。 因此,使用中断资源的外围设备驱动程序在很大程度上可以忽略有关这些资源的基础实现的详细信息。 有关详细信息,请参阅 GPIO 中断。
下图显示了将基于 GPIO 的资源分配给两个外围设备驱动程序的示例:
在上图中,为以下三个基于 GPIO 的资源分配了外围设备驱动程序 A:
- 两个数据输入引脚
- 数据输出引脚
- 中断输入引脚
以下两个基于 GPIO 的资源分配给外围设备驱动程序 B:
- 数据输入引脚
- 中断输入引脚
驱动程序 A 和 B 在其 EvtDevicePrepareHardware 回调函数中接收分配的资源。 如果驱动程序从资源中获得一组或多个 GPIO I/O 引脚,该驱动程序可以打开一个连接来访问这些引脚。 驱动程序获取 WDFIOTARGET 句柄来标识连接,并将 I/O 请求发送到此句柄以读取或写入这些引脚。
有关演示如何连接到一组 GPIO I/O 引脚并将 I/O 请求发送到此引脚的代码示例,请参阅以下主题:
在这两个主题中, IoRoutine 代码示例中的函数将打开一个 GPIO I/O 引脚资源,用于读取或写入,具体取决于 ReadOperation 参数值。 如果为读取打开资源(DesiredAccess = GENERIC_READ),则资源中的引脚配置为输入,发送到引脚资源的 IOCTL_GPIO_READ_PINS 请求将读取这些引脚上的输入值。 GpioClx 不允许对一组输入引脚发送 IOCTL_GPIO_WRITE_PINS 请求,并对此类请求以 STATUS_GPIO_OPERATION_DENIED 错误状态完成操作。 同样,如果为写入打开引脚资源(DesiredAccess = GENERIC_WRITE),则资源中的引脚配置为输出,并且发送到引脚资源的 IOCTL_GPIO_WRITE_PINS 请求将设置驱动这些引脚的输出闩锁中的值。 通常,向一组输出引脚发送 IOCTL_GPIO_READ_PINS 请求只是读取写入到输出闩锁的最后一个值。
若要使用中断资源来接收中断,客户端驱动程序必须将中断服务例程(ISR)连接到中断。 通常,驱动程序通过调用 WdfInterruptCreate 方法(或 IoConnectInterruptEx 例程)来建立此连接。 有关 KMDF 中断的详细信息,请参阅 “创建中断对象”。
与可以动态连接和断开硬件平台的即插即用设备不同,GPIO 控制器设备是永久附加的。 此外,GPIO 引脚与外围设备之间的连接假定为永久连接。 (或者,如果外围设备可以从槽中解拔,则该槽专用于此设备。因此,可用的 GPIO 资源是固定的,可以在平台固件中指定。 同样,假定使用 GPIO 资源的外围设备驱动程序使用专用的 GPIO 资源集。 因此,可以在平台固件中指定这些设备驱动程序的资源要求。
当平台固件将一组 GPIO 引脚指定为 GPIO I/O 资源时,固件指示是否可以为读取、写入或读取和写入打开此资源中的引脚。
如果外围设备驱动程序使用多个 GPIO I/O 资源,则此驱动程序必须知道 PnP 管理器枚举这些资源的顺序。 例如,如果驱动程序使用两个 GPIO I/O 引脚,但这些引脚必须独立访问,并且必须单独访问,则平台固件应将每个引脚描述为单独的 GPIO I/O 资源。 PnP 管理器按平台固件中描述的顺序枚举这些资源,这些资源必须与驱动程序预期的顺序匹配。
外围设备驱动程序打开与 GPIO I/O 资源的连接后, IOCTL_GPIO_READ_PINS 或 IOCTL_GPIO_WRITE_PINS 请求此驱动程序发送到此连接会访问资源中的所有引脚。 如果驱动程序有时只能访问这些引脚的子集,则必须将此子集作为单独的资源分配给驱动程序。
有关 IOCTL_GPIO_READ_PINS 请求的详细信息,包括将数据输入引脚映射到请求输出缓冲区中的位,请参阅 IOCTL_GPIO_READ_PINS。 有关 IOCTL_GPIO_WRITE_PINS 请求的详细信息,包括请求输入缓冲区中位到数据输出引脚的映射,请参阅 IOCTL_GPIO_WRITE_PINS。