GPIO, I2C ve SPI'ye kullanıcı modu erişimini etkinleştirme

Windows 10 ve sonraki sürümlerde, kullanıcı modundan genel amaçlı giriş/çıkışa (GPIO), Inter-Integrated Circuit'e (I2C), Seri Çevresel Arabirime (SPI) ve evrensel asenkron alıcı-vericiye (UART) doğrudan erişim sağlayan API'ler sunulur. Raspberry Pi 2 gibi geliştirme panoları bu bağlantıların bir alt kümesini kullanıma sunar ve bu sayede belirli bir uygulamayı ele almak için özel devreli bir temel işlem modülünü genişletebilirsiniz. Bu düşük seviyeli veri yolları genellikle kart üzerindeki diğer kritik işlevlerle paylaşılır; GPIO pinlerinin ve veri yollarının yalnızca bir alt kümesi header’lar üzerinden dışarıya sunulur. Sistem kararlılığını korumak için, kullanıcı modu uygulamaları tarafından değiştirilmesi için hangi pinlerin ve veri yolların güvenli olduğunu belirtmek gerekir.

Bu belge, Gelişmiş Yapılandırma ve Güç Arabirimi'nde (ACPI) bu yapılandırmanın nasıl belirtileceğini açıklar ve yapılandırmanın doğru belirtildiğini doğrulamak için araçlar sağlar.

Important

Bu belgenin hedef kitlesi Birleşik Genişletilebilir Üretici Yazılımı Arabirimi (UEFI) ve ACPI geliştiricileridir. ACPI, ACPI Kaynak Dili (ASL) yazma ve SpbCx/GpioClx hakkında bazı bilgi sahibi olduğunuz varsayılır.

Windows'da alt düzey veri yollarına kullanıcı modu erişimi, mevcut GpioClx ve SpbCx çerçeveleri aracılığıyla sağlanır. Windows IoT Core ve Windows Enterprise'da kullanılabilen RhProxy adlı yeni bir sürücü, GpioClx ve SpbCx kaynaklarını kullanıcı modunda kullanıma sunar. API'leri etkinleştirmek için, kullanıcı moduna açık olması gereken GPIO ve SPB kaynaklarının her biriyle ACPI tablolarınızda rhproxy için bir cihaz düğümü bildirilmelidir. Bu belge ASL yazma ve doğrulama işleminde yol gösterir.

Örneğe göre ASL

Raspberry Pi 2'de rhproxy cihaz düğümü bildirimini inceleyelim. İlk olarak, \_SB kapsamında ACPI cihaz bildirimini oluşturun.

Device(RHPX)
{
    Name(_HID, "MSFT8000")
    Name(_CID, "MSFT8000")
    Name(_UID, 1)
}
  • _HID – Donanım Kimliği. Bunu satıcıya özgü bir donanım kimliği olarak ayarlayın.
  • _CID – Uyumlu Kimlik. "MSFT8000" olmalıdır.
  • _UID – Benzersiz Kimlik. 1 olarak ayarlayın.

Ardından, kullanıcı moduna açık olması gereken GPIO ve SPB kaynaklarının her birini bildireceğiz. Kaynak dizinleri özellikleri kaynaklarla ilişkilendirmek için kullanıldığından kaynakların bildirildiği sıra önemlidir. Sunulan birden çok I2C veya SPI veri yolu varsa, bildirilen ilk veri yolu bu tür için 'varsayılan' veri yolu olarak kabul edilir ve Windows.Devices.I2c.I2cController ile Windows.Devices.Spi.SpiController sınıflarının GetDefaultAsync() yöntemleri tarafından döndürülen örnek olur.

SPI

Raspberry Pi'nin iki açık SPI otobüsü vardır. SPI0 iki donanım yongası seçim hattına ve SPI1'de bir donanım yongası seçim hattı vardır. Her veri yolundaki her yonga seçme hattı için bir SPISerialBus() kaynak bildirimi gereklidir. Aşağıdaki iki SPISerialBus kaynak bildirimi, SPI0 üzerindeki iki yonga seçme satırına yöneliktir. DeviceSelection alanı, sürücünün donanım yongası seçme satırı tanımlayıcısı olarak yorumladığı benzersiz bir değer içerir. DeviceSelection alanına yerleştirdiğiniz tam değer, sürücünüzün ACPI bağlantı tanımlayıcısının bu alanını nasıl yorumladığınıza bağlıdır.

Note

Bu makale, Microsoft göz yummayan ve yeni ürün ve belgelerde kullanmayı durduran bir terim olan köle terimine yönelik başvurular içerir. Terim yazılımdan kaldırıldığında bu makaleden de kaldırılacak.

// 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

Yazılım bu iki kaynağın aynı veri yolu ile ilişkilendirilmesi gerektiğini nasıl biliyor? Veri yolunun anlaşılır adı ile kaynak indeksi arasındaki eşleme DSD'de tanımlanmıştır:

Package(2) { "bus-SPI-SPI0", Package() { 0, 1 }},

Bu, kaynak dizinleri 0 ve 1 olan iki yonga seçme çizgisiyle "SPI0" adlı bir veri yolu oluşturur. SPI veri yolunun özelliklerini bildirmek için birkaç özellik daha gerekir.

Package(2) { "SPI0-MinClockInHz", 7629 },
Package(2) { "SPI0-MaxClockInHz", 125000000 },

MinClockInHz ve MaxClockInHz özellikleri, denetleyici tarafından desteklenen en düşük ve en yüksek saat hızlarını belirtir. API, kullanıcıların bu aralığın dışındaki değerleri belirtmesini engeller. Saat hızı, bağlantı tanımlayıcısının _SPE alanındaki SPB sürücünüze geçirilir (ACPI bölüm 6.4.3.8.2.2).

Package(2) { "SPI0-SupportedDataBitLengths", Package() { 8 }},

SupportedDataBitLengths özelliği, denetleyici tarafından desteklenen veri bit uzunluklarını listeler. Virgülle ayrılmış bir listede birden çok değer belirtilebilir. API, kullanıcıların bu listenin dışındaki değerleri belirtmesini engeller. Veri bit uzunluğu, bağlantı tanımlayıcısının _LEN alanındaki SPB sürücünüze geçirilir (ACPI bölüm 6.4.3.8.2.2).

Bu kaynak bildirimlerini "şablonlar" olarak düşünebilirsiniz. Bazı alanlar sistem önyüklemesinde düzeltilirken, diğerleri çalışma zamanında dinamik olarak belirtilir. SPISerialBus tanımlayıcısının aşağıdaki alanları sabittir:

  • Cihaz Seçimi
  • Aygıt Seçim Polaritesi
  • WireMode
  • SlaveMode
  • ResourceSource

Aşağıdaki alanlar, çalışma zamanında kullanıcı tarafından belirtilen değerler için yer tutuculardır:

  • DataBitLength
  • Bağlantı Hızı
  • Saat Polaritesi
  • ClockPhase

SPI1 yalnızca tek bir yonga seçme çizgisi içerdiğinden, tek SPISerialBus() bir kaynak bildirilir:

// 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

Eşlik eden, zorunlu olan dost ad bildirimi DSD'de belirtilir ve bu kaynak bildiriminin indeksine işaret eder.

Package(2) { "bus-SPI-SPI1", Package() { 2 }},

Bu, "SPI1" adlı bir veri yolu oluşturur ve bunu kaynak dizini 2 ile ilişkilendirir.

SPI Sürücü Gereksinimleri

  • SpbCx kullanılması veya SpbCx ile uyumlu olması gerekir
  • MITT SPI Testlerini geçmiş olmalıdır
  • 4Mhz saat hızını desteklemelidir
  • 8 bit veri uzunluğunu desteklemelidir
  • Tüm SPI Modlarını desteklemelidir: 0, 1, 2, 3

I2C

Ardından I2C kaynaklarını bildireceğiz. Raspberry Pi, 3 ve 5 pinlerinde tek bir I2C veri yolunu kullanıma sunar.

// 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

Eşlik eden kolay ad bildirimi (gerekli olan) DSD'de belirtilir:

Package(2) { "bus-I2C-I2C1", Package() { 3 }},

Bu, yukarıda bildirdiğimiz I2CSerialBus() kaynağının dizini olan 3 numaralı kaynak dizinine işaret eden, kolay anlaşılır adı “I2C1” olan bir I2C veri yolunu bildirir.

I2CSerialBus() tanımlayıcısının aşağıdaki alanları düzeltildi:

  • SlaveMode
  • ResourceSource

Aşağıdaki alanlar, çalışma zamanında kullanıcı tarafından belirtilen değerler için yer tutuculardır.

  • SlaveAddress
  • Bağlantı Hızı
  • Adresleme Modu

I2C Sürücü Gereksinimleri

  • SpbCx kullanmalı veya SpbCx uyumlu olmalıdır
  • MITT I2C Testlerini geçmiş olmalıdır
  • 7 bit adresleme desteklenmelidir
  • 100kHz saat hızını desteklemelidir
  • 400kHz saat hızını desteklemelidir

GPIO

Ardından, kullanıcı moduna sunulan tüm GPIO pinlerini bildireceğiz. Hangi pinlerin kullanıma sunulacağına karar verirken aşağıdaki yönergeleri sunuyoruz:

  • Açıkta bulunan tüm pin header’lar üzerindeki pinleri tanımlayın.
  • Düğmeler ve LED'ler gibi kullanışlı kart üzerindeki işlevlere bağlı pinleri tanımlayın.
  • Sistem işlevleri için ayrılmış veya hiçbir şeye bağlı olmayan pinleri bildirmeyin.

Aşağıdaki ASL bloğu iki pin bildirir: GPIO4 ve GPIO5. Diğer pinler, kısa tutmak adına burada gösterilmemiştir. Ek C, GPIO kaynaklarını oluşturmak için kullanılabilecek örnek bir powershell betiği içerir.

// 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 }

GPIO pinleri bildirildiğinde aşağıdaki gereksinimlere uyulmalıdır:

  • Yalnızca bellek eşlemeli GPIO denetleyicileri desteklenir. I2C/SPI üzerinden arabirimlenen GPIO denetleyicileri desteklenmez. Denetleyici sürücüsü, CLIENT_QueryControllerBasicInformation geri çağırmasına yanıt olarak CLIENT_CONTROLLER_BASIC_INFORMATION yapısında MemoryMappedController bayrağını ayarlıyorsa bellek eşlemeli bir denetleyicidir.
  • Her pin için hem GpioIO hem de GpioInt kaynağı gerekir. GpioInt kaynağının hemen GpioIO kaynağını izlemesi ve aynı pin numarasına başvurması gerekir.
  • GPIO kaynaklarının pin sayısı artırılarak sıralanması gerekir.
  • Her GpioIO ve GpioInt kaynağı, pin listesinde tam olarak bir pin numarası içermelidir.
  • Her iki tanımlayıcının ShareType alanı Shared olmalıdır
  • GpioInt tanımlayıcısının EdgeLevel alanı Edge olmalıdır
  • GpioInt tanımlayıcısının ActiveLevel alanı ActiveBoth olmalıdır
  • PinConfig alanı
    • Hem GpioIO hem de GpioInt tanımlayıcılarında aynı olmalıdır
    • PullUp, PullDown veya PullNone'lerden biri olmalıdır. Bu, PullDefault olamaz.
    • Çekme konfigürasyonu, pinin güç verildiğindeki durumla eşleşmelidir. Pinin açık durumdan belirtilen çekme moduna koyulması pinin durumunu değiştirmemelidir. Örneğin, veri sayfası pinin pull-up ile başlatıldığını belirtiyorsa, PinConfig değerini PullUp olarak belirtin.

Üretici yazılımı, UEFI ve sürücü başlatma kodu, önyükleme sırasında bir pinin durumunu güç verildiğindeki durumundan değiştirmemelidir. Bir pine neyin bağlı olduğunu ve dolayısıyla hangi durum geçişlerinin güvenli olduğunu yalnızca kullanıcı bilir. Kullanıcıların pinle doğru arabirimlere sahip donanımlar tasarlaması için her pinin açma durumu belgelenmelidir. Önyükleme sırasında pin beklenmedik şekilde durum değiştirmemelidir.

Desteklenen Sürücü Modları

GPIO denetleyiciniz yüksek empedans girişi ve CMOS çıkışına ek olarak yerleşik çekme ve aşağı çekme dirençlerini destekliyorsa, bunu isteğe bağlı SupportedDriveModes özelliğiyle belirtmeniz gerekir.

Package (2) { “GPIO-SupportedDriveModes”, 0xf },

SupportedDriveModes özelliği, GPIO denetleyicisi tarafından desteklenen sürücü modlarını gösterir. Yukarıdaki örnekte, aşağıdaki sürücü modlarının tümü desteklenir. özelliği aşağıdaki değerlerin bit maskesidir:

Bayrak Değeri Sürücü Modu Description
0x1 Giriş Yüksek Empedansı Pin, ACPI'deki "PullNone" değerine karşılık gelen yüksek empedans girişini destekler.
0x2 InputPullUp Pin, ACPI'deki "PullUp" değerine karşılık gelen yerleşik bir çekme direncini destekler.
0x4 Girdi Açılır Menüsü Pin, ACPI'deki "PullDown" değerine karşılık gelen yerleşik bir aşağı çekme direncini destekler.
0x8 OutputCmos Pin, hem güçlü yüksek hem de güçlü düşük değerlerin oluşturulmasını destekler (açık boşaltmanın aksine).

InputHighImpedance ve OutputCmos neredeyse tüm GPIO denetleyicileri tarafından desteklenir. SupportedDriveModes özelliği belirtilmezse, bu varsayılan değerdir.

Bir GPIO sinyali, harici bir başlığa ulaşmadan önce bir düzey kaydırıcıdan geçiyorsa, sürüş modu harici başlıkta gözlemlenemeyecek olsa bile SOC’nin desteklediği sürüş modlarını belirtin. Örneğin, bir pin, onu pull-up direnciyle açık drenajlı gibi gösteren çift yönlü bir seviye dönüştürücüden geçiyorsa, pin yüksek empedanslı giriş olarak yapılandırılmış olsa bile dışarıya çıkarılmış header üzerinde hiçbir zaman yüksek empedans durumu gözlemlemezsiniz. Pinin yüksek empedans girişini desteklediğini bildirmeniz gerekir.

Pin Numaralandırması

Windows iki pin numaralandırma düzenini destekler:

  • Sıralı Pin Numaralandırma – Kullanıcılar 0, 1, 2 gibi sayıları görür... açık pin sayısına kadar. 0, ASL'de bildirilen ilk GpioIo kaynağıdır, 1 ASL'de bildirilen ikinci GpioIo kaynağıdır, vb.
  • Yerel Pin Numaralandırma – Kullanıcılar GpioIo tanımlayıcılarında belirtilen pin numaralarını görür, örneğin, 4, 5, 12, 13, ...
Package (2) { “GPIO-UseDescriptorPinNumbers”, 1 },

UseDescriptorPinNumbers özelliği Windows sıralı pin numaralandırması yerine yerel pin numaralandırması kullanmasını bildirir. UseDescriptorPinNumbers özelliği belirtilmezse veya değeri sıfırsa, Windows varsayılan olarak Sıralı pin numaralandırması olur.

Yerel pin numaralandırması kullanılıyorsa , PinCount özelliğini de belirtmeniz gerekir.

Package (2) { “GPIO-PinCount”, 54 },

PinCount özelliği, sürücünün CLIENT_QueryControllerBasicInformation geri çağırmasında TotalPins özelliği aracılığıyla döndürülen değerle GpioClx eşleşmelidir.

Panonuz için mevcut yayımlanmış belgelerle en uyumlu numaralandırma düzenini seçin. Örneğin, Raspberry Pi yerel pin numaralandırmasını kullanır çünkü mevcut birçok pin dizilimi şeması BCM2835 pin numaralarını kullanır. MinnowBoardMax, çok az sayıda sabitleme diyagramı olduğundan sıralı pin numaralandırma kullanır ve 200'den fazla pinten yalnızca 10 pin gösterildiğinden sıralı pin numaralandırması geliştirici deneyimini basitleştirir. Sıralı veya yerel pin numaralandırması kullanma kararı, geliştirici karışıklığını azaltmayı hedeflemelidir.

GPIO Sürücü Gereksinimleri

  • Kullanmalıdır GpioClx
  • SoC üzerinde bellek eşlemeli olmalıdır
  • Öykülenen ActiveBoth kesme işleme mekanizması kullanılmalıdır

UART

UART sürücünüz SerCx veya SerCx2 kullanıyorsa, sürücüyü kullanıcı moduna sunmak için rhproxy'yi kullanabilirsiniz. Türünde GUID_DEVINTERFACE_COMPORT bir cihaz arabirimi oluşturan UART sürücülerinin rhproxy kullanması gerekmez. Gelen kutusu Serial.sys sürücüsü bu durumlardan biridir.

SerCx-style UART'ı kullanıcı moduna açmak için aşağıdaki gibi bir UARTSerialBus kaynak bildirin.

// 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
    ,
    ,
    ,
    )

Yalnızca ResourceSource alanı sabitken, diğer tüm alanlar kullanıcı tarafından çalışma zamanında belirtilen değerler için yer tutucudur.

Eşlik eden kolay ad bildirimi:

Package(2) { "bus-UART-UART2", Package() { 2 }},

Bu, "UART2" kolay adını denetleyiciye atar. Bu ad, kullanıcıların kullanıcı modundan veri yolu erişimi için kullanacağı tanımlayıcıdır.

Çalışma Zamanında Pin Çoklama

Pin muxing, farklı işlevler için aynı fiziksel pini kullanabilme özelliğidir. I2C denetleyicisi, SPI denetleyicisi ve GPIO denetleyicisi gibi çeşitli yonga üzerinde çevre birimleri soC üzerinde aynı fiziksel pine yönlendirilebilir. MUX bloğu, belirli bir anda uç üzerinde hangi işlevin etkin olduğunu denetler. Geleneksel olarak, bellenim önyükleme sırasında işlev atamaları oluşturmakla sorumludur ve bu atama önyükleme oturumu aracılığıyla statik kalır. Çalışma zamanında pin çoklama, pin işlevi atamalarının çalışma zamanında yeniden yapılandırılabilmesini sağlar. Kullanıcıların çalışma zamanında pin'in işlevini seçmesine olanak sağlamak, kullanıcıların panonun pinlerini hızla yeniden yapılandırmasına olanak tanıyarak geliştirmeyi hızlandırır ve donanımın statik yapılandırmaya göre daha geniş bir uygulama yelpazesini desteklemesini sağlar.

Kullanıcılar ek kod yazmadan GPIO, I2C, SPI ve UART için muxing desteğini tüketir. Bir kullanıcı, OpenPin() veya FromIdAsync() kullanarak bir GPIO ya da veri yolunu açtığında, alttaki fiziksel pinler istenen işleve otomatik olarak çoklanır. Pinler zaten farklı bir işlev tarafından kullanılıyorsa, OpenPin() veya FromIdAsync() çağrısı başarısız olur. Kullanıcı, GpioPin, I2cDevice, SpiDevice veya SerialDevice nesnesini dispose ederek cihazı kapattığında, pinler serbest bırakılır ve bunların daha sonra farklı bir işlev için açılmasına olanak tanınır.

Windows, GpioClx, SpbCx ve SerCx çerçevelerinde pin muxing için yerleşik destek içerir. Bu çerçeveler, GPIO pinine veya veri yoluna erişildiğinde pini otomatik olarak doğru işleve geçmek için birlikte çalışır. Birden çok istemci arasındaki çakışmaları önlemek için pinlere erişim denetlenir. Bu yerleşik desteğe ek olarak, pin muxing arabirimleri ve protokolleri genel amaçlıdır ve ek cihazları ve senaryoları destekleyecek şekilde genişletilebilir.

Bu belgede önce pin muxing'e dahil olan temel arabirimler ve protokoller açıklanır ve ardından GpioClx, SpbCx ve SerCx denetleyici sürücülerine pin muxing desteğinin nasıl ekleneceği açıklanır.

Pin Çoklama Mimarisi

Bu bölümde, pin muxing'e dahil olan temel arabirimler ve protokoller açıklanmaktadır. GpioClx/SpbCx/SerCx sürücüleriyle pin muxing'i desteklemek için temel protokoller hakkında bilgi sahibi olmak şart değildir. GpioCls/SpbCx/SerCx sürücüleriyle pin muxing'i destekleme hakkında ayrıntılı bilgi için bkz. GpioClx istemci sürücülerinde pin muxing desteği uygulama ve SpbCx ve SerCx denetleyici sürücülerinde muxing desteği kullanma.

Pin çoklama, birkaç bileşenin birlikte çalışmasıyla gerçekleştirilir.

  • Pin muxing sunucuları – bunlar, pin muxing denetim bloğunu denetleyan sürücülerdir. Pin çoklama sunucuları, istemcilerden gelen pin çoklama isteklerini, çoklama kaynaklarını ayırmaya yönelik IRP_MJ_CREATE istekleri ve bir pinin işlevini değiştirmeye yönelik *IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS- istekleri aracılığıyla alır. Katlama bloğu bazen GPIO bloğunun bir parçası olduğundan, pin muxing sunucusu genellikle GPIO sürücüsüdür. Muxing bloğu ayrı bir çevre birimi olsa bile, muxing işlevselliğini yerleştirmek için GPIO sürücüsü mantıksal olarak uygun bir yerdir.
  • Pin muxing istemcileri – bunlar pin muxing kullanan sürücülerdir. Pin çoklama istemcileri, pin çoklama kaynaklarını ACPI ürün yazılımından alır. Pin muxing kaynakları bir bağlantı kaynağı türüdür ve kaynak hub'ı tarafından yönetilir. Pin çoklama istemcileri, kaynak için bir tutamaç açarak pin çoklama kaynaklarını rezerve eder. Donanım değişikliğini etkilemek için istemcilerin IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS isteği göndererek yapılandırmayı işlemesi gerekir. İstemciler, tutamacı kapatarak pin çoklama kaynaklarını serbest bırakır; bu noktada çoklama yapılandırması varsayılan durumuna geri döndürülür.
  • ACPI üretici yazılımı – MsftFunctionConfig() kaynaklarıyla çoklama yapılandırmasını belirtir. MsftFunctionConfig kaynakları, bir istemci tarafından hangi pinlerin ve hangi çoklama yapılandırmasının gerekli olduğunu belirtir. MsftFunctionConfig kaynakları işlev numarası, çekme yapılandırması ve pin numaralarının listesini içerir. MsftFunctionConfig kaynakları, pin çoklama istemcilerine donanım kaynakları olarak sağlanır; bu kaynaklar, GPIO ve SPB bağlantı kaynaklarına benzer şekilde, sürücüler tarafından PrepareHardware geri çağırma işlevinde alınır. İstemcilere, kaynak için bir tanıtıcı açmakta kullanılabilecek bir kaynak merkezi kimliği verilir.

MsftFunctionConfig() tanımlayıcıları içeren ASL dosyalarını derlemek için, bu tanımlayıcılar şu anda ACPI çalışma komitesi tarafından gözden geçirilmekte olduğundan, /MsftInternal komut satırı anahtarını asl.exe öğesine iletmeniz gerekir. Örneğin: asl.exe /MsftInternal dsdt.asl

Pin muxing işlemine dahil olan işlemlerin dizisi aşağıda gösterilmiştir.

Pin çoklama istemci-sunucu etkileşimi

  1. İstemci, EvtDevicePrepareHardware() geri çağırmasında ACPI üretici yazılımından MsftFunctionConfig kaynaklarını alır.
  2. İstemci, kaynak kimliğinden bir yol oluşturmak için RESOURCE_HUB_CREATE_PATH_FROM_ID() resource hub yardımcı işlevini kullanır, ardından bu yola yönelik bir tanıtıcı açar (ZwCreateFile(), IoGetDeviceObjectPointer() veya WdfIoTargetOpen() kullanarak).
  3. Sunucu, kaynak hub'ı yardımcı işlevlerini RESOURCE_HUB_ID_FROM_FILE_NAME()kullanarak dosya yolundan kaynak hub kimliğini ayıklar ve kaynak tanımlayıcısını almak için kaynak hub'ını sorgular.
  4. Sunucu, tanımlayıcıdaki her pin için paylaşım tahkimi gerçekleştirir ve IRP_MJ_CREATE isteğini tamamlar.
  5. İstemci, alınan tanıtıcı üzerinde IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS isteğinde bulunur.
  6. sunucu, IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS yanıt olarak belirtilen işlevi her pinte etkin hale getirerek donanım muxing işlemini gerçekleştirir.
  7. İstemci, istenen pin çoklama yapılandırmasına bağlı işlemleri sürdürür.
  8. İstemci artık pinlerin çoklanmasına ihtiyaç duymadığında, tanıtıcıyı kapatır.
  9. İşleyici kapatıldığında sunucu, pinleri başlangıç durumuna geri döndürür.

Pin çoklama istemcileri için protokol açıklaması

Bu bölüm, bir istemcinin pin çoklama işlevini nasıl kullandığını açıklar. Bu, SerCx ve SpbCx denetleyici sürücüleri için geçerli değildir; çünkü çerçeveler bu protokolü denetleyici sürücüleri adına uygular.

Kaynakları ayrıştırma

WDF sürücüsüMsftFunctionConfig() yordamında kaynakları alır. MsftFunctionConfig kaynakları aşağıdaki alanlarla tanımlanabilir:

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

Bir EvtDevicePrepareHardware() yordam, MsftFunctionConfig kaynaklarını aşağıdaki gibi ayıklayabilir:

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;
}

Kaynakları ayırma ve tahsis etme

Bir istemci pinleri çoklamak istediğinde, MsftFunctionConfig kaynağını ayırtır ve onaylar. Aşağıdaki örnekte, bir istemcinin MsftFunctionConfig kaynaklarını nasıl ayırıp işleyebileceği gösterilmektedir.

_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;
}

Sürücü WDFIOTARGET'i daha sonra kapatılabilmesi için bağlam alanlarından birinde depolamalıdır. Sürücü muxing yapılandırmasını serbest bırakmaya hazır olduğunda, WDFIOTARGET'i yeniden kullanmak istiyorsanız WdfObjectDelete() veya WdfIoTargetClose() çağrısı yaparak kaynak tutamacını kapatması gerekir.

    WdfObjectDelete(resourceHandle);

İstemci kaynak tutamacını kapattığında, pinler başlangıçtaki çoklama durumlarına geri döndürülür ve artık farklı bir istemci tarafından alınabilir.

Pin çoklama sunucuları için protokol açıklaması

Bu bölümde, pin muxing sunucusunun işlevselliğini istemcilere nasıl sunduğu açıklanmaktadır. Çerçeve bu protokolü istemci sürücüleri adına uyguladığından bu, miniport sürücüleri için geçerli GpioClx değildir. İstemci sürücülerinde GpioClx pin muxing'in nasıl desteklenmesiyle ilgili ayrıntılar için bkz. GpioClx İstemci Sürücüleri'nde muxing desteği uygulama.

IRP_MJ_CREATE isteklerini işleme

İstemciler, bir pin çoklama kaynağını ayırmak istediklerinde bu kaynak için bir tanıtıcı açar. Bir pin çoklama sunucusu, kaynak merkezinden yeniden ayrıştırma işlemi aracılığıyla IRP_MJ_CREATE isteklerini alır. IRP_MJ_CREATE isteğinin sondaki yol bileşeni, onaltılık biçimde 64 bitlik bir tamsayı olan kaynak hub kimliğini içerir. Sunucu, dosya adından resource hub kimliğini çıkarmak için reshub.h içindeki RESOURCE_HUB_ID_FROM_FILE_NAME() öğesini kullanmalı ve MsftFunctionConfig() tanımlayıcısını elde etmek için resource hub’a IOCTL_RH_QUERY_CONNECTION_PROPERTIES göndermelidir.

Sunucu tanımlayıcıyı doğrulamalı ve tanımlayıcıdan paylaşım modunu ve sabitleme listesini ayıklamalıdır. Daha sonra pinler için paylaşım arbitrajı yapmalı ve başarılı olursa, isteği tamamlamadan önce pinleri rezerve edilmiş olarak işaretlemelidir.

Paylaşım tahkimi, pin listesindeki her pin için paylaşım tahkimi başarılı olursa genel olarak başarılı olur. Her pin aşağıdaki gibi rastgele oluşturulmalıdır:

  • Pin zaten ayrılmamışsa, paylaşım arbitrajı başarıyla tamamlanır.
  • Pin zaten özel olarak ayrılmışsa, paylaşım tahkimi başarısız olur.
  • Pin zaten paylaşımlı olarak ayrılmışsa,
    • ve gelen istek paylaşılırsa, paylaşım arabuluculuğu başarılı olur.
    • ve gelen istek münhasırdır, paylaşım tahkimi başarısız olur.

Paylaşım arbitrajı başarısız olursa, istek STATUS_GPIO_INCOMPATIBLE_CONNECT_MODE ile tamamlanmalıdır. Tahkim paylaşımı başarılı olursa, istek STATUS_SUCCESS ile tamamlanmalıdır.

Gelen isteğin paylaşım modunun IrpSp-Parameters.Create.ShareAccess> yerine MsftFunctionConfig tanımlayıcısından alınması gerektiğini unutmayın.

IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS isteklerinin işlenmesi

İstemci, bir tanıtıcı açarak bir MsftFunctionConfig kaynağını başarıyla rezerve ettikten sonra, sunucudan gerçek donanım çoklayıcı yapılandırma işlemini gerçekleştirmesini talep etmek için IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS gönderebilir. Sunucu IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS aldığında, pin listesindeki her pin için

  • PNP_FUNCTION_CONFIG_DESCRIPTOR yapısının PinConfiguration üyesinde belirtilen çekme modunu donanıma ayarlayın.
  • Pini, PNP_FUNCTION_CONFIG_DESCRIPTOR yapısının FunctionNumber üyesi tarafından belirtilen işleve ayarlayın.

Sunucu daha sonra isteği STATUS_SUCCESS ile tamamlamalıdır.

FunctionNumber'ın anlamı sunucu tarafından tanımlanır ve MsftFunctionConfig tanımlayıcısının, sunucunun bu alanı nasıl yorumladığı bilgisi ile yazıldığı anlaşılmaktadır.

Tanıtıcının kapatılması durumunda sunucunun, pinleri IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS alındığı sırada içinde bulundukları yapılandırmaya geri döndürmesi gerekeceğini unutmayın; bu nedenle sunucunun, pinleri değiştirmeden önce pinlerin durumunu kaydetmesi gerekebilir.

IRP_MJ_CLOSE isteklerini işleme

İstemci artık bir muxing kaynağına ihtiyaç duymadığında, tanıtıcısını kapatır. Bir sunucu IRP_MJ_CLOSE isteği aldığında, pinleri IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS alındığında bulundukları duruma geri döndürmesi gerekir. İstemci hiçbir zaman IOCTL_GPIO_COMMIT_FUNCTION_CONFIG_PINS göndermediyse herhangi bir işlem yapılması gerekmez. Sunucu daha sonra pinleri paylaşım arbitrajı açısından kullanılabilir olarak işaretlemeli ve isteği STATUS_SUCCESS ile tamamlamalıdır. IRP_MJ_CLOSE işlenmesini IRP_MJ_CREATE işlenmesiyle uygun şekilde eşzamanladığınızdan emin olun.

ACPI tabloları için yazma yönergeleri

Bu bölümde, istemci sürücülerine muxing kaynaklarının nasıl sağlandığı açıklanır. MsftFunctionConfig() kaynaklarını içeren tabloları derlemek için Microsoft ASL derleyicisinin 14327 veya sonraki bir sürümüne ihtiyaç duyacağınızı unutmayın. MsftFunctionConfig() kaynakları, pin muxing istemcilerine donanım kaynakları olarak sağlanır. MsftFunctionConfig() kaynaklar, pin çoğullama değişiklikleri gerektiren sürücülere sağlanmalıdır; bunlar genellikle SPB ve seri denetleyici sürücüleridir. Ancak çoğullama yapılandırmasını denetleyici sürücüsü yönettiğinden, SPB ve seri çevre birimi sürücülerine sağlanmamalıdır. MsftFunctionConfig() ACPI makro aşağıdaki gibi tanımlanır:

  MsftFunctionConfig(Shared/Exclusive
                PinPullConfig,
                FunctionNumber,
                ResourceSource,
                ResourceSourceIndex,
                ResourceConsumer/ResourceProducer,
                VendorData) { Pin List }

  • Paylaşılan/Özel Kullanım – Özel kullanım ise, bu pin aynı anda yalnızca tek bir istemci tarafından alınabilir. Kaynak paylaşılıyorsa, birden çok istemci kaynağı edinebilir. Birden çok koordine edilmemiş istemcinin değiştirilebilir bir kaynağa erişmesine izin vermek veri yarışlarına ve dolayısıyla öngörülemeyen sonuçlara neden olabileceğinden bunu her zaman özel olarak ayarlayın.
  • PinPullConfig – bir türü
    • PullDefault – SoC tarafından tanımlanan güç verildiğindeki varsayılan çekme yapılandırmasını kullanın
    • PullUp – çekme direncini etkinleştirme
    • PullDown – aşağı çekme direncini etkinleştirme
    • PullNone – tüm çekme dirençlerini devre dışı bırakın
  • FunctionNumber – mux içine programlanacak işlev numarası.
  • ResourceSource – Pin çoklama sunucusunun ACPI ad alanı yolu
  • ResourceSourceIndex – bunu 0 olarak ayarlayın
  • ResourceConsumer/ResourceProducer – bunu ResourceConsumer olarak ayarlayın
  • VendorData – anlamı pin çoklama sunucusu tarafından tanımlanan isteğe bağlı ikili veri. Bu genellikle boş bırakılmalıdır
  • Pin Listesi: Yapılandırmanın uygulandığı pin numaralarının virgülle ayrılmış listesi. Pin karıştırma sunucusu bir GpioClx sürücüsü olduğunda, bunlar GPIO pin numaralarıdır ve GpioIo tanımlayıcısında pin numaralarıyla aynı anlama gelir.

Aşağıdaki örnekte, I2C denetleyici sürücüsüne nasıl MsftFunctionConfig() kaynağı sağlanabileceği gösterilmektedir.

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)
    }
}

Bir denetleyici sürücüsü için genellikle gereken bellek ve kesme kaynaklarına ek olarak, bir MsftFunctionConfig() kaynağı da belirtilir. Bu kaynak, I2C denetleyici sürücüsünün \_SB.GPIO0’daki cihaz düğümü tarafından yönetilen 2 ve 3 numaralı pinleri, pull-up direnci etkinleştirilmiş olarak 4. işleve ayarlamasını sağlar.

GpioClx istemci sürücülerinde muxing desteğini destekleme

GpioClx, pin muxing'i yerleşik olarak destekler. GpioClx miniport sürücüleri ("GpioClx istemci sürücüleri" olarak da adlandırılır), GPIO denetleyici donanımını sürücü. Windows 10 derleme 14327 itibarıyla GpioClx miniport sürücüleri iki yeni DDI uygulayarak pin muxing desteği ekleyebilir:

  • CLIENT_ConnectFunctionConfigPins – belirtilen çoklama yapılandırmasını uygulaması için miniport sürücüsüne komut vermek üzere GpioClx tarafından çağrılır.
  • CLIENT_DisconnectFunctionConfigPins – çoklama yapılandırmasını geri almak için miniport sürücüsüne komut vermek üzere GpioClx tarafından çağrılır.

Bu yordamların açıklaması için bkz. GpioClx Olay Geri Çağırma İşlevleri .

Bu iki yeni DDI'ye ek olarak, mevcut DDI'ler pin muxing uyumluluğu için denetlenmelidir:

  • CLIENT_ConnectIoPins/CLIENT_ConnectInterrupt – CLIENT_ConnectIoPins, GpioClx tarafından miniport sürücüsüne bir dizi pini GPIO girişi veya çıkışı için yapılandırmasını bildirmek amacıyla çağrılır. GPIO, MsftFunctionConfig ile birbirini dışlar, yani GPIO ve MsftFunctionConfig için aynı anda hiçbir zaman bir pin bağlanmayacak. Pinin varsayılan işlevinin GPIO olması gerekmediğinden, ConnectIoPins çağrıldığında pin GPIO'ya katılmış olmayabilir. Pini GPIO GÇ için hazır hale getirmek için gereken tüm işlemleri gerçekleştirmek için ConnectIoPins gereklidir. Bu işlemler arasında muxing işlemleri de bulunur. CLIENT_ConnectInterrupt benzer şekilde davranmalıdır, çünkü kesintiler GPIO girişinin özel bir durumu olarak düşünülebilir.
  • CLIENT_DisconnectIoPins/CLIENT_DisconnectInterrupt – PreserveConfiguration bayrağı belirtilmediği sürece bu yordam, CLIENT_ConnectIoPins/CLIENT_ConnectInterrupt çağrıldığında bulundukları duruma pin döndürmelidir. Pinlerin yönünü varsayılan durumlarına döndürmenin yanı sıra, miniport ayrıca her pinin çoklama durumunu _Connect yordamı çağrıldığında içinde bulunduğu duruma geri döndürmelidir.

Örneğin, bir pinin varsayılan muxing yapılandırmasının UART olduğunu ve pinin GPIO olarak da kullanılabileceğini varsayalım. GPIO için pini bağlamak amacıyla CLIENT_ConnectIoPins çağrıldığında, pin GPIO olarak yapılandırılmalıdır; CLIENT_DisconnectIoPins çağrıldığında ise pin yeniden UART olarak yapılandırılmalıdır. Genel olarak, Bağlantı kesme yordamları, Connect yordamları tarafından yapılan işlemleri geri almalıdır.

SpbCx ve SerCx denetleyici sürücülerinde muxing desteği

Windows 10 derleme 14327'den itibaren, SpbCx ve SerCx çerçeveleri, SpbCx ve SerCx denetleyici sürücülerinin, denetleyici sürücülerinin kendilerinde herhangi bir kod değişikliği gerekmeksizin pin çoğullama istemcileri olmasını sağlayan yerleşik pin çoğullama desteği içerir. Uzantıya göre, muxing özellikli SpbCx/SerCx denetleyici sürücüsüne bağlanan herhangi bir SpbCx/SerCx çevre birimi sürücüsü pin muxing etkinliğini tetikler.

Aşağıdaki diyagramda bu bileşenlerin her biri arasındaki bağımlılıklar gösterilmektedir. Gördüğünüz gibi, pin çoklama, SerCx ve SpbCx denetleyici sürücülerini, çoklamadan genellikle sorumlu olan GPIO sürücüsüne bağımlı hâle getirir.

Pin çoklama bağımlılığı

Cihaz başlatıldığında, SpbCx ve SerCx çerçeveleri, cihaza donanım kaynağı olarak sağlanan tüm MsftFunctionConfig() kaynaklarını ayrıştırır. Ardından SpbCx/SerCx, pin muxing kaynaklarını isteğe bağlı olarak alır ve serbest bırakır.

SpbCx, istemci sürücüsünün EvtSpbTargetConnect() geri çağırmasını çağırmadan hemen önce IRP_MJ_CREATE işleyicisinde pin muxing yapılandırmasını uygular. Muxing yapılandırması uygulanamadıysa denetleyici sürücüsünün EvtSpbTargetConnect() geri çağırması çağrılmaz. Bu nedenle, bir SPB denetleyici sürücüsü, EvtSpbTargetConnect() çağrıldığında pinlerin SPB işlevine çoklanmış olduğunu varsayabilir.

SpbCx, denetleyici sürücüsünün EvtSpbTargetDisconnect() geri çağırmasını çağırdıktan hemen sonra IRP_MJ_CLOSE işleyicisinde pin muxing yapılandırmasını geri alır. Sonuç olarak, bir çevre birimi sürücüsü SPB denetleyici sürücüsüne bir tutamaç açtığında pinler SPB işlevine çoklanır; çevre birimi sürücüsü tutamacını kapattığında ise SPB işlevinden çıkarılır.

SerCx benzer şekilde davranır. SerCxdenetleyici sürücüsünün MsftFunctionConfig() geri çağrısını çağırmadan hemen önce IRP_MJ_CREATE işleyicisindeki tüm kaynakları alır ve denetleyici sürücüsünün EvtSerCx2FileClose geri çağırmasını başlattıktan hemen sonra tüm kaynakları IRP_MJ_CLOSE işleyicisinde serbest bırakır.

SerCx ve SpbCx denetleyici sürücüleri için dinamik pin çoklamanın anlamı, belirli zamanlarda pinlerin SPB/UART işlevinden başka bir işleve çoklanmasına dayanabilmeleri gerektiğidir. Denetleyici sürücülerinin, pinlerin EvtSpbTargetConnect() veya EvtSerCx2FileOpen() çağrılana kadar çoklanmayacağını varsayması gerekir. Aşağıdaki geri çağırma işlevleri sırasında pinlerin SPB/UART işlevine çoklanmış olması gerekmez. Aşağıdakiler tam bir liste değildir, ancak denetleyici sürücüleri tarafından uygulanan en yaygın PNP yordamlarını temsil eder.

  • DriverEntry
  • EvtDriverDeviceAdd
  • EvtDevicePrepareHardware/EvtDeviceReleaseHardware
  • EvtDeviceD0Entry/EvtDeviceD0Exit

Verification

Rhproxy'yi test etmeye hazır olduğunuzda aşağıdaki adım adım yordamı kullanmak yararlı olur.

  1. Her SpbCx, GpioClxve denetleyici sürücüsünün yüklendiğini ve SerCx düzgün çalıştığını doğrulayın
  2. rhproxy Bunun sistemde mevcut olduğunu doğrulayın. bazı Windows sürümleri ve derlemeleri buna sahip değildir.
  3. ACPITABL.dat kullanarak rhproxy düğümünüzü derleyin ve yükleyin
  4. rhproxy cihaz düğümünün mevcut olduğunu doğrulayın
  5. rhproxy yüklendiğini ve başladığını doğrulayın
  6. Beklenen cihazların kullanıcı moduna sunulduğundan emin olun
  7. Komut satırından her cihazla etkileşim kurabildiğinizi doğrulayın
  8. UWP uygulamasından her cihazla etkileşim kurabildiğinizi doğrulayın
  9. HLK testleri çalıştırma

Denetleyici sürücülerini doğrulama

Rhproxy sistemdeki diğer cihazları kullanıcı modunda kullanıma sunar, ancak bu cihazlar zaten çalışıyorsa çalışır. İlk adım, kullanıma açmak istediğiniz I2C, SPI, GPIO denetleyicileri olan bu cihazların zaten çalıştığını doğrulamaktır.

Komut isteminde çalıştırın

devcon status *

Çıktıya bakın ve ilgili tüm cihazların başlatıldığını doğrulayın. Bir cihazın sorun kodu varsa, bu cihazın neden yüklenmediğini belirleyip sorunu gidermeniz gerekir. İlk platform getirme sırasında tüm cihazların etkinleştirilmesi gerekir. , SpbCxveya GpioClx denetleyici sürücülerinin sorunlarını gidermek SerCxbu belgenin kapsamı dışındadır.

Rhproxy'nin sistemde mevcut olduğunu doğrulayın

Hizmetin sistemde mevcut olduğunu rhproxy doğrulayın.

reg query HKEY_LOCAL_MACHINE\SYSTEM\ControlSet001\Services\rhproxy

İlgili kayıt defteri anahtarı yoksa, sisteminizde rhproxy bulunmuyor demektir. Rhproxy, IoT Core'un tüm derlemelerinde ve Windows Enterprise'in 15063 ve sonraki derlemelerinde mevcuttur.

ACPITABL.dat ile ASL derleme ve yükleme

Artık rhproxy ASL düğümü oluşturduğunuza göre derleme ve yükleme zamanı geldi. Rhproxy düğümünü sistem ACPI tablolarına eklenebilen tek başına bir AML dosyasına derleyebilirsiniz. Alternatif olarak, sisteminizin ACPI kaynaklarına erişiminiz varsa rhproxy düğümünü doğrudan platformunuzun ACPI tablolarına ekleyebilirsiniz. Ancak, ilk başlatma sırasında ACPITABL.dat kullanmak daha kolay olabilir.

  1. yourboard.asl adlı bir dosya oluşturun ve RHPX cihaz düğümünü bir DefinitionBlock içine yerleştirin:

    DefinitionBlock ("ACPITABL.dat", "SSDT", 1, "MSFT", "RHPROXY", 1)
    {
        Scope (\_SB)
        {
            Device(RHPX)
            {
            ...
            }
        }
    }
    
  2. WDK dosyasını indirin ve asl.exe konumunda C:\Program Files (x86)\Windows Kits\10\Tools\x64\ACPIVerify bulun

  3. ACPITABL.dat oluşturmak için aşağıdaki komutu çalıştırın:

    asl.exe yourboard.asl
    
  4. Sonuçta elde edilen ACPITABL.dat dosyasını test edilen sisteminizdeki c:\windows\system32 dosyasına kopyalayın.

  5. Test edilen sisteminizde test imzalamayı açın:

    bcdedit /set testsigning on
    
  6. Test altındaki sistemi yeniden başlatın. Sistem, ACPITABL.dat içinde tanımlanan ACPI tablolarını sistem üretici yazılımı tablolarına ekler.

rhproxy aygıt düğümünün mevcut olduğunu doğrulayın

Rhproxy cihaz düğümünü numaralandırmak için aşağıdaki komutu çalıştırın.

devcon status *msft8000

Devcon çıkışı, cihazın mevcut olduğunu göstermelidir. Cihaz düğümü yoksa ACPI tabloları sisteme başarıyla eklenmedi.

Rhproxy'nin yüklendiğini ve başlatıldığını doğrulayın

Rhproxy durumunu denetleyin:

devcon status *msft8000

Çıkış rhproxy'nin başlatıldığını gösteriyorsa rhproxy başarıyla yüklenmiş ve başlatılmıştır. Bir sorun kodu görürseniz araştırmanız gerekir. Bazı yaygın sorun kodları şunlardır:

  • Sorun 51 - CM_PROB_WAITING_ON_DEPENDENCY - Bağımlılıklarından biri yüklenemediğinden sistem rhproxy'yi başlatmıyor. Bu, rhproxy'ye geçirilen kaynakların geçersiz ACPI düğümlerine işaret ettiğini veya hedef cihazların başlatılmadığı anlamına gelir. İlk olarak, tüm cihazların başarıyla çalışıp çalışmadığını bir kez daha denetleyin (yukarıdaki 'Denetleyici sürücülerini doğrulama' bölümüne bakın). Ardından ASL'nizi bir kez daha denetleyin ve tüm kaynak yollarınızın (örneğin, \_SB.I2C1) doğru olduğundan emin olun ve DSDT'nizdeki geçerli düğümlere işaret edin.
  • Sorun 10 - CM_PROB_FAILED_START - Rhproxy başlatılamadı, büyük olasılıkla bir kaynak ayrıştırma sorunu nedeniyle. ASL'nizin üzerinden geçin ve DSD'deki kaynak dizinlerini bir kez daha denetleyin ve GPIO kaynaklarının artan pin numarası sırasına göre belirtildiğini doğrulayın.

Beklenen cihazların kullanıcı moduna sunulduğundan emin olun

Rhproxy çalıştığına göre kullanıcı modu tarafından erişilebilen cihaz arabirimleri oluşturmuş olması gerekir. Cihazları listelemek ve mevcut olduklarını görmek için birkaç komut satırı aracı kullanacağız.

https://github.com/ms-iot/samples deposunu klonlayın ve GpioTestTool, I2cTestTool, SpiTestTool ve Mincomm örneklerini derleyin. Test altındaki araçları cihazınıza kopyalayın ve cihazları listelemek için aşağıdaki komutları kullanın.

I2cTestTool.exe -list
SpiTestTool.exe -list
GpioTestTool.exe -list
MinComm.exe -list

Cihazlarınızın ve bunlara ait kolay anlaşılır adların listelendiğini görmeniz gerekir. Doğru cihazları ve anlaşılır adları görmüyorsanız, ASL'nizi tekrar kontrol edin.

Komut satırındaki her cihazı doğrulama

Sonraki adım, cihazları açmak ve cihazlarla etkileşime geçmek için komut satırı araçlarını kullanmaktır.

I2CTestTool örneği:

I2cTestTool.exe 0x55 I2C1
> write {1 2 3}
> read 3
> writeread {1 2 3} 3

SpiTestTool örneği:

SpiTestTool.exe -n SPI1
> write {1 2 3}
> read 3

GpioTestTool örneği:

GpioTestTool.exe 12
> setdrivemode output
> write 0
> write 1
> setdrivemode input
> read
> interrupt on
> interrupt off

MinComm (seri) örneği. Çalıştırmadan önce Rx'i Tx'e bağlayın:

MinComm "\\?\ACPI#FSCL0007#3#{86e0d1e0-8089-11d0-9ce4-08003e301f73}\0000000000000006"
(type characters and see them echoed back)

UWP uygulamasından her cihazı doğrulama

Cihazların UWP'den çalıştığını doğrulamak için aşağıdaki örnekleri kullanın.

HLK Testlerini Çalıştırma

Donanım Laboratuvar Seti (HLK) indirin. Aşağıdaki testler kullanılabilir:

HLK yöneticisinde rhproxy cihaz düğümünü seçtiğinizde, geçerli testler otomatik olarak seçilir.

HLK yöneticisinde "Resource Hub Proxy cihazı" öğesini seçin:

 Resource Hub proxy cihaz seçeneği seçili durumdayken Seçim sekmesini gösteren Windows Donanım Laboratuvar Seti ekran görüntüsü.

Ardından Testler sekmesine tıklayın ve I2C WinRT, Gpio WinRT ve Spi WinRT testleri'ni seçin.

 G P I O Win R T İşlevsel ve Stres Testleri seçeneğinin seçili olduğu Testler sekmesini gösteren Windows Donanım Laboratuvar Seti ekran görüntüsü.

Seçileni Çalıştır'a tıklayın. Teste sağ tıklayıp "Test Açıklaması" seçeneğine tıklayarak her testle ilgili diğer belgelere ulaşabilirsiniz.

Kaynaklar

Appendix

Ek A - Raspberry Pi ASL Listesi

Ayrıca bkz . Raspberry Pi 2 ve 3 Pin Eşlemeleri

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
                }
            })
        }
    }
}

Ek B - MinnowBoardMax ASL Listesi

Ayrıca bakın: MinnowBoard Max Pin Eşlemeleri

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 }},
                }
            })
        }
    }
}

Ek C - GPIO kaynakları oluşturmak için örnek PowerShell betiği

Raspberry Pi için GPIO kaynak bildirimlerini oluşturmak için aşağıdaki betik kullanılabilir:

$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;
}