Interrupt-Related Rückrufe
Optional kann der Treiber für einen GPIO-Controller (General Purpose E/O) Unterstützung für GPIO-Interrupts bereitstellen. Um GPIO-Interrupts zu unterstützen, implementiert ein GPIO-Controllertreiber eine Reihe von Rückruffunktionen, um diese Interrupts zu verwalten. Der Treiber enthält Zeiger auf diese Rückruffunktionen im Registrierungspaket, das der Treiber bereitstellt, wenn er sich als Client der GPIO-Frameworkerweiterung (GpioClx) registriert. Weitere Informationen zu diesem Registrierungspaket finden Sie unter GPIO_CLIENT_REGISTRATION_PACKET.
In der Regel verfügt ein GPIO-Controller, der ein integrierter Bestandteil eines SoC-Chips (System on a Chip) ist, über speicherseitig zugeordnete Hardwareregister, auf die der Prozessor im SoC-Chip direkt zugreifen kann. Ein separates GPIO-Controllergerät kann jedoch über einen seriellen Bus extern mit dem SoC-Chip verbunden werden, wie im folgenden Diagramm dargestellt.
In diesem Diagramm ist der externe GPIO-Controller mit einem I²C-Bus verbunden. Dieser Bus wird von einem I²C-Buscontroller gesteuert, der ein integrierter Bestandteil des SoC-Chips ist. Die Interruptanforderungszeile vom externen GPIO-Controller ist mit einem Pin am integrierten GPIO-Controller verbunden. Der GpioClx DDI kann in diesem Beispiel sowohl den integrierten GPIO-Controller als auch den externen GPIO-Controller aufnehmen.
Wenn ein GPIO-Controllergerät speicherseitig zugeordnet ist, kann der GPIO-Controllertreiber direkt auf die Hardwareregister des Controllers unter DIRQL zugreifen. Wenn der GPIO-Controller jedoch seriell verbunden ist, kann der GPIO-Controllertreiber nur bei IRQL = PASSIVE_LEVEL auf die Hardwareregistrierungen zugreifen, wie unter ISRs auf passiver Ebene erläutert.
Der Treiber für einen GPIO-Controller mit speicherzuordnungen Hardwareregistern sollte das MemoryMappedController-Flagbit in den Geräteinformationen festlegen, die der Treiber gpioClx bereitstellt. Andernfalls geht GpioClx davon aus, dass die Hardwareregister nicht arbeitsspeicherseitig zugeordnet sind und der Treiber nur unter IRQL = PASSIVE_LEVEL auf diese Register zugreifen kann. Weitere Informationen zu diesem Flagbit finden Sie unter CONTROLLER_ATTRIBUTE_FLAGS.
GpioClx implementiert eine Interruptdienstroutine (ISR) für Dienstunterbrechungsanforderungen vom GPIO-Controller. Dieser ISR ruft die folgenden Interrupt-bezogenen Rückruffunktionen auf:
CLIENT_ClearActiveInterruptsCLIENT_MaskInterruptsCLIENT_QueryActiveInterruptsCLIENT_QueryEnabledInterruptsCLIENT_UnmaskInterrupt Diese Funktionen werden entweder bei DIRQL oder PASSIVE_LEVEL aufgerufen, je nachdem, ob die ISR in GpioClx mit DIRQL oder PASSIVE_LEVEL ausgeführt wird. Der ISR ruft diese Funktionen bei DIRQL auf, wenn MemoryMappedController = 1, und bei PASSIVE_LEVEL, wenn MemoryMappedController = 0. In beiden Fällen serialisiert der ISR seine Rückrufe automatisch, sodass ein Aufruf einer dieser Funktionen nicht in der Mitte eines Aufrufs einer anderen dieser Funktionen erfolgt.
Die GPIO-Frameworkerweiterung ruft die folgenden Interrupt-bezogenen Rückruffunktionen nur bei PASSIVE_LEVEL auf, unabhängig davon, ob das Flag MemoryMappedController festgelegt ist:
CLIENT_DisableInterruptCLIENT_EnableInterrupt Wenn das MemoryMappedController-Flag nicht festgelegt ist, werden alle Interrupt-bezogenen Rückruffunktionen am PASSIVE_LEVEL aufgerufen. GpioClx serialisiert Aufrufe dieser Funktionen automatisch, sodass ein Aufruf einer dieser Funktionen nicht in der Mitte eines Aufrufs einer anderen dieser Funktionen erfolgt.
Wenn jedoch das Flag MemoryMappedController festgelegt ist, müssen die CLIENT_EnableInterrupt - und CLIENT_DisableInterrupt-Funktionen ihre Interruptaktivierung explizit synchronisieren und Vorgänge mit der GpioClx ISR deaktivieren, die die anderen vier Interrupt-bezogenen Rückruffunktionen bei DIRQL aufruft.
In der Regel führen die anderen CLIENT_Xxx-Rückruffunktionen (deren Namen nicht "Interrupt" enthalten) keine Interrupt-bezogene Verarbeitung aus und müssen daher nicht mit der GpioClx ISR synchronisiert werden. Wenn jedoch eine dieser Funktionen bei PASSIVE_LEVEL aufgerufen wird und Code enthält, der auf Interrupteinstellungen zugreift, auf die von interruptbezogenen Funktionen unter DIRQL zugegriffen wird, muss dieser Code mit dem ISR synchronisiert werden.
Um die Interruptsynchronisierung zu unterstützen, implementiert GpioClx eine Reihe von Interruptsperren. Eine Rückruffunktion, die bei PASSIVE_LEVEL ausgeführt wird, kann die GPIO_CLX_AcquireInterruptLock-Methode aufrufen, um eine Unterbrechungssperre abzurufen, und die GPIO_CLX_ReleaseInterruptLock-Methode aufrufen, um die Sperre zu lösen. Wenn die Funktion die Interruptsperre enthält, kann der GpioClx-ISR nicht ausgeführt werden, und dieser ISR kann keine Interrupt-bezogene Rückruffunktion aufrufen. Damit GPIO-Interrupts rechtzeitig behandelt werden können, sollte der Treiber die Interruptsperre nicht länger als erforderlich halten.
Weitere Informationen finden Sie unter Unterbrechen der Synchronisierung für GPIO-Controllertreiber.