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 la memoria asignada al espacio de direcciones soC, debe escribir un controlador en modo kernel. El controlador debe registrar la interfaz de clase de dispositivo del controlador PWM para que las aplicaciones para UWP puedan acceder al sistema dispositivos PWM expuestos a través de las API de WinRT de PWM definidas en el espacio de nombres Windows.Devices.Pwm.
Nota
Si tiene un módulo PWM de complemento a través de I2C, SPI o un controlador UART, puede 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 patillas. Controlar el controlador o las patillas se realiza a través de las ICTLs definidas por PWM. Por ejemplo, un controlador de pantalla LCD envía tales solicitudes al controlador PWM para controlar el nivel de retroiluminación 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.
- Conducir una carga como led o motor cepillado dc.
- Generar 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 objetivo
- Oem e IHD desarrollando un sistema con un controlador PWM en SoC.
Última actualización
- Agosto de 2017
Versión de Windows
- Versión de Windows 10
API 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 "on" o "Active" con respecto al intervalo regular o "Período" de tiempo; un ciclo de trabajo bajo corresponde a un promedio de baja potencia de salida, porque la energía está apagada durante la mayor parte del tiempo. El ciclo de trabajo se expresa en porcentaje en el que el 100 % está totalmente activado, el 0 % está totalmente desactivado, el 50 % es "Activo" 50 % del tiempo.
Acceso al controlador PWM expuesto por el sistema y a las patillas
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 de devolución de llamada de 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 controlar el controlador o las patillas a través de las ICTLs definidas por PWM. Antes de enviar las ITL, 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 que se va a abrir.
Este es un ejemplo de la ruta de acceso simbólica para las patillas:
\??\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 usar la rutina de compatibilidad de PWM proporcionada PwmParsePinPath para analizar y validar las rutas de acceso del pin y extraer el número de patilla.
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 esquematico 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 de esquema 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. Al menos, no debe haber 2 dispositivos PWM que tengan el mismo nombre esquematético; de lo contrario, el comportamiento pwmController.GetDeviceSelector(FriendlyName) de WinRT será no determinista.
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 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
No 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 id. de hardware diferente para cada instancia de dispositivo PWM y hacer coincidir secciones INF selectivamente en función de la directiva.
Considere un diseño basado en SoC donde 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. La exposición de todos los dispositivos PWM a UWP requerirá las secciones INF que establezcan el DEVPKEY_DeviceInterface_Restricted para que coincida con el ID de hardware ACPI\FSCL00E0.
Esta forma de establecer propiedades no requiere ningún cambio en el código del 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 personalizado para 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 de 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 interfaz de dispositivo se puede especificar en cada nodo de dispositivo ACPI _DSD método 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.
La configuración mediante programación de las propiedades hace que el controlador y su archivo INF sean portátiles entre diseños y, por tanto, BSP donde el único cambio estaría en el DSDT ACPI que define cada nodo de dispositivo PWM. Sin embargo, la lectura y el análisis de 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 crear y cerrar eventos de archivo mediante la implementación de EVT_WDF_DEVICE_FILE_CREATE y funciones de devolución de llamada 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 patilla.
Si la solicitud es para un pin, el controlador debe analizar y validar la ruta de acceso del pin para crear solicitudes de pin y asegurarse de que el número de patilla solicitado está dentro de los límites del controlador.
Conceda o deniegue el acceso al controlador y ancle solicitudes de creación.
Mantenga la integridad del estado de los controladores y anclajes según una máquina de estado 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 al objeto de archivo de solicitud es una cadena vacía, se trata de una solicitud de creación del controlador; de lo contrario, es una solicitud de creación de patillas.
Si se trata de una solicitud de creación de patillas, haga lo siguiente:
Analice la ruta de acceso del pin en función del formato <DecimalName> y extraiga el número de patilla llamando a PwmParsePinPath.
Si se produjo un error al analizar y validar la ruta de acceso de anclaje, 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 patilla es un índice de base cero.
En caso contrario, continúe procesando 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 patillas
El modelo de uso compartido para controladores y patillas sigue los múltiples lectores, un único patrón de escritor. Varios autores de llamadas pueden abrir un controlador o patilla para leerlo, pero solo un autor de llamada puede abrir ese controlador o patilla 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 identificador 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 rol en el modelo de uso compartido y no se respeta si se especifica al abrir un controlador o una patilla.
En EVT_WDF_DEVICE_FILE_CREATE, la solicitud create Desired Access y Share Access deben extraerse y validarse en función del estado del controlador o 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, deniega el acceso y complete la solicitud con STATUS_SHARING_VIOLATION, de lo contrario conceda acceso, marque el controlador o anclar como abierto para escribir y continúe procesando EVT_WDF_DEVICE_FILE_CREATE.
Este es un ejemplo que muestra cómo extraer El acceso deseado y Compartir acceso desde 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 de las patillas
El controlador y el pin tienen una relación de elementos primarios y secundarios. Para abrir un pin, primero debe abrir su controlador primario. Otra manera de ver los pines es como entidades independientes en las que su controlador primario proporciona solo un servicio al pin que establece el período de PWM global para todos los patillas contenidos en ese controlador.
Aquí se muestran algunos escenarios de ejemplo:
Acceso de proceso único:
El proceso A puede abrir el pin, establecer su ciclo de trabajo, iniciarlo con el período predeterminado del controlador y, posteriormente, 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 subprocesos en los que cada uno controle 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 para UWP en segundo plano puede abrir el controlador para escribir y está controlando algún LED con un solo pin.
Controlador de pantalla en modo kernel que controla la luz trasera LCD a través de Pin0 mientras mantiene presionado el controlador para escribir y bloquear el período PWM. Al mismo tiempo, un servicio Win32 usa el período PWM establecido por el controlador de pantalla y usa Pin1 para atenuar algún LED para comunicar algún estado al usuario.
Tenga en cuenta que hay algunas implicaciones importantes para abrir y cerrar un controlador independientemente de sus patillas. Para obtener más información, consulte la sección de máquinas de estado.
Máquinas de estado de controlador y anclaje
Definición de estado del controlador
Característica de estado | Valor predeterminado | Descripción |
---|---|---|
Se abre para escritura | False | False indica que el controlador está cerrado o está abierto para lectura; True indica que se abre para escritura. |
Desired-Period | MinimumPeriod |
La máquina de estado del controlador siguiente se centra solo en el estado Is-Opened-For-Write. El valor del 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 abierto para escritura se cierra mediante el autor de la llamada 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 abre para escritura | False | False indica que el pin está cerrado o está abierto para lectura; True indica que se abre para escritura. |
Ciclo de servicio activo | 0 | |
Is-Started | False | False indica detenido; True indica que se inició. |
La máquina de estado de anclaje se centra alrededor de la combinación de los 2 estados Is-Opened-For-Write e Is-Started. Otros estados de patillas, como la polaridad y los ciclos de servicio activos, se dejan fuera porque sus valores no afectan al tipo de operaciones que se pueden realizar en la patilla. Tenga en cuenta que cada vez que un pin que se abre para escribir se cierra mediante el autor de la llamada que lo abrió para escribir, el pin obtiene reposo en sus valores predeterminados (detenido, polaridad predeterminada y ciclo de servicio activo). Tenga en cuenta también que Set-Polarity transición en un estado con Is-Started = true se deja fuera porque no es vá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 de la solicitud de creación de acceso deseado y el estado Is-Opened-For-Write del controlador o anclaje como se indica a continuación:
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 en el que 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 pin.
Si el objeto de archivo pertenece a un controlador o patilla que abrió ese controlador o patilla para escritura, restablezca el controlador/pin al estado predeterminado y desmarca ese controlador/pin de que se abra 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 en el que 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 un pin específico.
IOCTLs del controlador
- IOCTL_PWM_CONTROLLER_GET_ACTUAL_PERIOD
- IOCTL_PWM_CONTROLLER_GET_INFO
- IOCTL_PWM_CONTROLLER_SET_DESIRED_PERIOD
Anclar ICTLs
- 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.
Validez de la operación solicitada en el estado actual del controlador o pin.
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 establece una propiedad con valor que ya está establecida siempre debe ser correcta. Ejemplo de enemigo, establecer exactamente el mismo período que ya está establecido, detener un pin que ya está detenido, establecer 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 la configuración de la polaridad de la señal de salida, en tal caso IOCTL_PWM_PIN_SET_POLARITY se debe implementar, pero se producirá un error 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 pin.
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 los búferes de entrada y salida puede devolver su estado de error correspondiente tal cual. Todas las ITL con búferes de entrada o salida definidos para ellos tienen una estructura correspondiente que describe ese búfer, donde los nombres de struct de entrada y salida tienen input y _OUTPUT postfix 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_CONTROLLER_GET_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 llamador 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 de estructura más baja, la solicitud se completa mediante un estado de finalización de 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 la solicitud correctamente. 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_SET_DESIRED_PERIOD | 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 una salida 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 | 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_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE | 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 de PWM_PIN_SET_ACTIVE_DUTY_CYCLE_PERCENTAGE_INPUT. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
IOCTL_PWM_PIN_GET_POLARITY | 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 Alta activa o Baja activa, tal y 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 de PWM_PIN_SET_POLARITY_INPUT. La polaridad de señal es Alta activa o Baja activa, tal y como se define en la enumeración PWM_POLARITY. El cambio de polaridad solo se permite cuando se detiene la patilla. Puede saber si el pin se detiene mediante el código de control IOCTL_PWM_PIN_IS_STARTED. Si la patilla se detiene y la polaridad solicitada es diferente de la polaridad del pin actual, la solicitud se completa con un valor de STATUS_INVALID_DEVICE_STATE. Cambiar la polaridad mientras se inicia una patilla puede provocar problemas en algunos controladores de modulación de ancho de pulso (PWM). Si desea cambiar la polaridad, detenga primero el pin, cambie la polaridad y, a continuación, inicie la patilla. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
IOCTL_PWM_PIN_START | Inicia la generación de señal de modulación de ancho de pulso (PWM) en un pin o canal. Para comprobar si se ha iniciado 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 sí lo hace 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 ha iniciado 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í lo hace correctamente. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|
IOCTL_PWM_PIN_IS_STARTED | 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 false. De forma predeterminada, se detiene un pin cuando se abre y vuelve al estado detenido cuando se cierra o se libera. Irp-IoStatus.Status> se establece en uno de los valores de la lista siguiente.
|