Nota:
El acceso a esta página requiere autorización. Puede intentar iniciar sesión o cambiar directorios.
El acceso a esta página requiere autorización. Puede intentar cambiar los directorios.
Para proporcionar acceso a un controlador de modulación de ancho de pulso (PWM) que forma parte del SoC y está mapeado en la memoria al espacio de direcciones del SoC, debe escribir un controlador de modo núcleo. El controlador debe registrar la interfaz de clase de dispositivo del controlador PWM para que las aplicaciones para UWP puedan acceder a los dispositivos PWM expuestos por el sistema a través de las API de WinRT de PWM definidas en el espacio de nombres Windows.Devices.Pwm.
Nota:
Si tienes un módulo PWM de complemento a través de I2C, SPI o un controlador UART, puedes acceder al módulo desde una aplicación para UWP mediante las API definidas en el espacio de nombres Windows.Devices.Pwm y Windows.Devices.Pwm.Provider .
Un dispositivo PWM se abstrae en un único controlador y uno o varios pines. El control del controlador o los pines se realiza mediante los IOCTL definidos por PWM. Por ejemplo, un controlador de pantalla LCD envía tales solicitudes al controlador PWM para controlar el nivel de luz trasera LCD.
Generación de señales PWM multiproceso y multicanal con período configurable, polaridad y ciclo de trabajo, lo que permite las siguientes tareas:
- Conduce un motor servo.
- Controla una carga como un LED o un motor de corriente continua con escobillas.
- Genere una señal analógica.
- Genere un reloj preciso.
En este tema se describe,
Cómo habilitar el acceso de UWP a los dispositivos PWM expuestos por el sistema.
Cómo controlar las solicitudes IOCTL de PWM enviadas por una aplicación Win32 o un controlador en modo kernel de terceros.
Audiencia prevista
- Los OEM y los IHV están desarrollando un sistema con un controlador PWM en un SoC.
Última actualización
- Agosto de 2017
de la versión de Windows
- Versión de Windows 10
Las APIs importantes
Acerca de PWM
PWM describe la técnica básica para generar una onda de pulso rectangular con ancho de pulso modulado, lo que da lugar a la variación del valor medio de la forma de onda.
Una forma de onda PWM se puede clasificar por 2 parámetros: período de forma de onda (T) y ciclo de trabajo. La frecuencia de forma de onda (f) es la recíproca del período de forma de onda f=1/T. El ciclo de trabajo describe la proporción del tiempo "encendido" o "activo" con respecto al intervalo regular o "período" de tiempo; un ciclo de trabajo bajo corresponde a una potencia media de salida baja, ya que la potencia está desactivada durante la mayor parte del tiempo. El ciclo de servicio se expresa en porcentaje en el que 100% está totalmente activado, 0% está completamente desactivado, 50% está "Activo" 50% del tiempo.
Acceso al controlador PWM expuesto por el sistema y a los pines.
El controlador PWM debe registrarse
GUID_DEVINTERFACE_PWM_CONTROLLER como GUID de interfaz de dispositivo para exponer y acceder a dispositivos 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}"
Para registrar el GUID de la interfaz de dispositivo, el controlador debe llamar a WdfDeviceCreateDeviceInterface en la implementación del controlador de la función callback EVT_WDF_DRIVER_DEVICE_ADD. Después del registro, el sistema asigna un vínculo simbólico al controlador y a las patillas.
Una aplicación u otro controlador puede gestionar el controlador o los pines a través de las IOCTL definidas por PWM. Antes de enviar las IOCTLs, la aplicación o el controlador remitente deben abrir un identificador de archivo para el controlador y el pin especificando su vínculo simbólico. Esto requiere que el controlador se registre para los eventos de creación y cierre de archivos. Consulte (vínculo)
Este es un ejemplo de la ruta de acceso simbólica para el controlador:
\??\ACPI#FSCL000E#1#{60824b4c-eed1-4c9c-b49c-1b961461a819}
Del mismo modo, el formato de las patillas es el siguiente: el formato de la ruta de acceso es el siguiente:
<DeviceInterfaceSymbolicLinkName>\<PinNumber>
donde <PinNumber> es el índice basado en 0 del pin a abrir.
Este es un ejemplo de la ruta simbólica de ejemplo para los pines:
\??\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.
Para abrir el identificador de archivo, la aplicación debe llamar a las API de Configuration Manager (CM_Get_Device_Interface_*).
Una vez abierto el identificador de archivo, la aplicación puede enviar estas solicitudes llamando a la función DeviceIoControl. Consulte la sección PWM.
El controlador debe utilizar la rutina de soporte de PWM proporcionada, PwmParsePinPath, para analizar y validar las rutas de acceso de pines y extraer el número de pin.
Establecimiento de las propiedades de la interfaz de dispositivo
Para usar las API de WINRT de PWM desde aplicaciones para UWP, estas propiedades de interfaz de dispositivo deben establecerse.
DEVPKEY_DeviceInterface_Restricted
Según el modelo actual de acceso a dispositivos para UWP, se requiere establecer la propiedad de interfaz de dispositivo restringido en FALSE para conceder a las aplicaciones para UWP acceso a la interfaz de dispositivo PWM.
DEVPKEY_DeviceInterface_SchematicName (vínculo???)
Se requiere asignar un nombre esquemático a la interfaz de dispositivo PWM de dispositivos PWM conectados estáticamente para usar el método de fábrica PwmController.GetDeviceSelector(FriendlyName). El nombre esquemático es el nombre que se asigna al dispositivo PWM en los esquemas de diseño del sistema, por ejemplo, (PWM0, PWM_1, et.).). Se supone que los nombres de esquema son únicos en todo el sistema, pero eso no se aplica. Como mínimo, no debe haber 2 dispositivos PWM que tengan el mismo nombre esquemático; de lo contrario, el comportamiento de WinRT PwmController.GetDeviceSelector(FriendlyName) será indeterminado.
Las propiedades se pueden establecer de una de estas dos maneras:
Uso del archivo INF para el controlador PWM
Use la directiva AddProperty para establecer las propiedades del dispositivo. El archivo INF debe permitir establecer valores diferentes para la misma propiedad en uno o subconjunto de las instancias de dispositivo PWM. Este es un ejemplo de configuración de 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,,0No todos los diseños tienen la misma directiva para exponer el dispositivo PWM a UWP. Por ejemplo, la directiva podría ser permitir el acceso de UWP a un subconjunto de las instancias de dispositivo PWM. Exponer un subconjunto de los dispositivos PWM o asignar un valor de propiedad diferente a uno o un subconjunto de las instancias de dispositivo PWM requiere tener un identificador de hardware diferente para cada instancia de dispositivo PWM y hacer coincidir secciones INF de forma selectiva en función de la directiva.
Considere un diseño basado en SoC en el que hay cuatro instancias de dispositivo PWM idénticas (bloques IP) denominadas PWM0,...,PWM3 donde su ID de hardware asignado ACPI (_HID) es FSCL00E0 y su identificador único (_UID) es 0,...,3. Exponer todos los dispositivos PWM a UWP requerirá las secciones INF que establezcan el DEVPKEY_DeviceInterface_Restricted para que coincidan en el ID de hardware ACPI\FSCL00E0.
Esta manera de establecer las propiedades no requiere ningún cambio en el código de controlador. Esta es una opción más sencilla, ya que el mantenimiento de un archivo INF es más fácil que un archivo binario del controlador. El inconveniente es que este enfoque requiere un archivo INF adaptado a cada diseño.
Mediante programación en el controlador PWM
Un controlador PWM puede llamar a IoSetDeviceInterfacePropertyData para establecer las propiedades de la interfaz de dispositivo en su implementación de EVT_WDF_DRIVER_DEVICE_ADD después de crear y publicar la interfaz del dispositivo PWM. El controlador es responsable de decidir el valor que se va a asignar y la propiedad del dispositivo. Esa información se almacena normalmente en el ACPI del sistema para los diseños basados en SoC. El valor de cada propiedad de la interfaz del dispositivo se puede especificar en el método _DSD del nodo de dispositivo ACPI como propiedades del dispositivo. El controlador debe consultar the_DSD de ACPI, analizar los datos de propiedades del dispositivo, extraer el valor de cada propiedad y asignarle la interfaz de dispositivo.
Al configurar mediante programación las propiedades, el controlador y su archivo INF son portátiles entre diferentes diseños y, por lo tanto, en los BSPs donde el único cambio estaría en el DSDT ACPI que define cada nodo de dispositivo PWM. Sin embargo, leer y analizar bloques binarios ACPI es tedioso y requiere una gran cantidad de código que puede ser propenso a errores y vulnerabilidades, lo que da lugar a una superficie de error más grande.
Control de eventos de apertura y cierre de archivos
Un controlador PWM debe registrarse para eventos de creación y cierre de archivos mediante la implementación de las funciones de devolución de llamada EVT_WDF_DEVICE_FILE_CREATE y EVT_WDF_FILE_CLEANUP/EVT_WDF_FILE_CLOSE. En la implementación, el controlador debe realizar estas tareas:
Determine si la solicitud de creación es para un controlador o una clavija.
Si la solicitud es para un pin, el controlador debe analizar y validar la ruta de acceso del pin para solicitudes de creación de pin y asegurarse de que el número de pin solicitado esté dentro de los límites del controlador.
Conceda o deniegue el acceso al controlador y a las solicitudes de creación de pines.
Mantenga la integridad del estado de los controladores y pines según una máquina de estados bien definida.
En el conjunto anterior de tareas, la segunda tarea de validación se puede realizar en EVT_WDF_DEVICE_FILE_CREATE, como se indica a continuación:
Si el nombre de archivo asociado al objeto de archivo de solicitud es NULL, complete la solicitud con STATUS_INVALID_DEVICE_REQUEST.
Si el nombre de archivo asociado con el objeto de archivo de solicitud es una cadena vacía, entonces es una solicitud de creación de controlador; de lo contrario, es una solicitud de creación de pin.
Si se trata de una solicitud de creación de PIN, entonces:
Analice la ruta del pin en función del formato <DecimalName> y extraiga el número del pin llamando a PwmParsePinPath.
Si se produjo un error al analizar y validar la ruta de acceso del pin, complete la solicitud con STATUS_NO_SUCH_FILE.
Si el número de patilla es mayor o igual que el número de patillas del controlador, complete la solicitud con STATUS_NO_SUCH_FILE. Tenga en cuenta que el número de pin es un índice de base cero.
En caso contrario, continúe con el procesamiento de EVT_WDF_DEVICE_FILE_CREATE.
Este es un código de ejemplo que implementa los pasos de validación mencionados anteriormente para un controlador de 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
//
}
Uso compartido de controladores y pines
El modelo de distribución para el controlador y los pines sigue el patrón de múltiples lectores y un único escritor. Varios autores de llamada pueden abrir un controlador o pin para leerlo, pero solo un autor de llamada puede abrir ese controlador o pin para escritura a la vez.
Ese modelo se puede implementar mediante una combinación de marcas de acceso deseado y acceso compartido al abrir un manejador de archivo. El modelo de uso compartido de DDI opta por una semántica de uso compartido más sencilla en la que solo se usa la especificación de acceso deseado para controlar el acceso. La especificación de Acceso compartido no desempeña ningún papel en el modelo de uso compartido y no se respetará si se especifica al abrir un controlador o un pin.
En EVT_WDF_DEVICE_FILE_CREATE, se debe extraer y validar la solicitud de creación de Acceso deseado y Acceso compartido basado en el estado del controlador/pin o como se indica a continuación:
Si Share Access no es 0, deniegue el acceso y complete la solicitud con STATUS_SHARING_VIOLATION.
Si Desired Access es para solo lectura, conceda acceso y continúe procesando EVT_WDF_DEVICE_FILE_CREATE.
Si Desired Access es para escritura, haga lo siguiente:
Si el controlador o pin ya está abierto para escritura, deniegue el acceso y complete la solicitud con STATUS_SHARING_VIOLATION; si no, conceda acceso, marque el controlador o el pin como abierto para escritura y continúe procesando EVT_WDF_DEVICE_FILE_CREATE.
Este es un ejemplo que muestra cómo extraer el acceso deseado y el acceso compartido de una solicitud de creación.
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;
}
Independencia del controlador y del pin
El controlador y el pin tienen una relación de padre e hijo. Para abrir un pin, primero debe abrir su controlador principal. Otra manera de ver las patillas es como entidades independientes, donde el controlador principal proporciona solo un servicio al pin, que es establecer el período global de PWM para todos los pines contenidos en ese controlador.
Aquí se muestran algunos escenarios de ejemplo:
Acceso monoproceso
El proceso A puede abrir el pin, establecer su ciclo de trabajo, iniciarlo usando el período predeterminado del controlador y después abrir el controlador y establecer su período a petición. Es posible que nunca tenga que abrir el controlador si el período predeterminado es Correcto para la aplicación.
Un proceso puede tener varios hilos donde cada uno controla un pin diferente bajo el mismo controlador.
Acceso multiproceso:
Una utilidad de línea de comandos puede abrir el controlador con acceso de solo lectura para mostrar información en la consola. Al mismo tiempo, una tarea de UWP en segundo plano puede abrir el controlador para escritura y está controlando algunos LED con un solo pin.
Un controlador de pantalla en modo kernel que controla la luz de fondo del LCD a través de Pin0 mientras mantiene el controlador en posición para escritura y bloquea el periodo PWM. Al mismo tiempo, un servicio Win32 usa el período de PWM establecido por el controlador de pantalla y usa Pin1 para atenuar algunos LED para comunicar algún estado al usuario.
Tenga en cuenta que hay algunas implicaciones importantes de abrir y cerrar un controlador independientemente de sus pines. Para obtener más información, consulte la sección de máquinas de estado.
Máquinas de estado de controlador y pines
Definición de estado del controlador
| Característica de estado | Valor predeterminado | Descripción |
|---|---|---|
| Está abiertoFor-Write | Falso | False indica que el controlador está cerrado o está abierto para lectura; True indica que se abre para escritura. |
| Desired-Period | Período mínimo |
La siguiente máquina de estado del controlador se centra únicamente en el estado Is-Opened-For-Write. El valor de período deseado también se deja fuera porque no afecta al tipo de operación que se puede realizar en el controlador. Tenga en cuenta que cada vez que un controlador que se abre para escritura se cierra mediante el llamador que lo abrió para escribir, el controlador se restablece a sus valores predeterminados (período deseado predeterminado).
Definición de estado de anclaje
| Característica de estado | Valor predeterminado | Descripción |
|---|---|---|
| Se abreFor-Write | Falso | False indica que el pin está cerrado o está abierto para lectura; True indica que se abre para escritura. |
| Activo-Duty-Cycle | 0 | |
| Is-Started | Falso | Falso indica detenido; Verdadero indica iniciado. |
La máquina de estados del pin se centra en la combinación de los 2 estados: Is-Opened-For-Write e Is-Started. Otros estados del pin, como la polaridad y los ciclos de trabajo activos, se omiten porque sus valores no afectan al tipo de operaciones que se pueden realizar en el pin. Tenga en cuenta que cada vez que un pin que se abre para escritura es cerrado por quien lo abrió, el pin se reinicia a sus valores predeterminados (detenido, polaridad predeterminada y ciclo de trabajo activo). Tenga en cuenta también que la transición Set-Polarity en un estado con Is-Started = verdadero se omite porque es inválido en ese estado.
Cualquier transición que no se mencione para un estado determinado implica que dicha transición no es válida o no es posible y la solicitud correspondiente debe completarse con el estado de error adecuado.
Consideraciones de implementación para las transiciones de estado
En EVT_WDF_DEVICE_FILE_CREATE, el controlador debe conceder o denegar el acceso en función del acceso deseado de la solicitud de creación y el estado de aperturaFor-Write del controlador o pin.
Si la solicitud tiene acceso deseado de escritura y el controlador o pin ya está abierto para escritura, complete la solicitud con STATUS_SHARING_VIOLATION, de lo contrario, marque el controlador o pin como abierto para escritura (Is-Opened-For-Write = true), conceda acceso y continúe el procesamiento.
En este ejemplo se implementan los pasos de validación de acceso mencionados anteriormente para un controlador de EVT_WDF_DEVICE_FILE_CREATE cuando se omite la lógica de bloqueo necesaria para controlar las solicitudes simultáneas de creación de archivos:
// // 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; }En EVT_WDF_FILE_CLOSE/EVT_WDF_FILE_CLEANUP, el controlador debe mantener la integridad del estado del controlador o del pin.
Si el objeto de archivo pertenece a un controlador o patilla que abrió ese controlador o patilla para escritura, restablezca el controlador o patilla al estado predeterminado y desmarca ese controlador o patilla de abrirse para escritura (Is-Opened-For-Write = false).
En este ejemplo se implementan los pasos de validación de acceso mencionados anteriormente para un controlador de EVT_WDF_DEVICE_FILE_CLOSE cuando se omite la lógica de bloqueo necesaria para controlar las solicitudes simultáneas de cierre de archivos.
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."); } }
Solicitudes IOCTL de PWM
Las solicitudes IOCTL de PWM se envían mediante una aplicación u otro controlador y están destinadas a un controlador o a una patilla específica.
IOCTLs del controlador
- IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD
- IOCTL_PWM_CONTROLLER_GET_INFO
- IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD
Pin IOCTLs
- IOCTL_PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE
- IOCTL_PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE
- IOCTL_PWM_PIN_GET_POLARITY
- IOCTL_PWM_PIN_SET_POLARITY
- IOCTL_PWM_PIN_START
- IOCTL_PWM_PIN_STOP
- IOCTL_PWM_PIN_IS_STARTED
Para cada solicitud de IOCTL, el controlador PWM debe comprobar lo siguiente:
La operación solicitada (código IOCTL) es válida para el objeto de archivo asociado a la solicitud.
Solicite búferes de entrada y salida y asegúrese de que son al menos del tamaño mínimo esperado.
La validez de la operación solicitada en el estado actual del controlador o patilla.
La validez de los parámetros de entrada individuales. Por ejemplo: un período deseado de cero es un parámetro no válido para IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD.
Códigos de estado de finalización de IOCTL
El controlador PWM debe completar la solicitud IOCTL con el código de estado adecuado. Estos son los códigos de estado de finalización comunes. En general, un IOCTL que asigna una propiedad con un valor ya establecido siempre debe tener éxito. Por ejemplo, estableciendo exactamente el mismo período que ya está establecido, deteniendo un pin que ya está detenido, estableciendo la polaridad que ya está establecida, etc.
STATUS_NOT_SUPPORTED
La operación IOCTL solicitada no se implementa ni admite. Por ejemplo, es posible que algunos controladores no admitan establecer la polaridad de la señal de salida; en ese caso, IOCTL_PWM_PIN_SET_POLARITY se debería implementar, pero debería fallar con STATUS_NOT_SUPPORTED para la polaridad no predeterminada.
STATUS_INVALID_DEVICE_REQUEST
La solicitud IOCTL se envió al destino incorrecto. Por ejemplo, se envió una solicitud IOCTL del controlador mediante un identificador de archivo de anclaje.
STATUS_BUFFER_TOO_SMALL
El tamaño del búfer de entrada o salida es menor que el tamaño mínimo necesario del búfer para procesar la solicitud. Un controlador WDF que usa WdfRequestRetrieveInputBuffer o WdfRequestRetrieveOutputBuffer para recuperar y validar que los búferes de entrada y salida pueden devolver su estado de error correspondiente tal cual. Todos los ICTL con búferes de entrada o salida definidos para ellos tienen una estructura correspondiente que describe ese búfer, donde los nombres de estructura de entrada y salida tienen INPUT y _OUTPUT postfijo respectivamente. El tamaño mínimo del búfer de entrada es sizeof(PWMINPUT) mientras que el tamaño mínimo del búfer de salida es sizeof(PWM_OUTPUT).
| Código IOCTL | Descripción |
|---|---|
| IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD | Recupera el período de señal de salida efectivo del controlador de modulación de ancho de pulso (PWM), ya que se mediría en sus canales de salida. Devuelve un valor de PWM_CONTROLLER_GET_ACTUAL_PERIOD_OUTPUT. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_CONTROLADOR_OBTENER_INFO | Recupera información sobre un controlador de modulación de ancho de pulso (PWM). Esta información no cambia después de inicializar el controlador. El invocador debe pasar un búfer de salida que tenga exactamente el tamaño de la estructura PWM_CONTROLLER_INFO. El controlador deduce la versión de la estructura del tamaño del búfer de salida de la solicitud. Si el tamaño del búfer es menor que el tamaño de la versión más baja de la estructura, la solicitud se completa con un estado de finalización IOCTL de STATUS_BUFFER_TOO_SMALL. De lo contrario, el controlador asume la versión de estructura más alta que puede caber en el búfer de salida proporcionado y completa correctamente la solicitud. Una versión de PWM_CONTROLLER_INFO más reciente tiene un tamaño de bytes mayor que el de la versión anterior. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_CONTROLLER_ESTABLECER_PERIODO_DESEADO | Establece el período de señal de salida de un controlador de modulación de ancho de pulso (PWM) en un valor sugerido. El controlador PWM intenta establecer el período lo más cercano posible al valor solicitado en función de sus funcionalidades. El período efectivo se devuelve como salida de IOCTL. Más adelante se puede recuperar mediante IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD. El período deseado debe ser mayor que cero (0) y en el intervalo de períodos admitido por el controlador. Es decir, debe estar en el intervalo de MinimumPeriod y MaximumPeriod, ambos incluidos, que se pueden recuperar mediante IOCTL_PWM_CONTROLLER_GET_INFO. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE (Obtener el porcentaje del ciclo activo de trabajo del PIN PWM) | Recupera el porcentaje de ciclo de trabajo actual para un pin o canal. El código de control devuelve el porcentaje como una estructura PWM_PIN_GET_ACTIVE_DUTY_CYCLE_PERCENTAGE_OUTPUT. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_PIN_ESTABLECER_PORCENTAJE_CICLO_TRABAJO_ACTIVO | Establezca un valor de porcentaje de ciclo de trabajo deseado para el pin o canal del controlador. El código de control especifica el porcentaje como una estructura PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE_INPUT. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| Comando IOCTL para obtener la polaridad del pin PWM | Recupera la polaridad de señal actual del pin o canal. El código de control obtiene la polaridad de señal como una estructura PWM_PIN_GET_POLARITY_OUTPUT. La polaridad de señal es Activo Alto o Bajo activo, tal como se define en la enumeración PWM_POLARITY. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_PIN_SET_POLARITY | Establece la polaridad de señal del pin o canal. El código de control establece la polaridad de señal en función de una estructura PWM_PIN_SET_POLARITY_INPUT. La polaridad de señal es Activo Alto o Activo Bajo, tal como se define en el enum PWM_POLARITY. El cambio de polaridad solo se permite cuando se detiene el pin. Puede saber si la patilla está detenida mediante el código de control IOCTL_PWM_PIN_IS_STARTED. Si el pin se detiene y la polaridad solicitada es diferente de la polaridad actual del pin, la solicitud se completa con un valor de STATUS_INVALID_DEVICE_STATE. Cambiar la polaridad cuando se inicia un pin puede provocar fallos en algunos controladores de modulación de ancho de pulso (PWM). Si desea cambiar la polaridad, primero detenga el pin, cambie la polaridad y luego inicie el pin. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_PIN_START | Inicia la generación de la señal de modulación de ancho de pulso (PWM) en un pin o canal. Para comprobar si se inicia un pin, use IOCTL_PWM_PIN_IS_STARTED. La emisión de este IOCTL en un pin o canal que ya se ha iniciado no tiene ningún efecto, pero se realiza correctamente. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente. >
|
| IOCTL_PWM_PIN_STOP | Detiene la generación de señal de modulación de ancho de pulso (PWM) en un pin o canal. Para comprobar si se inicia un pin, use IOCTL_PWM_PIN_IS_STARTED. La emisión de este IOCTL en un pin o canal que ya está detenido no tiene ningún efecto, pero sí se considera exitosa. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
| IOCTL_PWM_PIN_ESTÁ_INICIADO | Recupera el estado de generación de señal para un pin o canal. Cada patilla tiene un estado de iniciado o detenido como una estructura de PWM_PIN_IS_STARTED_OUTPUT. El estado iniciado tiene un valor booleano de true. El estado detenido es falso. Por defecto, un pin se detiene al abrirse y regresa al estado detenido al cerrarse o soltarse. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|