適用於 SoC 上 PWM 模組的 PWM 驅動程式

若要提供脈衝寬度調變 (PWM) 控制器的存取權,該控制器屬於 SoC 的一部分,並記憶體對應至 SoC 位址空間,您必須撰寫核心模式驅動程式。 驅動程式必須註冊 PWM 控制器的裝置類別介面,讓 UWP 應用程式可以透過 Windows.Devices.Pwm 命名空間中定義的 PWM WinRT API 來存取系統公開的 PWM 裝置。

備註

如果您有透過 I2C、SPI 或 UART 控制器的附加元件 PWM 模組,您可以使用 Windows.Devices.PwmWindows.Devices.Pwm.Provider 命名空間中定義的 API,從 UWP 應用程式存取模組。

PWM 裝置抽象化為單一控制器和一或多個引腳。 控制控制器或針腳是透過 PWM 定義的 IOCTL 命令來完成。 例如,LCD 顯示驅動程式會將這類要求傳送至 PWM 驅動程式,以控制 LCD 背光層級。

多控制器和多通道 PWM 訊號生成,其週期、極性和佔空比均可設定,能夠執行以下任務:

  • 驅動伺服電機。
  • 驅動 LED 或直流有刷馬達等負載。
  • 產生類比訊號。
  • 生成一個精確的時鐘。

本主題說明,

  • 如何啟用對系統公開 PWM 裝置的 UWP 存取。

  • 如何處理 Win32 應用程式或第三方核心模式驅動程式所傳送的 PWM IOCTL 要求。

目標受眾

  • OEM 和 IHV 開發具有 SoC 上 PWM 控制器的系統。

最後更新

  • 2017 年 8 月

Windows 版本

  • Windows 10 版本

重要的應用程式介面

關於PWM

PWM 描述了產生具有調製脈寬的矩形脈衝波的基本技術,導致波形平均值的變化。

PWM 波形可分為 2 個參數:波形週期 (T) 和佔空比。 波形頻率 (f) 是波形週期 f=1/T 的倒數。 佔空比描述了“開啟”或“活動”時間相對於固定時間間隔或“週期”的比例;低佔空比對應於低輸出功率的平均值,因為大部分時間電源處於關閉狀態。 佔空比以百分比表示,其中 100% 完全開啟,0% 完全關閉,50% 50% 時間為「活動」。

驅動程式。

存取系統公開的 PWM 控制器和引腳

PWM 驅動程式必須註冊
GUID_DEVINTERFACE_PWM_CONTROLLER作為裝置介面 GUID,用於公開和存取 PWM 裝置。

// {60824B4C-EED1-4C9C-B49C-1B961461A819} 

DEFINE_GUID(GUID_DEVINTERFACE_PWM_CONTROLLER, 0x60824b4c, 0xeed1, 0x4c9c, 0xb4, 0x9c, 0x1b, 0x96, 0x14, 0x61, 0xa8, 0x19); 

#define GUID_DEVINTERFACE_PWM_CONTROLLER_WSZ L"{60824B4C-EED1-4C9C-B49C-1B961461A819}" 

若要註冊裝置介面 GUID,驅動程式必須在驅動程式的 EVT_WDF_DRIVER_DEVICE_ADD 回呼函式實作中呼叫 WdfDeviceCreateDeviceInterface。 註冊後,系統會為控制器和引腳分配一個符號鏈路。

應用程式或其他驅動程式可以透過 PWM 定義的 IOCTL 來控制控制器或針腳。 在發送 IOCTLs 之前,發送端應用程式或驅動程式必須藉由指定其符號連結,開啟控制器和接腳的檔案控制碼。 這需要驅動程式註冊檔案的建立和關閉事件。 參見(鏈接)

以下是控制器符號路徑的範例:

\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}  

同樣,引腳的格式如下:路徑的格式如下:

<DeviceInterfaceSymbolicLinkName>\<PinNumber>

其中 <PinNumber> 是要打開的引腳的以 0 為基礎的索引。

以下是引腳符號路徑的範例:

\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}\0 ; Opens pin 0 

\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}\0001 ; Opens pin 1 with the leading 0s have no effect.

若要開啟檔案控制碼,應用程式必須呼叫 Configuration Manager API (CM_Get_Device_Interface_*) 。

開啟檔案控制碼之後,應用程式可以呼叫 DeviceIoControl 函式來傳送這些要求。 請參閱PWM部分。

驅動程式應該使用提供的 PWM 支援常式 PwmParsePinPath 來剖解析和驗證針腳路徑,並擷取針腳號碼。

設定裝置介面屬性

若要從 UWP 應用程式使用 PWM WinRT API,必須設定這些 裝置介面屬性

  • DEVPKEY_DeviceInterface_Restricted

    根據目前的 UWP 裝置存取模型,必須將 [受限制的裝置介面] 屬性設定為 FALSE,才能讓 UWP 應用程式存取 PWM 裝置介面。

  • DEVPKEY_DeviceInterface_SchematicName (連結???)

    使用 PwmController.GetDeviceSelector(FriendlyName) 工廠方法需要將原理圖名稱指派給靜態連接的 PWM 裝置的 PWM 裝置介面。 原理圖名稱是系統設計原理圖中賦予 PWM 器件的名稱,例如 (PWM0、PWM_1 等)。 假設線路圖名稱在整個系統中是唯一的,但不會強制執行。 至少,不應該有 2 個具有相同線路圖名稱的 PWM 裝置,否則 WinRT PWM PwmController.GetDeviceSelector(FriendlyName) 行為將會是不確定的。

這些屬性可以透過以下兩種方式之一來設定:

  1. 使用 PWM 驅動程式的 INF 檔案

    使用 AddProperty 指示詞來設定裝置屬性。 INF 檔案應該允許在一個或子集的 PWM 裝置實例上為相同屬性設定不同的值。 以下是設定DEVPKEY_DeviceInterface_Restricted的範例。

    ;***************************************** 
    ; Device interface installation 
    ;***************************************** 
    
    [PWM_Device.NT.Interfaces] 
    AddInterface={60824B4C-EED1-4C9C-B49C-1B961461A819},,PWM_Interface 
    
    [PWM_Interface] 
    AddProperty=PWM_Interface_AddProperty 
    
    ; Set DEVPKEY_DeviceInterface_Restricted property to false to allow UWP access 
    ; to the device interface without the need to be bound with device metadata. 
    ; If Restricted property is set to true, then only applications which are bound 
    ; with device metadata would be allowed access to the device interface. 
    
    [PWM_Interface_AddProperty] 
    {026e516e-b814-414b-83cd-856d6fef4822},6,0x11,,0 
    

    並非所有設計都有相同的原則來將 PWM 裝置公開給 UWP。 例如,原則可能是允許 UWP 存取 PWM 裝置實例的子集。 公開 PWM 裝置的子集,或將不同的屬性值指派給 PWM 裝置實例的一個或子集,需要每個 PWM 裝置實例都有不同的硬體識別碼,並根據原則選擇性地比對 INF 區段。

    假設以 SoC 為基礎的設計,其中有四個名為 PWM0,...,PWM3 的相同 PWM 裝置實例 (IP 區塊),其中其 ACPI 指派的硬體識別碼 (_HID) 為FSCL00E0,其唯一識別碼 (_UID) 為 0,...,3。 將所有 PWM 裝置公開給 UWP 需要 INF 區段,以將 DEVPKEY_DeviceInterface_Restricted 設定為與硬體識別碼 ACPI\FSCL00E0 匹配。

    這種設定屬性的方式不需要對驅動程式程式碼進行任何變更。 這是較簡單的選項,因為服務 INF 檔案比驅動程式二進位檔更容易。 權衡的結果是此方法需要針對每個設計專用的 INF 檔案。

  2. 在 PWM 驅動程式中程式化地

    PWM 驅動程式可以在建立並發佈 PWM 裝置介面之後,呼叫 IoSetDeviceInterfacePropertyData,以在其 EVT_WDF_DRIVER_DEVICE_ADD 實作中設定裝置介面屬性。 驅動程式負責決定要指派的值和裝置屬性。 該資訊通常會儲存在 SoC 型設計的系統 ACPI 中。 每個裝置介面屬性的值都可以在每個 ACPI 裝置節點_DSD方法中指定為 [裝置屬性]。 驅動程式必須從 ACPI 查詢 the_DSD,剖析裝置屬性數據,擷取每個屬性的值,並將其指派到裝置介面。

    以程式化方式設定屬性,可讓驅動程式及其 INF 檔案在不同設計和 BSP 之間移植,其中唯一的變更是定義每個 PWM 裝置節點的 ACPI DSDT。 不過,讀取和剖析 ACPI 二進位區塊是一項繁瑣的作業,而且需要大量程式碼,這些程式碼容易發生錯誤和弱點,進而造成更大的錯誤表面。

處理檔案開啟/關閉事件

PWM 驅動程式必須藉由實作 EVT_WDF_DEVICE_FILE_CREATE 和 EVT_WDF_FILE_CLEANUP/EVT_WDF_FILE_CLOSE回呼函式來註冊檔案建立和關閉事件。 在實作中,驅動程式必須執行下列工作:

  1. 判斷建立請求是否針對控制器或針腳。

  2. 如果要求針腳,驅動程式必須解析並驗證建立針腳請求的針腳路徑,並確定要求的針腳號碼在控制器範圍內。

  3. 為控制器和引腳創建請求授予或拒絕存取權。

  4. 根據定義良好的狀態機維護控制器和針腳狀態完整性。

在上述一組任務中,可以在 EVT_WDF_DEVICE_FILE_CREATE 中執行第二個驗證任務,如下所示:

  1. 如果與要求檔案物件相關聯的檔名為空值,則使用 STATUS_INVALID_DEVICE_REQUEST 完成要求。

  2. 如果與要求檔案物件相關聯的檔名是空字串,則這是控制器建立請求,否則是腳位建立請求。

  3. 如果這是一個釘選創建請求,則:

    1. 根據格式 <DecimalName> 剖解析針腳路徑,並呼叫 PwmParsePinPath 來提取針腳號碼。

    2. 如果剖析和驗證引腳路徑失敗,請返回 STATUS_NO_SUCH_FILE 以完成請求。

    3. 如果針腳號碼大於或等於控制器針腳數,請使用 STATUS_NO_SUCH_FILE 完成要求。 請注意,引腳編號是從零開始的索引。

    4. 否則,繼續處理EVT_WDF_DEVICE_FILE_CREATE。

以下是一個實作前面提到的EVT_WDF_DEVICE_FILE_CREATE處理常式驗證步驟的範例程式碼:

EVT_WDF_DEVICE_FILE_CREATE PwmEvtDeviceFileCreate;

VOID 

PwmEvtDeviceFileCreate ( 
    WDFDEVICE WdfDevice, 
    WDFREQUEST WdfRequest, 
    WDFFILEOBJECT WdfFileObject 
    ) 
{ 

    UNICODE_STRING* filenamePtr = WdfFileObjectGetFileName(WdfFileObject); 
    IMXPWM_DEVICE_CONTEXT* deviceContextPtr = PwmGetDeviceContext(WdfDevice); 
    NTSTATUS status; 
    ULONG pinNumber; 

    // 
    // Parse and validate the filename associated with the file object 
    // 

    bool isPinInterface; 

    if (filenamePtr == nullptr) { 

        WdfRequestComplete(WdfRequest, STATUS_INVALID_DEVICE_REQUEST); 

        return; 

    } else if (filenamePtr->Length > 0) { 

        // 
        // A non-empty filename means to open a pin under the controller namespace 
        // 

        status = PwmParsePinPath(filenamePtr, &pinNumber); 

        if (!NT_SUCCESS(status)) { 

            WdfRequestComplete(WdfRequest, status); 

            return; 

        } 


        if (pinNumber >= deviceContextPtr->ControllerInfo.PinCount) { 

            WdfRequestComplete(WdfRequest, STATUS_NO_SUCH_FILE); 

            return; 

        } 


        isPinInterface = true; 

    } else { 

        // 
        // An empty filename means that the create is against the root controller 
        // 

        isPinInterface = false; 
    } 

    // 
    // Continue request processing here 
    // 
} 

控制器和引腳共享

控制器和針腳的共用模型會遵循多個讀取器、單一寫入器模式。 控制器/針腳可以開啟以供多個呼叫端讀取,但一次只有一個呼叫端可以開啟該控制器/針腳進行寫入。

開啟檔案句柄時,可以使用所需存取權和共用存取權旗標的組合來實作該模型。 DDI 共享模型選擇使用更簡單的共享語意,其中僅使用「所需的存取」規格來控制存取。 分享存取規格在分享模型中不具任何作用,如果在開啟控制器或針腳時指定,則不會被遵循。

在EVT_WDF_DEVICE_FILE_CREATE中,應根據控制器/引腳狀態來擷取並驗證創建請求的“所需存取權限”和“共用存取權限”,或者根據如下所示:

  1. 如果共用存取權不是0,則拒絕存取權,並使用STATUS_SHARING_VIOLATION完成要求。

  2. 如果所需存取權是唯讀的,請授與存取權並繼續處理EVT_WDF_DEVICE_FILE_CREATE。

  3. 如果所需存取權用於寫入,則:

如果控制器/針腳已開啟進行寫入操作,則拒絕存取,並使用 STATUS_SHARING_VIOLATION 完成要求,否則授予存取權限,將控制器或針腳標示為已開啟以供寫入,並繼續處理 EVT_WDF_DEVICE_FILE_CREATE。

以下範例顯示如何從建立請求中擷取所需存取權和共用存取權:

void 
PwmCreateRequestGetAccess( 
    _In_ WDFREQUEST WdfRequest, 
    _Out_ ACCESS_MASK* DesiredAccessPtr, 
    _Out_ ULONG* ShareAccessPtr 
    ) 
{ 

    NT_ASSERT(ARGUMENT_PRESENT(DesiredAccessPtr)); 

    NT_ASSERT(ARGUMENT_PRESENT(ShareAccessPtr)); 


    WDF_REQUEST_PARAMETERS wdfRequestParameters; 

    WDF_REQUEST_PARAMETERS_INIT(&wdfRequestParameters); 

    WdfRequestGetParameters(WdfRequest, &wdfRequestParameters); 


    NT_ASSERTMSG( 

        "Expected create request", 
        wdfRequestParameters.Type == WdfRequestTypeCreate); 


    *DesiredAccessPtr = 
        wdfRequestParameters.Parameters.Create.SecurityContext->DesiredAccess; 

    *ShareAccessPtr = wdfRequestParameters.Parameters.Create.ShareAccess; 
} 

控制器和引腳獨立性

控制器和引腳具有父子關係。 若要開啟引腳,您必須先開啟其父控制器。 另一種方法是將引腳視為獨立實體,其中其父控制器僅向引腳提供一項服務,該引腳為該控制器上包含的所有引腳設置全局 PWM 週期。

以下是一些範例案例:

  • 單一進程存取:

    • 製程 A 可以打開引腳,設置其佔空比,使用控制器默認週期啟動它,然後打開控制器並按需設置其週期。 如果應用程式的預設期間是正常的,則可能永遠不需要開啟控制器。

    • 進程可以有多個執行緒,每個執行緒都控制相同控制器下的不同針腳。

  • 多進程存取:

    • 指令行公用程式可以開啟具有唯讀存取權的控制器,以便向主控台顯示資訊。 同時,背景 UWP 任務可以開啟控制器來進行寫入,並使用單一引腳控制某些 LED。

    • 運行於核心模式的顯示驅動程式通過 Pin0 控制 LCD 背光,同時持續佔用控制器進行寫入操作並鎖定 PWM 週期。 同時,Win32 服務會使用顯示驅動程式所設定的 PWM 期間,並使用 Pin1 將某些 LED 調暗,以將某些狀態傳達給使用者。

請注意,將控制器的開啟和關閉與其針腳分開操作有一些重要的影響。 如需詳細資訊,請參閱狀態機一節。

控制器和引腳狀態機

控制器狀態定義

狀態特徵 預設值 說明
已開啟 -For-Write False 表示控制器已關閉或已開啟以供讀取;True 表示已開啟寫入。
Desired-Period 最小期間

控制器狀態機。

下列控制器狀態機僅以 Is-Opened-For-Write 狀態為中心。 所需的週期值也被省略,因為它不會影響可以在控制器上執行的操作類型。 請注意,當開啟寫入的控制器被呼叫端關閉時,控制器會重設為其預設值(包含預設所需週期)。

針腳狀態定義

狀態特徵 預設值 說明
已開啟-For-Write False 表示針腳已關閉或已開啟供讀取;True 表示已開啟供寫入。
主動 -Duty-Cycle 0
Is-Started False 表示已停止;True 表示已啟動。

引腳狀態機。

引腳狀態機以 2 種狀態的組合為中心:Is-Opened-For-Write 和 Is-Started。 其他引腳狀態(如極性和主動佔空工作週期)被排除在外,因為它們的值不會影響可以在引腳上執行的操作類型。 請注意,每當開啟寫入的針腳由開啟它進行寫入的呼叫端關閉時,該針腳將恢復到其預設值(停止狀態、預設極性和默認工作週期)。 請注意,狀態轉換中若Is-Started = true 時,Set-Polarity 會被省略,因為在該狀態下它無效。

針對給定狀態未提及的任何轉換都表示此類轉換無效或不可能,並且應以適當的錯誤狀態完成相應的要求。

狀態轉換的實作考量

  • 在 EVT_WDF_DEVICE_FILE_CREATE 中,驅動程式應依據建立請求中所需的存取權,以及控制器或針腳 Is-Opened-For-Write 狀態來授與或拒絕存取權,如下所示:

    如果要求具有所需的寫入存取權,且控制器/引腳已開啟以供寫入,則使用 STATUS_SHARING_VIOLATION 完成要求,否則將控制器/引腳標示為已開啟以供寫入 (Is-Opened-For-Write = true),授與存取權並繼續處理。

    此範例會實作先前提及的EVT_WDF_DEVICE_FILE_CREATE處理常式存取驗證步驟,其中省略處理並行檔案建立要求的必要鎖定邏輯:

    //
    // Verify request desired access
    //
    
    const bool hasWriteAccess = desiredAccess & FILE_WRITE_DATA;
    
    if (isPinInterface) {
        PWM_PIN_STATE* pinPtr = deviceContextPtr->Pins + pinNumber;
        if (hasWriteAccess) {
            if (pinPtr->IsOpenForReadWrite) {
                PWM_LOG_TRACE("Pin%lu access denied.", pinNumber);
                WdfRequestComplete(WdfRequest, STATUS_SHARING_VIOLATION);
                return;
            }
            pinPtr->IsOpenForReadWrite = true;
        }
        PWM_LOG_TRACE(
            "Pin%lu Opened. (IsOpenForReadWrite = %lu)",
            pinNumber,
            (pinPtr->IsOpenForReadWrite ? 1 : 0));
    
    } else {
        if (hasWriteAccess) {
            if (deviceContextPtr->IsControllerOpenForReadWrite) {
                PWM_LOG_TRACE("Controller access denied.");
                WdfRequestComplete(WdfRequest, STATUS_SHARING_VIOLATION);
                return;
            }
            deviceContextPtr->IsControllerOpenForReadWrite = true;
        }
        PWM_LOG_TRACE(
            "Controller Opened. (IsControllerOpenForReadWrite = %lu)",
            (deviceContextPtr->IsControllerOpenForReadWrite ? 1 : 0));
    }
    
    //
    // Allocate and fill a file object context
    //
    IMXPWM_FILE_OBJECT_CONTEXT* fileObjectContextPtr;
    {
        WDF_OBJECT_ATTRIBUTES wdfObjectAttributes;
        WDF_OBJECT_ATTRIBUTES_INIT_CONTEXT_TYPE(
            &wdfObjectAttributes,
            IMXPWM_FILE_OBJECT_CONTEXT);
    
        void* contextPtr;
        NTSTATUS status = WdfObjectAllocateContext(
                WdfFileObject,
                &wdfObjectAttributes,
                &contextPtr);
        if (!NT_SUCCESS(status)) {
            IMXPWM_LOG_ERROR(
                "WdfObjectAllocateContext(...) failed. (status = %!STATUS!)",
                status);
            WdfRequestComplete(WdfRequest, status);
            return;
        }
    
        fileObjectContextPtr =
            static_cast<IMXPWM_FILE_OBJECT_CONTEXT*>(contextPtr);
    
        NT_ASSERT(fileObjectContextPtr != nullptr);
        fileObjectContextPtr->IsPinInterface = isPinInterface;
        fileObjectContextPtr->IsOpenForWrite = hasWriteAccess;
        fileObjectContextPtr->PinNumber = pinNumber;
    }
    
  • 在EVT_WDF_FILE_CLOSE/EVT_WDF_FILE_CLEANUP中,驅動程式應該維護控制器/針腳狀態完整性。

    如果檔案物件屬於開啟該控制器/引腳進行寫入的控制器/引腳,則將控制器/引腳重設為預設狀態,並將該控制器/引腳標示為不再開啟以進行寫入(Is-Opened-For-Write = false)。

    此範例會實作先前提及的EVT_WDF_DEVICE_FILE_CLOSE處理常式存取驗證步驟,其中省略處理並行檔案關閉要求的必要鎖定邏輯。

    EVT_WDF_DEVICE_FILE_CLOSE PwmEvtFileClose;
    
    VOID
    PwmEvtFileClose (
        WDFFILEOBJECT WdfFileObject
        )
    {
        WDFDEVICE wdfDevice = WdfFileObjectGetDevice(WdfFileObject);
        PWM_DEVICE_CONTEXT* deviceContextPtr = PwmGetDeviceContext(wdfDevice);
        PWM_FILE_OBJECT_CONTEXT* fileObjectContextPtr = PwmGetFileObjectContext(WdfFileObject);
    
        if (fileObjectContextPtr->IsPinInterface) {
            if (fileObjectContextPtr->IsOpenForReadWrite) {
                const ULONG pinNumber = fileObjectContextPtr->PinNumber;
    
                NTSTATUS status = PwmResetPinDefaults(deviceContextPtr, pinNumber);
                if (!NT_SUCCESS(status)) {
                    PWM_LOG_ERROR(
                        "PwmResetPinDefaults(...) failed. "
                        "(pinNumber = %lu, status = %!STATUS!)",
                        pinNumber,
                        status);
                    //
                    // HW Error Recovery
                    //
                }
    
                NT_ASSERT(deviceContextPtr->Pins[pinNumber].IsOpenForReadWrite);
                deviceContextPtr->Pins[pinNumber].IsOpenForReadWrite = false;
            }
    
            PWM_LOG_TRACE("Pin%lu Closed.", fileObjectContextPtr->PinNumber);
    
        } else {
            if (fileObjectContextPtr->IsOpenForReadWrite) {
                NTSTATUS status = PwmResetControllerDefaults(deviceContextPtr);
                if (!NT_SUCCESS(status)) {
                    IMXPWM_LOG_ERROR(
                        "PwmResetControllerDefaults(...) failed. (status = %!STATUS!)",
                        status);
                    //
                    // HW Error Recovery
                    //  
                }
    
                NT_ASSERT(deviceContextPtr->IsControllerOpenForReadWrite);
                deviceContextPtr->IsControllerOpenForReadWrite = false;
            }
    
            PWM_LOG_TRACE("Controller Closed.");
        }
    }
    

PWM IOCTL 請求

PWM IOCTL 要求由應用程式或其他驅動程式發出,目標對象是控制器或特定針腳。

控制器 IOCTL

腳位 IOCTL

針對每個 IOCTL 要求,PWM 驅動程式必須驗證下列項目:

  1. 要求的作業 (IOCTL 程式代碼) 對要求相關聯的檔案物件有效。

  2. 要求輸入和輸出緩衝區,並確定它們至少為預期大小下限。

  3. 目前控制器/針腳狀態下所要求作業的有效性。

  4. 個別輸入參數的有效性。 例如:所需的週期為零是IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD的無效參數。

IOCTL 完成狀態碼

PWM 驅動程式必須使用適當的狀態碼完成 IOCTL 要求。 以下是常見的完成狀態碼。 一般而言,對於已設定值的屬性進行設定的 IOCTL 應該總是會成功。 例如,設定與已設定相同的週期、停止已停止的引腳、設定已設定的極性等等。

STATUS_NOT_SUPPORTED

未實作或支援要求的 IOCTL 作業。 例如,某些控制器可能不支援設定輸出信號的極性。在這種情況下,應該實作 IOCTL_PWM_PIN_SET_POLARITY,但對於非預設極性,會以 STATUS_NOT_SUPPORTED 失敗。

STATUS_INVALID_DEVICE_REQUEST

IOCTL 要求已傳送至錯誤的目標。 例如,控制器的 IOCTL 請求是使用固定檔案控制代碼傳送的。

STATUS_BUFFER_TOO_SMALL

輸入或輸出緩衝區大小小於處理要求所需的緩衝區大小下限。 使用 WdfRequestRetrieveInputBuffer 或 WdfRequestRetrieveOutputBuffer 來擷取和驗證輸入和輸出緩衝區的 WDF 驅動程式可以依原樣傳回其對應的錯誤狀態。 所有已定義輸入和/或輸出緩衝區的 IOCTL 都有對應的結構,可描述該緩衝區,其中輸入和輸出結構名稱 分別具有 INPUT 和 _OUTPUT 後置詞。輸入緩衝區最小大小為 sizeof(PWMINPUT),而輸出緩衝區最小大小為 sizeof(PWM_OUTPUT)。

IOCTL 代碼 說明
IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD (輸入/輸出控制碼_PWM控制器取得實際周期) 擷取脈衝寬度調節器 (PWM) 控制器的有效輸出訊號期間,因為它會在輸出通道上測量。 傳回PWM_CONTROLLER_GET_ACTUAL_PERIOD_OUTPUT值。 Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_CONTROLLER_GET_INFO 擷取脈衝寬度調節器 (PWM) 控制器的相關信息。 初始化控制器之後,這項資訊不會變更。

呼叫端應該傳遞輸出緩衝區,其大小完全符合PWM_CONTROLLER_INFO結構的大小。 驅動程式會從要求輸出緩衝區大小推斷結構的版本。

如果緩衝區大小小於最低結構版本的大小,則會使用 IOCTL 完成狀態 STATUS_BUFFER_TOO_SMALL 來完成要求。 否則,驅動程式會假設可以符合所提供輸出緩衝區的最高結構版本,並成功完成要求。

較新的PWM_CONTROLLER_INFO版本的位元組大小大於舊版的位元組大小

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD(設定期望的PWM週期控制器) 將脈衝寬度調節器 (PWM) 控制器的輸出訊號週期設定為建議的值。

PWM 控制器嘗試根據其功能設定盡可能接近請求值的週期。 IOCTL 輸出的結果為有效期間。 稍後可以使用IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD來擷取它。

所需的週期必須大於零 (0) 且在控制器支援的週期範圍內。 也就是說,它必須在 MinimumPeriod 和 MaximumPeriod(均含)的範圍內,可以使用 IOCTL_PWM_CONTROLLER_GET_INFO 來擷取。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。
  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_INVALID_PARAMETER (參數無效)
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE 擷取針腳或通道的目前工作週期百分比。 控制件程式代碼會以PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE_OUTPUT結構傳回百分比。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE(設定PWM引腳的啟動佔空比百分比) 設定控制器針腳或通道所需的工作週期百分比值。 控制程式代碼會將百分比指定為 PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE_INPUT 結構。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_GET_POLARITY 擷取針腳或通道的目前訊號極性。 控件程式代碼會以PWM_PIN_GET_POLARITY_OUTPUT結構的形式取得訊號極性。 訊號極性為 Active High 或 Active Low,如PWM_POLARITY列舉中所定義。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_SET_POLARITY 設定針腳或通道的訊號極性。 控件程式代碼會根據PWM_PIN_SET_POLARITY_INPUT結構來設定訊號極性。 訊號極性為高電平有效或低電平有效,如PWM_POLARITY枚舉中所定義。

只有在引腳停止時才允許改變極性。 您可以使用IOCTL_PWM_PIN_IS_STARTED控制碼來判斷引腳是否已停止。 如果針腳已停止,且所請求的極性與目前針腳極性不同,則請求將以 STATUS_INVALID_DEVICE_STATE 值完成。

在啟動引腳時更改極性可能會導致某些脈寬調變控制器出現毛刺。 如果要更改極性,請先停止引腳,更改極性,然後啟動引腳。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_INVALID_PARAMETER (參數無效)
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_START 開始在針腳或通道上產生脈衝寬度調節(PWM)訊號。 若要檢查是否已啟動針腳,請使用 IOCTL_PWM_PIN_IS_STARTED。

在已啟動的接腳或通道上發出此 IOCTL 不會造成任何影響,但仍會成功。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

>
  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_STOP 停止在針腳或通道上產生脈衝寬度調節(PWM)訊號。 若要檢查是否已啟動針腳,請使用 IOCTL_PWM_PIN_IS_STARTED。

在已停止的針腳或通道上發出此 IOCTL 沒有任何作用,但會成功。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL
IOCTL_PWM_PIN_IS_STARTED 擷取針腳或通道的訊號產生狀態。 每個針腳的狀態皆為啟動或停止,做為PWM_PIN_IS_STARTED_OUTPUT結構。 開始狀態的布林值為 true。 停止狀態為 (false)。

根據預設,針腳會在開啟時仍處於停止狀態,並在關閉或釋放時返回停止狀態。

Irp-IoStatus.Status> 會設定為下列清單中的其中一個值。

  • 狀態_成功
  • STATUS_NOT_SUPPORTED
  • STATUS_INVALID_DEVICE_REQUEST
  • STATUS_BUFFER_TOO_SMALL