Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
In Windows 10 und höher werden APIs mit direktem Zugriff vom Benutzermodus auf allgemeine Eingabe/Ausgabe (GPIO), Inter-Integrated Circuit (I2C), Serial Peripheral Interface (SPI) und Universal Asynchronous Receiver Transmitter (UART) bereitgestellt. Entwicklungsboards wie Raspberry Pi 2 machen eine Teilmenge dieser Verbindungen verfügbar, mit denen Sie ein Basisberechnungsmodul mit benutzerdefinierter Schaltung erweitern können, um eine bestimmte Anwendung zu adressieren. Diese Low-Level-Busse werden in der Regel mit anderen kritischen Onboard-Funktionen geteilt, wobei nur eine Teilmenge von GPIO-Pins und -Bussen an Headern verfügbar gemacht wird. Um die Systemstabilität zu erhalten, müssen Sie angeben, welche Pins und Busse für die Änderung durch Anwendungen im Benutzermodus sicher sind.
In diesem Dokument wird beschrieben, wie diese Konfiguration im Advanced Configuration and Power Interface (ACPI) angegeben wird, und es werden Werkzeuge bereitgestellt, um zu überprüfen, ob die Konfiguration korrekt spezifiziert wurde.
Von Bedeutung
Die Zielgruppe für dieses Dokument ist Unified Extensible Firmware Interface (UEFI) und ACPI-Entwickler. Einige Kenntnisse in ACPI, der Erstellung der ACPI-Quellsprache (ASL) und SpbCx/GpioClx werden vorausgesetzt.
Der Benutzermoduszugriff auf niedrigstufige Busse unter Windows wird durch die vorhandenen GpioClx
und SpbCx
Frameworks abgewickelt. Ein neuer Treiber namens RhProxy, verfügbar unter Windows IoT Core und Windows Enterprise, macht GpioClx
und SpbCx
Ressourcen im Benutzermodus zugänglich. Um die APIs zu aktivieren, muss ein Geräteknoten für rhproxy in Ihren ACPI-Tabellen mit den einzelnen GPIO- und SPB-Ressourcen deklariert werden, die für den Benutzermodus verfügbar gemacht werden sollen. Dieses Dokument durchläuft die Erstellung und Überprüfung der ASL.
ASL anhand von Beispielen
Sehen wir uns die rhproxy-Geräteknotendeklaration auf Raspberry Pi 2 an. Erstellen Sie zunächst die ACPI-Gerätedeklaration im Bereich \_SB.
Device(RHPX)
{
Name(_HID, "MSFT8000")
Name(_CID, "MSFT8000")
Name(_UID, 1)
}
- _HID – Hardware-ID. Legen Sie diese auf eine herstellerspezifische Hardware-ID fest.
- _CID – Kompatible ID. Muss "MSFT8000" sein.
- _UID – Eindeutige ID. Auf 1 festgelegt.
Als Nächstes deklarieren wir die einzelnen GPIO- und SPB-Ressourcen, die für den Benutzermodus verfügbar gemacht werden sollen. Die Reihenfolge, in der Ressourcen deklariert werden, ist wichtig, da Ressourcenindizes zum Zuordnen von Eigenschaften zu Ressourcen verwendet werden. Wenn mehrere I2C- oder SPI-Busse verfügbar gemacht werden, gilt der erste deklarierte Bus als "Standardbus" für diesen Typ und wird die Instanz sein, die von den GetDefaultAsync()
Methoden von Windows.Devices.I2c.I2cController und Windows.Devices.Spi.SpiControllerzurückgegeben wird.
SPI
Raspberry Pi verfügt über zwei offengelegte SPI-Busse. SPI0 verfügt über zwei Hardware-Chip-Auswahllinien und SPI1 verfügt über eine Hardware-Chip-Auswahllinie. Für jede Chipauswahllinie für jeden Bus ist eine SPISerialBus()-Ressourcendeklaration erforderlich. Die folgenden beiden SPISerialBus-Ressourcendeklarationen beziehen sich auf die beiden Chip-Auswahlleitungen von SPI0. Das DeviceSelection-Feld enthält einen eindeutigen Wert, den der Treiber als Hardwarechip-Auswahlzeilenbezeichner interpretiert. Der genaue Wert, den Sie im Feld DeviceSelection einfügen, hängt davon ab, wie Der Treiber dieses Feld der ACPI-Verbindungsbeschreibung interpretiert.
Hinweis
Dieser Artikel enthält Verweise auf den Begriff Sklaven – einen Begriff, der von Microsoft nicht unterstützt wird und in neuen Produkten und Dokumentationen nicht mehr verwendet wurde. Wenn der Begriff aus der Software entfernt wird, entfernen wir ihn aus diesem Artikel.
// Index 0
SPISerialBus( // SCKL - GPIO 11 - Pin 23
// MOSI - GPIO 10 - Pin 19
// MISO - GPIO 9 - Pin 21
// CE0 - GPIO 8 - Pin 24
0, // Device selection (CE0)
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
0, // databit len: placeholder
ControllerInitiated, // slave mode
0, // connection speed: placeholder
ClockPolarityLow, // clock polarity: placeholder
ClockPhaseFirst, // clock phase: placeholder
"\\_SB.SPI0", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
// Resource usage
) // Vendor Data
// Index 1
SPISerialBus( // SCKL - GPIO 11 - Pin 23
// MOSI - GPIO 10 - Pin 19
// MISO - GPIO 9 - Pin 21
// CE1 - GPIO 7 - Pin 26
1, // Device selection (CE1)
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
0, // databit len: placeholder
ControllerInitiated, // slave mode
0, // connection speed: placeholder
ClockPolarityLow, // clock polarity: placeholder
ClockPhaseFirst, // clock phase: placeholder
"\\_SB.SPI0", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
// Resource usage
) // Vendor Data
Wie weiß Software, dass diese beiden Ressourcen mit demselben Bus verknüpft werden sollen? Die Zuordnung zwischen dem Bus-Anzeigename und dem Ressourcenindex wird in der DSD angegeben.
Package(2) { "bus-SPI-SPI0", Package() { 0, 1 }},
Dadurch wird ein Bus namens "SPI0" mit zwei Chipauswahllinien erstellt – Ressourcenindizes 0 und 1. Zum Deklarieren der Funktionen des SPI-Bus sind mehrere weitere Eigenschaften erforderlich.
Package(2) { "SPI0-MinClockInHz", 7629 },
Package(2) { "SPI0-MaxClockInHz", 125000000 },
Die MinClockInHz- und MaxClockInHz- Eigenschaften geben die mindesten und maximalen Taktgeschwindigkeiten an, die vom Controller unterstützt werden. Die API verhindert, dass Benutzer Werte außerhalb dieses Bereichs angeben. Die Taktgeschwindigkeit wird an Ihren SPB-Treiber im _SPE Feld der Verbindungsbeschreibung übergeben (ACPI-Abschnitt 6.4.3.8.2.2).
Package(2) { "SPI0-SupportedDataBitLengths", Package() { 8 }},
Die SupportedDataBitLengths--Eigenschaft listet die vom Controller unterstützten Datenbitlängen auf. Mehrere Werte können in einer durch Trennzeichen getrennten Liste angegeben werden. Die API verhindert, dass Benutzer Werte außerhalb dieser Liste angeben. Die Datenbitlänge wird an Ihren SPB-Treiber im feld _LEN des Verbindungsdeskriptors (ACPI Abschnitt 6.4.3.8.2.2) übergeben.
Sie können sich diese Ressourcendeklarationen als "Vorlagen" vorstellen. Einige Felder werden beim Systemstart festgelegt, während andere dynamisch während der Laufzeit angegeben werden. Die folgenden Felder des SPISerialBus-Deskriptors sind fest:
- Geräteauswahl
- Geräteauswahlpolarität
- WireMode
- SlaveMode
- Ressourcenquelle
Die folgenden Felder sind Platzhalter für Werte, die vom Benutzer zur Laufzeit angegeben werden:
- Datenbitlänge
- Verbindungsgeschwindigkeit
- Clock-Pegel
- ClockPhase
Da SPI1 nur eine einzelne Chipauswahllinie enthält, wird eine einzelne SPISerialBus()
Ressource deklariert:
// Index 2
SPISerialBus( // SCKL - GPIO 21 - Pin 40
// MOSI - GPIO 20 - Pin 38
// MISO - GPIO 19 - Pin 35
// CE1 - GPIO 17 - Pin 11
1, // Device selection (CE1)
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
0, // databit len: placeholder
ControllerInitiated, // slave mode
0, // connection speed: placeholder
ClockPolarityLow, // clock polarity: placeholder
ClockPhaseFirst, // clock phase: placeholder
"\\_SB.SPI1", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
// Resource usage
) // Vendor Data
Die Deklaration des zugehörigen Anzeigenamens, die erforderlich ist, wird im DSD angegeben und bezieht sich auf den Index dieser Ressourcendeklaration.
Package(2) { "bus-SPI-SPI1", Package() { 2 }},
Dadurch wird ein Bus mit dem Namen "SPI1" erstellt und dem Ressourcenindex 2 zugeordnet.
SPI-Treiberanforderungen
- Muss
SpbCx
verwenden oder SpbCx-kompatibel sein - Muss die MITT SPI Tests bestanden haben
- Muss 4MHz Taktfrequenz unterstützen
- Muss 8-Bit-Datenlänge unterstützen
- Muss alle SPI-Modi unterstützen: 0, 1, 2, 3
I2C
Als Nächstes deklarieren wir die I2C-Ressourcen. Der Raspberry Pi stellt einen einzelnen I2C-Bus auf den Pins 3 und 5 zur Verfügung.
// Index 3
I2CSerialBus( // Pin 3 (GPIO2, SDA1), 5 (GPIO3, SCL1)
0xFFFF, // SlaveAddress: placeholder
, // SlaveMode: default to ControllerInitiated
0, // ConnectionSpeed: placeholder
, // Addressing Mode: placeholder
"\\_SB.I2C1", // ResourceSource: I2C bus controller name
,
,
) // VendorData
Die zugehörige Anzeigenamendeklaration , die erforderlich ist, wird in der DSD angegeben:
Package(2) { "bus-I2C-I2C1", Package() { 3 }},
Dadurch wird ein I2C-Bus mit dem Anzeigenamen "I2C1" deklariert, der den Ressourcenindex 3 angibt. Dieser Index bezieht sich auf die oben deklarierte I2CSerialBus()-Ressource.
Die folgenden Felder des I2CSerialBus()-Deskriptors sind festgelegt:
- SlaveMode
- Ressourcenquelle
Die folgenden Felder sind Platzhalter für Werte, die vom Benutzer zur Laufzeit angegeben werden.
- SlaveAddress
- Verbindungsgeschwindigkeit
- Adressierungsmodus
I2C-Treiberanforderungen
- Muss SpbCx verwenden oder SpbCx-kompatibel sein
- Muss die MITT I2C Tests bestanden haben
- Muss die 7-Bit-Adressierung unterstützen
- Muss 100kHz Taktfrequenz unterstützen
- Muss 400kHz Taktfrequenz unterstützen
GPIO
Als Nächstes deklarieren wir alle GPIO-Pins, die für den Benutzermodus verfügbar gemacht werden. Wir bieten die folgende Anleitung bei der Entscheidung, welche Pins freigelegt werden sollen:
- Deklarieren Sie alle Pins auf freiliegenden Headern.
- Deklarieren Sie Pins, die mit nützlichen integrierten Funktionen wie Tasten und LEDs verbunden sind.
- Deklarieren Sie keine Pins, die für Systemfunktionen reserviert sind oder mit nichts verbunden sind.
Der folgende Block von ASL deklariert zwei Pins – GPIO4 und GPIO5. Die anderen Pins werden der Kürze halber hier nicht angezeigt. Anhang C enthält ein PowerShell-Beispielskript, das zum Generieren der GPIO-Ressourcen verwendet werden kann.
// Index 4 – GPIO 4
GpioIO(Shared, PullUp, , , , “\\_SB.GPI0”, , , , ) { 4 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, “\\_SB.GPI0”,) { 4 }
// Index 6 – GPIO 5
GpioIO(Shared, PullUp, , , , “\\_SB.GPI0”, , , , ) { 5 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, “\\_SB.GPI0”,) { 5 }
Die folgenden Anforderungen müssen beim Deklarieren von GPIO-Pins beachtet werden:
- Es werden nur speicherzugeordnete GPIO-Controller unterstützt. GPIO-Controller, die über die I2C/SPI-Schnittstelle verbunden sind, werden nicht unterstützt. Der Controllertreiber ist ein Speicherzuordnungscontroller, wenn die MemoryMappedController-Flagge in der CLIENT_CONTROLLER_BASIC_INFORMATION-Struktur als Reaktion auf die CLIENT_QueryControllerBasicInformation-Rückruffunktion festgelegt wird.
- Jeder Pin erfordert sowohl eine GpioIO- als auch eine GpioInt-Ressource. Die GpioInt-Ressource muss sofort der GpioIO-Ressource folgen und muss auf dieselbe Pinnummer verweisen.
- GPIO-Ressourcen müssen in der Reihenfolge der aufsteigenden Pinnummern sortiert werden.
- Jede GpioIO- und GpioInt-Ressource muss genau eine Pinnummer in der Pinliste enthalten.
- Das ShareType-Feld beider Deskriptoren muss auf 'Gemeinsamer Zugriff' gesetzt sein.
- Das EdgeLevel-Feld des GpioInt-Deskriptors muss Edge sein.
- Das ActiveLevel-Feld des GpioInt-Deskriptors muss auf ActiveBoth gesetzt sein.
- Das PinConfig-Feld
- Muss in den GpioIO- und GpioInt-Deskriptoren identisch sein
- Muss einer von PullUp, PullDown oder PullNone sein. Es kann nicht PullDefault sein.
- Die Pull-Konfiguration muss mit dem Einschaltzustand des Pins übereinstimmen. Beim Setzen des Pins im angegebenen Pullmodus aus dem Einschaltzustand darf der Zustand des Pins nicht geändert werden. Wenn das Datenblatt beispielsweise angibt, dass der Pin mit einem Pullup aktiviert wird, geben Sie als PinConfig PullUp an.
Der Firmware-, UEFI- und Treiberinitialisierungscode sollte den Zustand eines Pins während des Starts nicht vom Einschaltzustand ändern. Nur der Benutzer weiß, was mit einem Pin verbunden ist und damit welche Zustandsübergänge sicher sind. Der Einschaltzustand jeder Pin muss dokumentiert sein, damit Benutzer Hardware entwerfen können, die ordnungsgemäß mit einem Pin interagieren kann. Ein Pin darf während des Starts nicht unerwartet den Zustand ändern.
Unterstützte Laufwerkmodi
Wenn Ihr GPIO-Controller integrierte Pullup- und Pulldown-Widerstände zusätzlich zu hochohmigem Eingang und CMOS-Ausgabe unterstützt, müssen Sie dies mit der optionalen SupportedDriveModes-Eigenschaft angeben.
Package (2) { “GPIO-SupportedDriveModes”, 0xf },
Die Eigenschaft für unterstützte Antriebsmodi gibt an, welche Fahrmodi vom GPIO-Controller unterstützt werden. Im obigen Beispiel werden alle der folgenden Fahrmodi unterstützt. Die Eigenschaft ist eine Bitmaske der folgenden Werte:
Flag-Wert | Fahrmodus | BESCHREIBUNG |
---|---|---|
0x1 | Eingang mit hoher Impedanz | Der Pin unterstützt die Eingabe mit hoher Impedanz, die dem Wert "PullNone" in ACPI entspricht. |
0x2 | InputPullUp | Der Pin unterstützt einen integrierten Pull-Up-Widerstand, der dem Wert "PullUp" in ACPI entspricht. |
0x4 | Eingabe-Pull-Down-Menü | Der Pin unterstützt einen integrierten Pulldown-Widerstand, der dem Wert "PullDown" in ACPI entspricht. |
0x8 | OutputCmos | Der Pin unterstützt das Generieren von starken Hochs und starken Tiefen (im Gegensatz zu offenem Abfluss). |
InputHighImpedance und OutputCmos werden von fast allen GPIO-Controllern unterstützt. Wenn die SupportedDriveModes-Eigenschaft nicht angegeben ist, ist dies der Standardwert.
Wenn ein GPIO-Signal einen Pegelwandler durchläuft, bevor es einen freiliegenden Header erreicht, deklarieren Sie die vom SOC unterstützten Treiber-Modi, auch wenn der Treiber-Modus im externen Header nicht feststellbar wäre. Wenn z. B. ein Pin einen bidirektionalen Pegelwandler durchläuft, der den Pin als Open-Drain mit Widerstand hochgezogen erscheinen lässt, werden Sie niemals einen hochohmigen Zustand auf dem exponierten Header beobachten, selbst wenn der Pin als hochohmiger Eingang konfiguriert ist. Sie sollten dennoch deklarieren, dass der Pin eine Eingabe mit hoher Impedanz unterstützt.
Pin-Nummerierung
Windows unterstützt zwei Pinnummerierungsschemas:
- Sequenzielle Pinnummerierung – Benutzer sehen Zahlen wie 0, 1, 2... bis zur Anzahl der sichtbaren Pins. 0 ist die erste gpioIo-Ressource, die in ASL deklariert ist, 1 ist die zweite gpioIo-Ressource, die in ASL deklariert ist usw.
- Native Pinnummerierung – Benutzer sehen die in GpioIo-Deskriptoren angegebenen Pinnummern, z. B. 4, 5, 12, 13, ...
Package (2) { “GPIO-UseDescriptorPinNumbers”, 1 },
Die Eigenschaft UseDescriptorPinNumbers weist Windows an, die native Pinnummerierung anstelle der sequenziellen Pinnummerierung zu verwenden. Wenn die UseDescriptorPinNumbers-Eigenschaft nicht angegeben ist oder der Wert null ist, verwendet Windows standardmäßig sequenzielle Pinnummerierung.
Wenn systemeigene Pinnummerierung verwendet wird, müssen Sie auch die eigenschaft PinCount angeben.
Package (2) { “GPIO-PinCount”, 54 },
Die PinCount--Eigenschaft sollte mit dem Wert übereinstimmen, der über die TotalPins--Eigenschaft im CLIENT_QueryControllerBasicInformation Callback des GpioClx
Treibers zurückgegeben wird.
Wählen Sie das Nummerierungsschema aus, das mit vorhandenen veröffentlichten Dokumentationen für Ihr Board am besten kompatibel ist. Beispielsweise verwendet der Raspberry Pi die native Pinnummerierung, da viele vorhandene Pinout-Diagramme die BCM2835-Pinnummern verwenden. MinnowBoardMax verwendet sequenzielle Pinnummerierung, da nur wenige Pinoutdiagramme vorhanden sind. Die sequenzielle Pinnummerierung vereinfacht die Entwicklererfahrung, da nur 10 Pins aus mehr als 200 Pins freigelegt sind. Die Entscheidung, eine sequenzielle oder systemeigene Pinnummerierung zu verwenden, sollte darauf abzielen, die Verwirrung der Entwickler zu verringern.
GPIO-Treiberanforderungen
- Muss
GpioClx
verwenden - Muss auf den SOC-Speicher gemappt sein
- Muss die emulierte ActiveBoth-Unterbrechungsbehandlung verwenden
UART
Wenn Ihr UART-Treiber SerCx
oder SerCx2
verwendet, können Sie rhproxy verwenden, um den Treiber für den Benutzermodus verfügbar zu machen. UART-Treiber, die eine Geräteschnittstelle vom Typ GUID_DEVINTERFACE_COMPORT
erstellen, müssen rhproxy nicht verwenden. Der eingebaute Serial.sys
-Treiber ist einer dieser Fälle.
Um eine UART im SerCx
-Stil für den Benutzermodus verfügbar zu machen, deklarieren Sie eine Ressource UARTSerialBus
wie folgt.
// Index 2
UARTSerialBus( // Pin 17, 19 of JP1, for SIO_UART2
115200, // InitialBaudRate: in bits ber second
, // BitsPerByte: default to 8 bits
, // StopBits: Defaults to one bit
0xfc, // LinesInUse: 8 1-bit flags to declare line enabled
, // IsBigEndian: default to LittleEndian
, // Parity: Defaults to no parity
, // FlowControl: Defaults to no flow control
32, // ReceiveBufferSize
32, // TransmitBufferSize
"\\_SB.URT2", // ResourceSource: UART bus controller name
,
,
,
)
Nur das ResourceSource-Feld ist festgelegt, während alle anderen Felder Platzhalter für Werte sind, die zur Laufzeit vom Benutzer angegeben werden.
Die zugehörige Deklaration des Anzeigenamens lautet:
Package(2) { "bus-UART-UART2", Package() { 2 }},
Dadurch wird dem Controller die benutzerfreundliche Bezeichnung "UART2" zugewiesen, welche der Bezeichner ist, den Benutzer verwenden, um im Benutzermodus auf den Bus zuzugreifen.
Laufzeit-Pin-Muxing
Pin-Muxing ist die Möglichkeit, denselben physischen Pin für verschiedene Funktionen zu verwenden. Mehrere verschiedene On-Chip-Peripheriegeräte, z. B. ein I2C-Controller, SPI-Controller und GPIO-Controller, können an den gleichen physischen Pin auf einem SOC weitergeleitet werden. Der Mux-Block steuert, welche Funktion jederzeit auf dem Pin aktiv ist. Die Firmware ist traditionell dafür verantwortlich, Funktionszuweisungen beim Start festzulegen, und diese Zuordnung bleibt während des Boot-Vorgangs unverändert. Laufzeit-Pin-Muxing bietet die Möglichkeit, Pin-Funktionszuweisungen zur Laufzeit neu zu konfigurieren. Wenn Benutzer die Funktion eines Pins zur Laufzeit auswählen können, wird die Entwicklung beschleunigt, da Benutzer die Pins eines Boards schnell neu konfigurieren können, und die Hardware kann eine breitere Palette von Anwendungen unterstützen als eine statische Konfiguration.
Benutzer nutzen Muxing-Unterstützung für GPIO, I2C, SPI und UART, ohne zusätzlichen Code zu schreiben. Wenn ein Benutzer eine GPIO oder einen Bus mit OpenPin() oder FromIdAsync()öffnet, werden die zugrunde liegenden physischen Pins automatisch an die angeforderte Funktion muxiert. Wenn die Pins bereits von einer anderen Funktion verwendet werden, schlägt der Aufruf von OpenPin() oder FromIdAsync() fehl. Wenn der Benutzer das Gerät abgeschlossen hat, indem er das GpioPin--, I2cDevice--, SpiDevice-- oder SerialDevice--Objekt freigibt, werden die Pins freigegeben, sodass sie zur späteren Nutzung für eine andere Funktion geöffnet werden können.
Windows enthält integrierte Unterstützung für Pin-Muxing in den Frameworks GpioClx-, SpbCx-und SerCx-. Diese Frameworks arbeiten zusammen, um automatisch einen Pin zur richtigen Funktion zu wechseln, wenn auf einen GPIO-Pin oder -Bus zugegriffen wird. Der Zugriff auf die Pins wird arbitriert, um Konflikte zwischen mehreren Clients zu verhindern. Zusätzlich zu dieser integrierten Unterstützung sind die Schnittstellen und Protokolle für Pin-Muxing von allgemeinem Zweck und erweiterbar, um zusätzliche Geräte und Szenarien zu unterstützen.
In diesem Dokument werden zunächst die zugrunde liegenden Schnittstellen und Protokolle beschrieben, die an Pin-Muxing beteiligt sind, und anschließend wird beschrieben, wie Sie Unterstützung für Pin-Muxing zu GpioClx-, SpbCx- und SerCx-Controllertreibern hinzufügen.
Pin-Muxing-Architektur
In diesem Abschnitt werden die zugrunde liegenden Schnittstellen und Protokolle beschrieben, die an Pin-Muxing beteiligt sind. Kenntnisse der zugrunde liegenden Protokolle sind nicht unbedingt erforderlich, um Pin-Muxing mit GpioClx/SpbCx/SerCx-Treibern zu unterstützen. Ausführliche Informationen zur Unterstützung von Pin-Muxing mit GpioCls/SpbCx/SerCx-Treibern finden Sie unter Implementieren der Pin-Muxing-Unterstützung in GpioClx-Clienttreibern und Verwenden von Muxing-Unterstützung in SpbCx- und SerCx-Controllertreibern.
Pin-Muxing wird durch die Zusammenarbeit mehrerer Komponenten erreicht.
- Pin-Muxing-Server – hierbei handelt es sich um Treiber, die den Pin-Muxing-Kontrollblock steuern. Pin-Muxing-Server empfangen Pin-Muxing-Anforderungen von Clients über Anfragen zur Reservierung von Muxing-Ressourcen (über IRP_MJ_CREATE) und zum Wechsel der Funktion eines Pins (über *IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS-Anfragen). Der Pin-Muxing-Server ist in der Regel der GPIO-Treiber, da der Muxing-Block manchmal Teil des GPIO-Blocks ist. Selbst wenn der Muxing-Block ein separates Peripheriegerät ist, ist der GPIO-Treiber ein logischer Ort, um Muxing-Funktionen zu platzieren.
- Pin-Muxing-Klienten – das sind Treiber, die Pin-Muxing nutzen. Pin-Muxing-Clients erhalten Pin-Muxing-Ressourcen von ACPI-Firmware. Pin-Muxing-Ressourcen sind eine Art Verbindungsressource und werden vom Ressourcenhub verwaltet. Pin-Muxing-Klienten reservieren Pin-Muxing-Ressourcen, indem sie ein Handle für die Ressource öffnen. Um eine Hardwareänderung durchzuführen, müssen Clients die Konfiguration verbindlich machen, indem sie eine IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS Anfrage senden. Clients geben Pin-Muxing-Ressourcen frei, indem sie den Handle schließen, wobei die Muxing-Konfiguration in den Standardzustand wiederhergestellt wird.
- ACPI-Firmware – gibt die Muxing-Konfiguration mit Ressourcen von
MsftFunctionConfig()
an. MsftFunctionConfig-Ressourcen geben an, welche Pins, in welcher Muxing-Konfiguration, von einem Client benötigt werden. MsftFunctionConfig-Ressourcen enthalten Funktionsnummer, Pullkonfiguration und Liste der Pinnummern. MsftFunctionConfig-Ressourcen werden als Hardwareressourcen an Pin-Muxing-Clients bereitgestellt. Treiber empfangen sie in ihrem PrepareHardware-Rückruf, ähnlich wie bei GPIO- und SPB-Verbindungsressourcen. Clients erhalten eine Ressourcenhub-ID, die zum Öffnen eines Handles für die Ressource verwendet werden kann.
Sie müssen die Befehlszeilenoption
/MsftInternal
anasl.exe
übergeben, um ASL-Dateien zu kompilieren, dieMsftFunctionConfig()
Deskriptoren enthalten, da diese Deskriptoren derzeit vom ACPI-Arbeitsausschuss überprüft werden. Beispiel:asl.exe /MsftInternal dsdt.asl
Die Sequenz der Vorgänge, die am Pin-Muxing beteiligt sind, wird unten gezeigt.
- Der Client empfängt die MsftFunctionConfig-Ressourcen von der ACPI-Firmware in seiner EvtDevicePrepareHardware() Callback-Funktion.
- Der Client verwendet die Hilfsfunktion des Ressourcenhubs
RESOURCE_HUB_CREATE_PATH_FROM_ID()
, um einen Pfad aus der Ressourcen-ID zu erstellen, und öffnet dann ein Handle zum Pfad (mithilfe ZwCreateFile(), IoGetDeviceObjectPointer()oder WdfIoTargetOpen()). - Der Server extrahiert die Ressourcenhub-ID aus dem Dateipfad mithilfe von Ressourcenhub-Hilfsfunktionen
RESOURCE_HUB_ID_FROM_FILE_NAME()
und fragt dann den Ressourcenhub ab, um den Ressourcendeskriptor abzurufen. - Der Server führt die Freigabevermittlung für jeden Pin im Deskriptor aus und schließt die IRP_MJ_CREATE Anforderung ab.
- Der Client gibt eine IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS Anforderung für das empfangene Handle aus.
- Als Reaktion auf IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINSführt der Server den Hardware-Muxing-Vorgang durch, indem die angegebene Funktion auf jedem Pin aktiv wird.
- Der Client fährt mit Vorgängen fort, die von der angeforderten Pin-Muxing-Konfiguration abhängen.
- Wenn der Client die Pins nicht mehr multiplexiert, wird das Handle geschlossen.
- Als Reaktion darauf, dass das Handle geschlossen wird, setzt der Server die Pins wieder in ihren Anfangszustand zurück.
Protokollbeschreibung für Pin-Muxing-Clients
In diesem Abschnitt wird beschrieben, wie ein Client die Pin-Muxing-Funktionalität nutzt. Dies gilt nicht für SerCx
- und SpbCx
Controllertreiber, da die Frameworks dieses Protokoll im Auftrag von Controllertreibern implementieren.
Analysieren von Ressourcen
Ein WDF-Treiber empfängt MsftFunctionConfig()
Ressourcen in seiner EvtDevicePrepareHardware() Routine. MsftFunctionConfig-Ressourcen können durch die folgenden Felder identifiziert werden:
CM_PARTIAL_RESOURCE_DESCRIPTOR::Type = CmResourceTypeConnection
CM_PARTIAL_RESOURCE_DESCRIPTOR::u.Connection.Class = CM_RESOURCE_CONNECTION_CLASS_FUNCTION_CONFIG
CM_PARTIAL_RESOURCE_DESCRIPTOR::u.Connection.Type = CM_RESOURCE_CONNECTION_TYPE_FUNCTION_CONFIG
Eine EvtDevicePrepareHardware()
Routine kann MsftFunctionConfig-Ressourcen wie folgt extrahieren:
EVT_WDF_DEVICE_PREPARE_HARDWARE evtDevicePrepareHardware;
_Use_decl_annotations_
NTSTATUS
evtDevicePrepareHardware (
WDFDEVICE WdfDevice,
WDFCMRESLIST ResourcesTranslated
)
{
PAGED_CODE();
LARGE_INTEGER connectionId;
ULONG functionConfigCount = 0;
const ULONG resourceCount = WdfCmResourceListGetCount(ResourcesTranslated);
for (ULONG index = 0; index < resourceCount; ++index) {
const CM_PARTIAL_RESOURCE_DESCRIPTOR* resDescPtr =
WdfCmResourceListGetDescriptor(ResourcesTranslated, index);
switch (resDescPtr->Type) {
case CmResourceTypeConnection:
switch (resDescPtr->u.Connection.Class) {
case CM_RESOURCE_CONNECTION_CLASS_FUNCTION_CONFIG:
switch (resDescPtr->u.Connection.Type) {
case CM_RESOURCE_CONNECTION_TYPE_FUNCTION_CONFIG:
switch (functionConfigCount) {
case 0:
// save the connection ID
connectionId.LowPart = resDescPtr->u.Connection.IdLowPart;
connectionId.HighPart = resDescPtr->u.Connection.IdHighPart;
break;
} // switch (functionConfigCount)
++functionConfigCount;
break; // CM_RESOURCE_CONNECTION_TYPE_FUNCTION_CONFIG
} // switch (resDescPtr->u.Connection.Type)
break; // CM_RESOURCE_CONNECTION_CLASS_FUNCTION_CONFIG
} // switch (resDescPtr->u.Connection.Class)
break;
} // switch
} // for (resource list)
if (functionConfigCount < 1) {
return STATUS_INVALID_DEVICE_CONFIGURATION;
}
// TODO: save connectionId in the device context for later use
return STATUS_SUCCESS;
}
Reservieren und Zuweisen von Ressourcen
Wenn ein Client Pins multiplexen möchte, reserviert und verbindet er die MsftFunctionConfig-Ressource. Das folgende Beispiel zeigt, wie ein Client MsftFunctionConfig-Ressourcen reservieren und übernehmen kann.
_IRQL_requires_max_(PASSIVE_LEVEL)
NTSTATUS AcquireFunctionConfigResource (
WDFDEVICE WdfDevice,
LARGE_INTEGER ConnectionId,
_Out_ WDFIOTARGET* ResourceHandlePtr
)
{
PAGED_CODE();
//
// Form the resource path from the connection ID
//
DECLARE_UNICODE_STRING_SIZE(resourcePath, RESOURCE_HUB_PATH_CHARS);
NTSTATUS status = RESOURCE_HUB_CREATE_PATH_FROM_ID(
&resourcePath,
ConnectionId.LowPart,
ConnectionId.HighPart);
if (!NT_SUCCESS(status)) {
return status;
}
//
// Create a WDFIOTARGET
//
WDFIOTARGET resourceHandle;
status = WdfIoTargetCreate(WdfDevice, WDF_NO_ATTRIBUTES, &resourceHandle);
if (!NT_SUCCESS(status)) {
return status;
}
//
// Reserve the resource by opening a WDFIOTARGET to the resource
//
WDF_IO_TARGET_OPEN_PARAMS openParams;
WDF_IO_TARGET_OPEN_PARAMS_INIT_OPEN_BY_NAME(
&openParams,
&resourcePath,
FILE_GENERIC_READ | FILE_GENERIC_WRITE);
status = WdfIoTargetOpen(resourceHandle, &openParams);
if (!NT_SUCCESS(status)) {
return status;
}
//
// Commit the resource
//
status = WdfIoTargetSendIoctlSynchronously(
resourceHandle,
WDF_NO_HANDLE, // WdfRequest
IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS,
nullptr, // InputBuffer
nullptr, // OutputBuffer
nullptr, // RequestOptions
nullptr); // BytesReturned
if (!NT_SUCCESS(status)) {
WdfIoTargetClose(resourceHandle);
return status;
}
//
// Pins were successfully muxed, return the handle to the caller
//
*ResourceHandlePtr = resourceHandle;
return STATUS_SUCCESS;
}
Der Treiber sollte das WDFIOTARGET in einem seiner Kontextbereiche speichern, damit es später geschlossen werden kann. Wenn der Treiber bereit ist, die Konfiguration für das Multiplexing freizugeben, sollte er den Ressourcen-Handle schließen, indem er WdfObjectDelete()aufruft, oder WdfIoTargetClose(), wenn das WDFIOTARGET wiederverwendet werden soll.
WdfObjectDelete(resourceHandle);
Wenn der Client sein Ressourcen-Handle schließt, werden die Pins wieder in ihren ursprünglichen Zustand zurückgesteuert und können jetzt von einem anderen Klienten übernommen werden.
Protokollbeschreibung für Pin-Muxing-Server
In diesem Abschnitt wird beschrieben, wie ein Pin-Muxing-Server seine Funktionalität für Clients verfügbar macht. Dies gilt nicht für GpioClx
Miniporttreiber, da das Framework dieses Protokoll im Auftrag von Clienttreibern implementiert. Informationen zur Unterstützung von Pin-Muxing in GpioClx
-Clienttreibern finden Sie unter Implementierung der Muxing-Unterstützung in GpioClx-Clienttreibern.
Bearbeitung von IRP_MJ_CREATE-Anforderungen
Kunden öffnen ein Handle für eine Ressource, wenn sie eine Pin-Multiplexing-Ressource reservieren möchten. Ein Pin-Muxing-Server empfängt IRP_MJ_CREATE Anforderungen durch eine Umleitungsoperation vom Ressourcenknoten. Die letzte Pfadkomponente der IRP_MJ_CREATE-Anforderung enthält die Ressourcenhub-ID, bei der es sich um eine 64-Bit-Ganzzahl im Hexadezimalformat handelt. Der Server sollte die Ressourcenhub-ID aus dem Dateinamen mithilfe von RESOURCE_HUB_ID_FROM_FILE_NAME()
von reshub.h extrahieren und IOCTL_RH_QUERY_CONNECTION_PROPERTIES an den Ressourcenhub senden, um den MsftFunctionConfig()
Deskriptor abzurufen.
Der Server sollte den Deskriptor überprüfen und den Freigabemodus und die Pinliste aus dem Deskriptor extrahieren. Anschließend sollte die Freigabevermittlung für die Pins ausgeführt werden, und wenn sie erfolgreich ist, werden die Pins als reserviert markiert, bevor die Anforderung abgeschlossen wird.
Die Freigabevermittlung ist insgesamt erfolgreich, wenn die Freigabevermittlung für jeden Pin in der Pinliste erfolgreich ist. Jeder Pin sollte wie folgt arbitriert werden:
- Wenn die Pin noch nicht reserviert ist, ist die Freigabevermittlung erfolgreich.
- Wenn der Pin bereits als exklusiv reserviert ist, schlägt die Arbitration fehl.
- Wenn der Pin bereits als geteilt reserviert ist,
- und die eingehende Anforderung freigegeben wird, ist die Freigabevermittlung erfolgreich.
- und die eingehende Anforderung ist exklusiv, daher schlägt die Teilungsarbitrage fehl.
Wenn die Teilungsvermittlung fehlschlägt, sollte die Anforderung mit STATUS_GPIO_INCOMPATIBLE_CONNECT_MODEabgeschlossen werden. Wenn die Freigabevermittlung erfolgreich ist, sollte die Anforderung mit STATUS_SUCCESSvervollständigt werden.
Beachten Sie, dass der Freigabemodus der eingehenden Anforderung vom MsftFunctionConfig-Deskriptor und nicht von IrpSp ->Parameters.Create.ShareAccessgenommen werden sollte.
Behandeln von IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS Anfragen
Nachdem der Client eine MsftFunctionConfig-Ressource erfolgreich reserviert hat, indem er ein Handle öffnet, kann er IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS senden, um den Server dazu aufzufordern, den tatsächlichen Hardware-Muxing-Prozess auszuführen. Wenn der Server IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINSempfängt, sollte er, für jeden Pin in der Pinliste,
- Setzen Sie den im PinConfiguration-Mitglied der PNP_FUNCTION_CONFIG_DESCRIPTOR-Struktur angegebenen Pullmodus in die Hardware um.
- Schalte das Pin auf die Funktion, die durch das FunctionNumber-Element der PNP_FUNCTION_CONFIG_DESCRIPTOR-Struktur angegeben wird.
Der Server sollte dann die Anforderung mit STATUS_SUCCESSerfolgreich abschließen.
Die Bedeutung von FunctionNumber wird vom Server definiert, und es wird verstanden, dass der MsftFunctionConfig-Deskriptor mit Kenntnissen darüber erstellt wurde, wie der Server dieses Feld interpretiert.
Denken Sie daran, dass der Server beim Schließen des Handles die Pins auf die Konfiguration zurücksetzen muss, in der sie sich befanden, als IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS empfangen wurde. Daher muss der Server möglicherweise den Zustand der Pins speichern, bevor sie geändert werden.
Verarbeitung von IRP_MJ_CLOSE-Anforderungen
Wenn ein Client keine Muxing-Ressource mehr benötigt, schließt er sein Handle. Wenn ein Server eine IRP_MJ_CLOSE Anforderung empfängt, sollte er die Pins in den Zustand zurücksetzen, in dem sie sich befanden, als IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS empfangen wurde. Wenn der Client nie eine IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINSgesendet hat, ist keine Aktion erforderlich. Der Server sollte dann die Pins in Bezug auf die Teilarbitrage als verfügbar markieren und die Anforderung mit STATUS_SUCCESSabschließen. Stellen Sie sicher, dass Sie die Bearbeitung von IRP_MJ_CLOSE ordnungsgemäß mit der Bearbeitung von IRP_MJ_CREATE synchronisieren.
Richtlinien zur Erstellung von ACPI-Tabellen
In diesem Abschnitt wird beschrieben, wie Muxing-Ressourcen für Clienttreiber bereitgestellt werden. Beachten Sie, dass Sie den Microsoft ASL-Compiler Build 14327 oder höher benötigen, um Tabellen zu kompilieren, die MsftFunctionConfig()
-Ressourcen enthalten.
MsftFunctionConfig()
-Ressourcen werden für Pin-Multiplexing-Clients als Hardware-Ressourcen bereitgestellt.
MsftFunctionConfig()
-Ressourcen sollten Treibern bereitgestellt werden, die Änderungen am Pin-Muxing benötigen, typischerweise SPB- und serielle Controllertreiber. Sie sollten jedoch nicht an SPB- und serielle Peripherietreiber bereitgestellt werden, da die Muxing-Konfiguration vom Controllertreiber verwaltet wird.
Das MsftFunctionConfig()
ACPI-Makro ist wie folgt definiert:
MsftFunctionConfig(Shared/Exclusive
PinPullConfig,
FunctionNumber,
ResourceSource,
ResourceSourceIndex,
ResourceConsumer/ResourceProducer,
VendorData) { Pin List }
- Freigegeben/Exklusiv – Falls exklusiv, kann dieser Pin von einem einzelnen Client gleichzeitig erworben werden. Wenn die Ressource geteilt wird, können mehrere gemeinsame Clients darauf zugreifen. Legen Sie dies immer auf exklusiv fest, da das Zulassen mehrerer unkoordinierter Clients den Zugriff auf eine veränderbare Ressource zu Datenrennen und daher zu unvorhersehbaren Ergebnissen führen kann.
- PinPullConfig – einer von
- PullDefault – Verwenden der SOC-definierten Power-On-Standard-Pullkonfiguration
- PullUp – Pull-Up-Widerstand aktivieren
- PullDown – Pull-down-Widerstand aktivieren
- PullNone – Alle Pull-Widerstände deaktivieren
- FunctionNumber – die Funktionsnummer, die in den Mux zu programmieren ist.
- ResourceSource – Der ACPI-Namespacepfad des Pin-Muxing-Servers
- ResourceSourceIndex – Legen Sie diesen Wert auf 0 fest.
- ResourceConsumer/ResourceProducer – setzen Sie dies auf ResourceConsumer
- VendorData – optionale Binärdaten, deren Bedeutung vom Pin-Muxing-Server definiert wird. Dies sollte in der Regel leer bleiben.
- Pinliste – eine durch Trennzeichen getrennte Liste von Pinnummern, auf die die Konfiguration angewendet wird. Wenn der Pin-Muxing-Server ein GpioClx-Treiber ist, sind dies GPIO-Pinnummern und haben dieselbe Bedeutung wie Pinnummern in einem GpioIo-Deskriptor.
Das folgende Beispiel zeigt, wie eine MsftFunctionConfig()-Ressource an einen I2C-Controllertreiber bereitgestellt werden kann.
Device(I2C1)
{
Name(_HID, "BCM2841")
Name(_CID, "BCMI2C")
Name(_UID, 0x1)
Method(_STA)
{
Return(0xf)
}
Method(_CRS, 0x0, NotSerialized)
{
Name(RBUF, ResourceTemplate()
{
Memory32Fixed(ReadWrite, 0x3F804000, 0x20)
Interrupt(ResourceConsumer, Level, ActiveHigh, Shared) { 0x55 }
MsftFunctionConfig(Exclusive, PullUp, 4, "\\_SB.GPI0", 0, ResourceConsumer, ) { 2, 3 }
})
Return(RBUF)
}
}
Neben dem Arbeitsspeicher und den Unterbrechungsressourcen, die in der Regel von einem Controllertreiber benötigt werden, wird auch eine MsftFunctionConfig()
-Ressource angegeben. Diese Ressource ermöglicht es dem I2C-Controllertreiber, die Pins 2 und 3, die vom Geräteknoten bei \_SB.GPIO0 verwaltet werden, in Funktion 4 zu setzen und den Pull-up-Widerstand zu aktivieren.
Unterstützung von Muxing in GpioClx-Clienttreibern
GpioClx
verfügt über integrierte Unterstützung für Pin-Muxing. GpioClx-Miniporttreiber (auch als "GpioClx-Clienttreiber" bezeichnet) steuern die GPIO-Controllerhardware. Ab Windows 10 Build 14327 können GpioClx-Miniporttreiber Unterstützung für Pin-Muxing hinzufügen, indem zwei neue DDIs implementiert werden:
- CLIENT_ConnectFunctionConfigPins – wird von
GpioClx
aufgerufen, um den Miniporttreiber anzuweisen, die angegebene Muxing-Konfiguration anzuwenden. - CLIENT_DisconnectFunctionConfigPins – wird von
GpioClx
aufgerufen, um den Miniporttreiber anzuweisen, die Multiplex-Konfiguration zurückzusetzen.
Eine Beschreibung dieser Routinen finden Sie unter GpioClx Event Callback Functions.
Zusätzlich zu diesen beiden neuen DDIs sollten vorhandene DDIs auf Pin-Muxing-Kompatibilität geprüft werden.
- CLIENT_ConnectIoPins/CLIENT_ConnectInterrupt – CLIENT_ConnectIoPins wird von GpioClx aufgerufen, um den Miniporttreiber anzuweisen, festgelegte Pins für den GPIO-Eingang oder -Ausgang zu konfigurieren. GPIO schließt MsftFunctionConfig aus, was bedeutet, dass ein Pin niemals gleichzeitig für GPIO und MsftFunctionConfig verbunden sein kann. Da die Standardfunktion eines Pins nicht erforderlich sein mag, um als GPIO zu fungieren, wird ein Pin möglicherweise nicht unbedingt auf GPIO multiplexiert, wenn ConnectIoPins aufgerufen wird. ConnectIoPins ist erforderlich, um alle erforderlichen Vorgänge auszuführen, um den Pin für GPIO IO vorzubereiten, einschließlich Muxing-Vorgängen. CLIENT_ConnectInterrupt sollten sich ähnlich verhalten, da Interrupts als Sonderfall von GPIO-Inputs betrachtet werden können.
- CLIENT_DisconnectIoPins/CLIENT_DisconnectInterrupt – Diese Routine sollte Pins an den Zustand zurückgeben, in dem sie sich befanden, als CLIENT_ConnectIoPins/CLIENT_ConnectInterrupt aufgerufen wurde, es sei denn, das PreserveConfiguration-Flag ist angegeben. Zusätzlich zum Wiederherstellen der Richtung von Pins in ihren Standardzustand sollte der Miniport auch den Mux-Zustand der einzelnen Pins in den Zustand zurücksetzen, in dem sie sich befanden, als die _Connect Routine aufgerufen wurde.
Angenommen, die Standard-Muxing-Konfiguration eines Pins ist UART, und der Pin kann auch als GPIO verwendet werden. Wenn CLIENT_ConnectIoPins aufgerufen wird, um den Pin für GPIO zu verbinden, sollte er den Pin auf GPIO muxen, und in CLIENT_DisconnectIoPins sollte er den Pin zurück auf UART muxen. Im Allgemeinen sollten die Disconnect-Routinen Vorgänge rückgängig machen, die von den Connect-Routinen durchgeführt werden.
Unterstützung von Multiplexing in SpbCx- und SerCx-Controllertreibern
Ab Windows 10 Build 14327 enthalten die SpbCx
und SerCx
Frameworks integrierte Unterstützung für Pin-Muxing, mit der SpbCx
- und SerCx
Controllertreiber ohne Codeänderungen an den Controllertreibern selbst pin-Muxing-Clients sein können. Im weiteren Sinne löst jeder SpbCx/SerCx-Peripherietreiber, der eine Verbindung zu einem Muxing-fähigen SpbCx/SerCx-Controllertreiber herstellt, eine Pin-Muxing-Aktivität aus.
Das folgende Diagramm zeigt die Abhängigkeiten zwischen den einzelnen Komponenten. Wie Sie sehen können, führt das Pin-Muxing zu einer Abhängigkeit der SerCx- und SpbCx-Controllertreiber vom GPIO-Treiber, der normalerweise für das Muxing zuständig ist.
Zum Zeitpunkt der Geräteinitialisierung analysieren die SpbCx
- und SerCx
Frameworks alle MsftFunctionConfig()
Ressourcen, die als Hardwareressourcen für das Gerät bereitgestellt werden. SpbCx/SerCx erwerben und geben die Pin-Muxing-Ressourcen bei Bedarf frei.
SpbCx
wendet die Pin-Muxing-Konfiguration in seinem IRP_MJ_CREATE-Handler an, direkt vor dem Aufrufen der EvtSpbTargetConnect() Rückruf-Funktion des Client-Treibers. Wenn die Muxing-Konfiguration nicht angewendet werden konnte, wird der EvtSpbTargetConnect()
-Callback des Controllertreibers nicht aufgerufen. Daher kann ein SPB-Controllertreiber davon ausgehen, dass Pins zu dem Zeitpunkt, an dem EvtSpbTargetConnect()
aufgerufen wird, der SPB-Funktion zugeordnet sind.
SpbCx
setzt die Pin-Muxing-Konfiguration im IRP_MJ_CLOSE-Handler zurück, unmittelbar nach dem Aufrufen des EvtSpbTargetDisconnect()- Rückrufs des Controllertreibers. Das Ergebnis ist, dass Pins auf die SPB-Funktion umgeschaltet werden, sobald ein Peripherietreiber ein Handle für den SPB-Controllertreiber öffnet, und dass sie abgeschaltet werden, wenn der Peripherietreiber sein Handle schließt.
SerCx
verhält sich ähnlich.
SerCx
ruft alle MsftFunctionConfig()
Ressourcen in seinem IRP_MJ_CREATE Handler direkt vor dem Aufrufen der EvtSerCx2FileOpen() des Controllertreibers Rückruf ab und gibt alle Ressourcen in seinem IRP_MJ_CLOSE Handler frei, unmittelbar nach dem Aufrufen des EvtSerCx2FileClose Rückrufs des Controllertreibers.
Die Auswirkung des dynamischen Pin-Muxings für SerCx
- und SpbCx
-Controllertreiber besteht darin, dass sie in der Lage sein müssen, Pins zu tolerieren, die zu bestimmten Zeiten von der SPB/UART-Funktion zu anderen Funktionen umgeschaltet werden. Controllertreiber müssen davon ausgehen, dass Pins nicht multiplexiert werden, bis EvtSpbTargetConnect()
oder EvtSerCx2FileOpen()
aufgerufen wird. Pins müssen bei den folgenden Rückrufen nicht für die SPB/UART-Funktion gemultiplext werden. Es folgt keine vollständige Liste, sondern stellt die am häufigsten verwendeten PNP-Routinen dar, die von Controllertreibern implementiert werden.
- DriverEntry
- EvtTreiberGerätHinzufügen
- EvtDevicePrepareHardware/EvtDeviceReleaseHardware
- EvtDeviceD0Entry/EvtDeviceD0Exit
Verifizierung
Wenn Sie rhproxy testen möchten, ist es hilfreich, das folgende Schritt-für-Schritt-Verfahren zu verwenden.
- Überprüfen Sie, ob die einzelnen Controllertreiber
SpbCx
,GpioClx
undSerCx
ordnungsgemäß geladen sind und ordnungsgemäß funktionieren. - Stellen Sie sicher, dass
rhproxy
auf dem System vorhanden ist. Einige Editionen und Builds von Windows verfügen nicht über sie. - Kompilieren und laden Sie Ihren rhproxy-Knoten mithilfe von
ACPITABL.dat
. - Überprüfen Sie, dass der Geräteknoten
rhproxy
vorhanden ist. - Überprüfen Sie, ob
rhproxy
geladen wird und startet. - Überprüfen, ob die erwarteten Geräte für den Benutzermodus verfügbar gemacht werden
- Stellen Sie sicher, dass Sie über die Befehlszeile mit jedem Gerät interagieren können.
- Überprüfen, ob Sie mit jedem Gerät über eine UWP-App interagieren können
- Ausführen von HLK-Tests
Überprüfen von Controllertreibern
Da rhproxy andere Geräte im System für den Benutzermodus verfügbar macht, funktioniert es nur, wenn diese Geräte bereits funktionieren. Der erste Schritt besteht darin, zu überprüfen, ob diese Geräte – die I2C-, SPI- und GPIO-Controller, die Sie verfügbar machen möchten – bereits funktionieren.
Führen Sie an der Eingabeaufforderung aus
devcon status *
Schauen Sie sich die Ausgabe an und stellen Sie sicher, dass alle Geräte von Interesse gestartet sind. Wenn ein Gerät einen Problemcode aufweist, müssen Sie die Ursache ermitteln, warum das Gerät nicht lädt. Alle Geräte sollten während der anfänglichen Inbetriebnahme der Plattform aktiviert worden sein. Die Problembehandlung für SpbCx
, GpioClx
oder SerCx
Controllertreiber liegt außerhalb des Umfangs dieses Dokuments.
Überprüfen, ob rhproxy auf dem System vorhanden ist
Stellen Sie sicher, dass der rhproxy
Dienst auf dem System vorhanden ist.
reg query HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\rhproxy
Wenn der Registrierungsschlüssel nicht vorhanden ist, ist rhproxy auf Ihrem System nicht vorhanden. Rhproxy ist auf allen Builds von IoT Core und Windows Enterprise Build 15063 und höher vorhanden.
Kompilieren und Laden von ASL mit ACPITABL.dat
Nachdem Sie nun einen rhproxy ASL-Knoten erstellt haben, ist es an der Zeit, ihn zu kompilieren und zu laden. Sie können den rhproxy-Knoten in eine eigenständige AML-Datei kompilieren, die an die ACPI-Systemtabellen angefügt werden kann. Alternativ können Sie den rhproxy-Knoten direkt in die ACPI-Tabellen Ihrer Plattform einfügen, wenn Sie Zugriff auf die ACPI-Quellen Ihres Systems haben. Während der ersten Inbetriebnahme kann es jedoch einfacher sein, ACPITABL.dat
zu verwenden.
Erstellen Sie eine Datei namens "yourboard.asl", und fügen Sie den RHPX-Geräteknoten in einen DefinitionBlock ein:
DefinitionBlock ("ACPITABL.dat", "SSDT", 1, "MSFT", "RHPROXY", 1) { Scope (\_SB) { Device(RHPX) { ... } } }
Laden Sie die WDK- herunter und finden Sie
asl.exe
beiC:\Program Files (x86)\Windows Kits\10\Tools\x64\ACPIVerify
.Führen Sie den folgenden Befehl aus, um ACPITABL.dat zu generieren:
asl.exe yourboard.asl
Kopieren Sie die resultierende ACPITABL.dat Datei in "c:\windows\system32" auf dem zu testenden System.
Aktivieren Sie "testsigning" auf Ihrem System im Test.
bcdedit /set testsigning on
Starten Sie das System im Test neu. Das System fügt die in ACPITABL.dat definierten ACPI-Tabellen an die Systemfirmwaretabellen an.
Überprüfen, ob der rhproxy-Geräteknoten vorhanden ist
Führen Sie den folgenden Befehl aus, um den rhproxy-Geräteknoten aufzulisten.
devcon status *msft8000
Die Ausgabe von devcon sollte angeben, dass das Gerät vorhanden ist. Wenn der Geräteknoten nicht vorhanden ist, wurden die ACPI-Tabellen dem System nicht erfolgreich hinzugefügt.
Überprüfen Sie, dass rhproxy geladen und gestartet wird
Überprüfen Sie den Status von rhproxy:
devcon status *msft8000
Wenn die Ausgabe angibt, dass rhproxy gestartet wird, wurde rhproxy geladen und erfolgreich gestartet. Wenn ein Problemcode angezeigt wird, müssen Sie dies untersuchen. Einige häufige Problemcodes sind:
- Problem 51 -
CM_PROB_WAITING_ON_DEPENDENCY
Das System startet rhproxy nicht, da eine seiner Abhängigkeiten nicht geladen werden konnte. Dies bedeutet, dass entweder die an rhproxy übergebenen Ressourcen auf ungültige ACPI-Knoten verweisen, oder dass diese Zielgeräte nicht gestartet werden. Überprüfen Sie zunächst, ob alle Geräte erfolgreich ausgeführt werden (siehe "Überprüfen von Controllertreibern" oben). Überprüfen Sie dann Ihre ASL und stellen Sie sicher, dass alle Ressourcenpfade (z. B.\_SB.I2C1
) korrekt sind und auf gültige Knoten in Ihrem DSDT verweisen. - Problem 10 -
CM_PROB_FAILED_START
- Rhproxy konnte nicht gestartet werden, höchstwahrscheinlich aufgrund eines Ressourcenanalyseproblems. Überprüfen Sie Ihre ASL, vergewissern Sie sich, dass die Ressourcenindizes in der DSD korrekt sind, und dass die GPIO-Ressourcen in aufsteigender Reihenfolge der Pin-Nummern angegeben sind.
Überprüfen, ob die erwarteten Geräte für den Benutzermodus verfügbar gemacht werden
Jetzt, da rhproxy läuft, sollte es Geräteschnittstellen erstellt haben, auf die über den Benutzermodus zugegriffen werden kann. Wir verwenden mehrere Befehlszeilentools zum Aufzählen von Geräten und sehen, dass sie vorhanden sind.
Klonen Sie das https://github.com/ms-iot/samples-Repository und erstellen Sie die Beispiele GpioTestTool
, I2cTestTool
, SpiTestTool
und Mincomm
. Kopieren Sie die Tools auf das zu testende Gerät und verwenden Sie die folgenden Befehle, um die Geräte aufzulisten.
I2cTestTool.exe -list
SpiTestTool.exe -list
GpioTestTool.exe -list
MinComm.exe -list
Sie sollten Ihre Geräte und freundliche Namen aufgelistet sehen. Wenn Sie die richtigen Geräte und benutzerfreundlichen Namen nicht sehen, überprüfen Sie Ihre ASL.
Überprüfen Sie jedes Gerät in der Befehlszeile
Der nächste Schritt besteht darin, die Befehlszeilentools zum Öffnen und Interagieren mit den Geräten zu verwenden.
I2CTestTool-Beispiel:
I2cTestTool.exe 0x55 I2C1
> write {1 2 3}
> read 3
> writeread {1 2 3} 3
SpiTestTool-Beispiel:
SpiTestTool.exe -n SPI1
> write {1 2 3}
> read 3
GpioTestTool-Beispiel:
GpioTestTool.exe 12
> setdrivemode output
> write 0
> write 1
> setdrivemode input
> read
> interrupt on
> interrupt off
MinComm (serial) (Beispiel). Verbinden Sie Rx mit Tx, bevor Sie Folgendes ausführen:
MinComm "\\?\ACPI#FSCL0007#3#{86e0d1e0-8089-11d0-9ce4-08003e301f73}\0000000000000006"
(type characters and see them echoed back)
Überprüfen Sie jedes Gerät aus einer UWP-App heraus.
Verwenden Sie die folgenden Beispiele, um zu überprüfen, ob Geräte von UWP funktionieren.
Ausführen der HLK-Tests
Laden Sie das Hardware Lab Kit (HLK)herunter. Die folgenden Tests sind verfügbar:
- GPIO WinRT Funktions- und Stresstests
- I2C WinRT Schreibtests (EEPROM erforderlich)
- I2C WinRT-Lesetests (EEPROM erforderlich)
- I2C WinRT Tests für nicht vorhandene Slave-Adressen
- Erweiterte Funktionstests für I2C WinRT (mbed LPC1768 Erforderlich)
- SPI WinRT-Taktfrequenz-Verifikationstests (mbed LPC1768 erforderlich)
- SPI WinRT IO Transfer Tests (mbed LPC1768 wird benötigt)
- SPI WinRT Stride-Verifikations-Tests
- SPI WinRT Transfer Gap Detection Test (mbed LPC1768 erforderlich)
Wenn Sie den rhproxy-Geräteknoten im HLK-Manager auswählen, werden die entsprechenden Tests automatisch ausgewählt.
Wählen Sie im HLK-Manager "Resource Hub-Proxygerät" aus.
Klicken Sie dann auf die Registerkarte "Tests", und wählen Sie "I2C WinRT", "Gpio WinRT" und "Spi WinRT"-Tests aus.
Klicken Sie auf "Ausgewählt ausführen". Weitere Dokumentation zu jedem Test ist verfügbar, indem Sie mit der rechten Maustaste auf den Test klicken und auf "Testbeschreibung" klicken.
Ressourcen
- ACPI 5.0-Spezifikation
- Asl.exe (Microsoft ASL-Compiler)
- Windows.Devices.Gpio
- Windows.Devices.I2c
- Windows.Devices.Spi
- Windows.Devices.SerialCommunication
- Testautoren- und Ausführungsrahmen (TAEF)
- SpbCx
- GpioClx-
- SerCx
- MITT I2C-Tests
- GpioTestTool
- I2cTestTool-
- SpiTestTool
- MinComm (Serial)
- Hardware Lab Kit (HLK)
Anhang
Anhang A - Raspberry Pi ASL-Auflistung
Siehe auch Raspberry Pi 2 & 3 Pin Mappings
DefinitionBlock ("ACPITABL.dat", "SSDT", 1, "MSFT", "RHPROXY", 1)
{
Scope (\_SB)
{
//
// RHProxy Device Node to enable WinRT API
//
Device(RHPX)
{
Name(_HID, "MSFT8000")
Name(_CID, "MSFT8000")
Name(_UID, 1)
Name(_CRS, ResourceTemplate()
{
// Index 0
SPISerialBus( // SCKL - GPIO 11 - Pin 23
// MOSI - GPIO 10 - Pin 19
// MISO - GPIO 9 - Pin 21
// CE0 - GPIO 8 - Pin 24
0, // Device selection (CE0)
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
0, // databit len: placeholder
ControllerInitiated, // slave mode
0, // connection speed: placeholder
ClockPolarityLow, // clock polarity: placeholder
ClockPhaseFirst, // clock phase: placeholder
"\\_SB.SPI0", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
// Resource usage
) // Vendor Data
// Index 1
SPISerialBus( // SCKL - GPIO 11 - Pin 23
// MOSI - GPIO 10 - Pin 19
// MISO - GPIO 9 - Pin 21
// CE1 - GPIO 7 - Pin 26
1, // Device selection (CE1)
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
0, // databit len: placeholder
ControllerInitiated, // slave mode
0, // connection speed: placeholder
ClockPolarityLow, // clock polarity: placeholder
ClockPhaseFirst, // clock phase: placeholder
"\\_SB.SPI0", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
// Resource usage
) // Vendor Data
// Index 2
SPISerialBus( // SCKL - GPIO 21 - Pin 40
// MOSI - GPIO 20 - Pin 38
// MISO - GPIO 19 - Pin 35
// CE1 - GPIO 17 - Pin 11
1, // Device selection (CE1)
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
0, // databit len: placeholder
ControllerInitiated, // slave mode
0, // connection speed: placeholder
ClockPolarityLow, // clock polarity: placeholder
ClockPhaseFirst, // clock phase: placeholder
"\\_SB.SPI1", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
// Resource usage
) // Vendor Data
// Index 3
I2CSerialBus( // Pin 3 (GPIO2, SDA1), 5 (GPIO3, SCL1)
0xFFFF, // SlaveAddress: placeholder
, // SlaveMode: default to ControllerInitiated
0, // ConnectionSpeed: placeholder
, // Addressing Mode: placeholder
"\\_SB.I2C1", // ResourceSource: I2C bus controller name
,
,
) // VendorData
// Index 4 - GPIO 4 -
GpioIO(Shared, PullUp, , , , "\\_SB.GPI0", , , , ) { 4 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 4 }
// Index 6 - GPIO 5 -
GpioIO(Shared, PullUp, , , , "\\_SB.GPI0", , , , ) { 5 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 5 }
// Index 8 - GPIO 6 -
GpioIO(Shared, PullUp, , , , "\\_SB.GPI0", , , , ) { 6 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 6 }
// Index 10 - GPIO 12 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 12 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 12 }
// Index 12 - GPIO 13 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 13 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 13 }
// Index 14 - GPIO 16 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 16 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 16 }
// Index 16 - GPIO 18 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 18 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 18 }
// Index 18 - GPIO 22 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 22 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 22 }
// Index 20 - GPIO 23 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 23 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 23 }
// Index 22 - GPIO 24 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 24 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 24 }
// Index 24 - GPIO 25 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 25 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 25 }
// Index 26 - GPIO 26 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 26 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 26 }
// Index 28 - GPIO 27 -
GpioIO(Shared, PullDown, , , , "\\_SB.GPI0", , , , ) { 27 }
GpioInt(Edge, ActiveBoth, Shared, PullDown, 0, "\\_SB.GPI0",) { 27 }
// Index 30 - GPIO 35 -
GpioIO(Shared, PullUp, , , , "\\_SB.GPI0", , , , ) { 35 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 35 }
// Index 32 - GPIO 47 -
GpioIO(Shared, PullUp, , , , "\\_SB.GPI0", , , , ) { 47 }
GpioInt(Edge, ActiveBoth, Shared, PullUp, 0, "\\_SB.GPI0",) { 47 }
})
Name(_DSD, Package()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package()
{
// Reference http://www.raspberrypi.org/documentation/hardware/raspberrypi/spi/README.md
// SPI 0
Package(2) { "bus-SPI-SPI0", Package() { 0, 1 }}, // Index 0 & 1
Package(2) { "SPI0-MinClockInHz", 7629 }, // 7629 Hz
Package(2) { "SPI0-MaxClockInHz", 125000000 }, // 125 MHz
Package(2) { "SPI0-SupportedDataBitLengths", Package() { 8 }}, // Data Bit Length
// SPI 1
Package(2) { "bus-SPI-SPI1", Package() { 2 }}, // Index 2
Package(2) { "SPI1-MinClockInHz", 30518 }, // 30518 Hz
Package(2) { "SPI1-MaxClockInHz", 125000000 }, // 125 MHz
Package(2) { "SPI1-SupportedDataBitLengths", Package() { 8 }}, // Data Bit Length
// I2C1
Package(2) { "bus-I2C-I2C1", Package() { 3 }},
// GPIO Pin Count and supported drive modes
Package (2) { "GPIO-PinCount", 54 },
Package (2) { "GPIO-UseDescriptorPinNumbers", 1 },
Package (2) { "GPIO-SupportedDriveModes", 0xf }, // InputHighImpedance, InputPullUp, InputPullDown, OutputCmos
}
})
}
}
}
Anhang B - MinnowBoardMax ASL-Auflistung
Siehe auch MinnowBoard Max Pin Mappings
DefinitionBlock ("ACPITABL.dat", "SSDT", 1, "MSFT", "RHPROXY", 1)
{
Scope (\_SB)
{
Device(RHPX)
{
Name(_HID, "MSFT8000")
Name(_CID, "MSFT8000")
Name(_UID, 1)
Name(_CRS, ResourceTemplate()
{
// Index 0
SPISerialBus( // Pin 5, 7, 9 , 11 of JP1 for SIO_SPI
1, // Device selection
PolarityLow, // Device selection polarity
FourWireMode, // wiremode
8, // databit len
ControllerInitiated, // slave mode
8000000, // Connection speed
ClockPolarityLow, // Clock polarity
ClockPhaseSecond, // clock phase
"\\_SB.SPI1", // ResourceSource: SPI bus controller name
0, // ResourceSourceIndex
ResourceConsumer, // Resource usage
JSPI, // DescriptorName: creates name for offset of resource descriptor
) // Vendor Data
// Index 1
I2CSerialBus( // Pin 13, 15 of JP1, for SIO_I2C5 (signal)
0xFF, // SlaveAddress: bus address
, // SlaveMode: default to ControllerInitiated
400000, // ConnectionSpeed: in Hz
, // Addressing Mode: default to 7 bit
"\\_SB.I2C6", // ResourceSource: I2C bus controller name (For MinnowBoard Max, hardware I2C5(0-based) is reported as ACPI I2C6(1-based))
,
,
JI2C, // Descriptor Name: creates name for offset of resource descriptor
) // VendorData
// Index 2
UARTSerialBus( // Pin 17, 19 of JP1, for SIO_UART2
115200, // InitialBaudRate: in bits ber second
, // BitsPerByte: default to 8 bits
, // StopBits: Defaults to one bit
0xfc, // LinesInUse: 8 1-bit flags to declare line enabled
, // IsBigEndian: default to LittleEndian
, // Parity: Defaults to no parity
, // FlowControl: Defaults to no flow control
32, // ReceiveBufferSize
32, // TransmitBufferSize
"\\_SB.URT2", // ResourceSource: UART bus controller name
,
,
UAR2, // DescriptorName: creates name for offset of resource descriptor
)
// Index 3
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO2",) {0} // Pin 21 of JP1 (GPIO_S5[00])
// Index 4
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO2",) {0}
// Index 5
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO2",) {1} // Pin 23 of JP1 (GPIO_S5[01])
// Index 6
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO2",) {1}
// Index 7
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO2",) {2} // Pin 25 of JP1 (GPIO_S5[02])
// Index 8
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO2",) {2}
// Index 9
UARTSerialBus( // Pin 6, 8, 10, 12 of JP1, for SIO_UART1
115200, // InitialBaudRate: in bits ber second
, // BitsPerByte: default to 8 bits
, // StopBits: Defaults to one bit
0xfc, // LinesInUse: 8 1-bit flags to declare line enabled
, // IsBigEndian: default to LittleEndian
, // Parity: Defaults to no parity
FlowControlHardware, // FlowControl: Defaults to no flow control
32, // ReceiveBufferSize
32, // TransmitBufferSize
"\\_SB.URT1", // ResourceSource: UART bus controller name
,
,
UAR1, // DescriptorName: creates name for offset of resource descriptor
)
// Index 10
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {62} // Pin 14 of JP1 (GPIO_SC[62])
// Index 11
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {62}
// Index 12
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {63} // Pin 16 of JP1 (GPIO_SC[63])
// Index 13
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {63}
// Index 14
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {65} // Pin 18 of JP1 (GPIO_SC[65])
// Index 15
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {65}
// Index 16
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {64} // Pin 20 of JP1 (GPIO_SC[64])
// Index 17
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {64}
// Index 18
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {94} // Pin 22 of JP1 (GPIO_SC[94])
// Index 19
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {94}
// Index 20
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {95} // Pin 24 of JP1 (GPIO_SC[95])
// Index 21
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {95}
// Index 22
GpioIo (Shared, PullNone, 0, 0, IoRestrictionNone, "\\_SB.GPO0",) {54} // Pin 26 of JP1 (GPIO_SC[54])
// Index 23
GpioInt(Edge, ActiveBoth, SharedAndWake, PullNone, 0,"\\_SB.GPO0",) {54}
})
Name(_DSD, Package()
{
ToUUID("daffd814-6eba-4d8c-8a91-bc9bbf4aa301"),
Package()
{
// SPI Mapping
Package(2) { "bus-SPI-SPI0", Package() { 0 }},
Package(2) { "SPI0-MinClockInHz", 100000 },
Package(2) { "SPI0-MaxClockInHz", 15000000 },
// SupportedDataBitLengths takes a list of support data bit length
// Example : Package(2) { "SPI0-SupportedDataBitLengths", Package() { 8, 7, 16 }},
Package(2) { "SPI0-SupportedDataBitLengths", Package() { 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 }},
// I2C Mapping
Package(2) { "bus-I2C-I2C5", Package() { 1 }},
// UART Mapping
Package(2) { "bus-UART-UART2", Package() { 2 }},
Package(2) { "bus-UART-UART1", Package() { 9 }},
}
})
}
}
}
Anhang C – PowerShell-Beispielskript zum Generieren von GPIO-Ressourcen
Das folgende Skript kann verwendet werden, um die GPIO-Ressourcendeklarationen für Raspberry Pi zu generieren:
$pins = @(
@{PinNumber=4;PullConfig='PullUp'},
@{PinNumber=5;PullConfig='PullUp'},
@{PinNumber=6;PullConfig='PullUp'},
@{PinNumber=12;PullConfig='PullDown'},
@{PinNumber=13;PullConfig='PullDown'},
@{PinNumber=16;PullConfig='PullDown'},
@{PinNumber=18;PullConfig='PullDown'},
@{PinNumber=22;PullConfig='PullDown'},
@{PinNumber=23;PullConfig='PullDown'},
@{PinNumber=24;PullConfig='PullDown'},
@{PinNumber=25;PullConfig='PullDown'},
@{PinNumber=26;PullConfig='PullDown'},
@{PinNumber=27;PullConfig='PullDown'},
@{PinNumber=35;PullConfig='PullUp'},
@{PinNumber=47;PullConfig='PullUp'})
# generate the resources
$FIRST_RESOURCE_INDEX = 4
$resourceIndex = $FIRST_RESOURCE_INDEX
$pins | % {
$a = @"
// Index $resourceIndex - GPIO $($_.PinNumber) - $($_.Name)
GpioIO(Shared, $($_.PullConfig), , , , "\\_SB.GPI0", , , , ) { $($_.PinNumber) }
GpioInt(Edge, ActiveBoth, Shared, $($_.PullConfig), 0, "\\_SB.GPI0",) { $($_.PinNumber) }
"@
Write-Host $a
$resourceIndex += 2;
}