Estoy desarrollando firmware para un dispositivo USB 2.0 Full Speed de baja potencia (12 Mbps) que utiliza un microcontrolador STM32F070CB . La fuente de reloj para el módulo USB será el oscilador externo de alta velocidad (HSE). Estoy usando STM32CubeMX con la versión 1.7.0 de STM32CubeF0 para generar el código base.
Para conservar nuestro presupuesto de energía, debemos apagar el HSE cuando el USB no está conectado. Estoy pensando que deberíamos hacer que el firmware retrase la detección de USB por parte del host hasta que el dispositivo esté listo, para que los eventos en el firmware sean más o menos así:
DPPU
) para activar la enumeración USB por parte del hostDPPU
(simular la desconexión física del host)PF0-OSC_IN
baja)¿Es lo anterior la forma correcta de hacerlo? ¿Todas las acciones son necesarias? ¿Están en el orden correcto?
¿ Necesito llamar a alguna función además USBD_DeInit()
de desactivar el USB?
¿Cómo puedo hacer que el dispositivo parezca desconectado en el host mientras está físicamente conectado? (es decir, debería desaparecer del Administrador de dispositivos de Windows). ¿Por qué las llamadas no HAL_PCD_DevDisconnect()
hacen que eso suceda?
En los siguientes párrafos, "conectar físicamente" significa conectar el cable USB al dispositivo y la PC host.
Esperaría que todas las llamadas MX_USB_DEVICE_Init()
tuvieran MX_USB_DEVICE_DeInit()
efecto de inmediato, es decir, que vería aparecer/desaparecer el dispositivo en el Administrador de dispositivos de Windows si se llamó a la función mientras el dispositivo está conectado físicamente. Sin embargo, he observado esto solo en la primera llamada a MX_USB_DEVICE_Init()
. Todas las llamadas a MX_USB_DEVICE_DeInit()
y las llamadas subsiguientes a MX_USB_DEVICE_Init()
no hacen que el dispositivo aparezca o desaparezca del Administrador de dispositivos de Windows hasta después de la reconexión física. (es decir, si está conectado, cuando se llama a la función, no hay cambios en el Administrador de dispositivos hasta después de desconectar/reconectar).
Según lo generado por STM32CubeMX:
/* USB Device Core handle declaration */
USBD_HandleTypeDef hUsbDeviceFS;
/* init function */
void MX_USB_DEVICE_Init(void)
{
/* Init Device Library,Add Supported Class and Start the library*/
USBD_Init(&hUsbDeviceFS, &FS_Desc, DEVICE_FS);
USBD_RegisterClass(&hUsbDeviceFS, &USBD_CDC);
USBD_CDC_RegisterInterface(&hUsbDeviceFS, &USBD_Interface_fops_FS);
USBD_Start(&hUsbDeviceFS);
}
Yo creé:
void MX_USB_DEVICE_DeInit(void)
{
HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)&hUsbDeviceFS.pData);
USBD_Stop (&hUsbDeviceFS);
USBD_DeInit(&hUsbDeviceFS);
}
No importa si llamo o cuándo HAL_PCD_DevDisconnect()
. Nunca he observado que el dispositivo desaparezca del Administrador de dispositivos de Windows mientras está conectado físicamente.
- ¿Cómo puedo hacer que el dispositivo parezca desconectado en el host mientras está físicamente conectado? (es decir, debería desaparecer del Administrador de dispositivos de Windows). ¿Por qué las llamadas no
HAL_PCD_DevDisconnect()
hacen que eso suceda?
Llamar HAL_PCD_DevDisconnect()
con los parámetros adecuados desconecta DPPU, por lo que el dispositivo desaparece del Administrador de dispositivos de Windows. El error en la pregunta es que en MX_USB_DEVICE_DeInit()
,
HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)&hUsbDeviceFS.pData);
debiera ser
HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)hUsbDeviceFS.pData);
(sin el operador de dirección &
).
Aquí hay una versión revisada de la función USB de-init:
void MX_USB_DEVICE_DeInit(void)
{
PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)hUsbDeviceFS.pData;
if (hpcd != NULL)
{
HAL_PCD_DevDisconnect(hpcd);
USBD_DeInit(&hUsbDeviceFS);
}
}
- ¿Es lo anterior la forma correcta de hacerlo? ¿Todas las acciones son necesarias? ¿Están en el orden correcto?
Cerca. Hay más en la configuración del reloj que simplemente activar o desactivar HSE.
STM32CubeMX genera SystemClock_Config()
. Puede usarlo como modelo para los pasos "Configurar los relojes del sistema" en la lista a continuación.
SYSCLKSOURCE
enPLLCLK
UsbClockSelection
en PLLDPPU
) para activar la enumeración de USB por host - MX_USB_DEVICE_Init()
hace todo estoDPPU
( HAL_PCD_DevDisconnect()
)USBD_DeInit()
)PF0-OSC_IN
es necesario conducir bajo)
- ¿ Necesito llamar a alguna función además
USBD_DeInit()
de desactivar el USB?
No, eso lo hace. Explore las pilas de llamadas y encontrará que USBD_DeInit()
llama todo lo que USBD_Stop()
hace y más.