STM32 USB VCP bug

8

He estado trabajando en un proyecto durante las últimas dos semanas y la depuración de este problema se ha desarrollado durante toda la semana. Preguntándome si alguien puede ayudar, trataré de ser lo más explícito y claro posible.

Estoy intentando implementar un puerto de comunicación virtual USB en un microcontrolador basado en el STM32F302K8 (Cortex M4). He usado STM32CubMX para generar el código necesario para configurar un dispositivo USB de velocidad completa implementando una clase CDC. Mi dispositivo aparece tanto en Windows (Administrador de dispositivos) como en Linux. Soy capaz de implementar una función de eco simple basada en el código de ejemplo, pero cuando trato de usar la función USBD_CDC_SetTxBuffer para enviar datos a la PC, esto activa un Controlador de fallas. He reducido esto al hecho de que el campo UsbDeviceFS.pClass (que es necesario para USBD_CDC_SetTxBuffer) nunca se inicializa porque USBD_CDC_Init () nunca se llama en la inicialización del dispositivo USB.

He implementado soluciones a varios errores (incluido cambiar el tamaño del montón, corregir el indicador de transmisión en USBD_CDC_TransmitPacket y cambiar el tamaño de CDC_DATA_HS_MAX_PACKET_SIZE a 256 desde 512) en el código de ejemplo que figura en el código ST foro pero sigue teniendo el mismo error.

El código de configuración de mi dispositivo es

* 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);

}
    
pregunta Galaxy

4 respuestas

7

Para responder a mi propia pregunta, el problema es que mi código no esperó a que el USB terminara la inicialización e inmediatamente comenzó a enviar datos. Insertar una espera activa en un booleano o agregar un retraso (como lo señala @ramez) resuelve el problema.

ACTUALIZACIÓN Este error se ha corregido en las versiones posteriores del controlador USB CDC de ST. Ahora hay un HAL_Delay en la configuración. La advertencia es que si por alguna razón Sys_Tick no funciona / está desactivado / aún no está inicializado, su código se bloqueará.

    
respondido por el Galaxy
2

Usé CubeMX para generar código para el descubrimiento de STM32F4. Lo usé como puerto COM virtual como tú. No utilicé la función USBD_CDC_SetTxBuffer () directamente. En el archivo usbd_cdc_if.c hay una función llamada CDC_Transmit_FS () . Hubo un error en el código generado, la función tomó un búfer como parámetro y no hizo nada con él. El código de función corregido es el siguiente:

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len)
{
  uint8_t result = USBD_OK;
  memcpy(UserTxBufferFS, Buf, sizeof(char) * Len);
  USBD_CDC_SetTxBuffer(hUsbDevice_0, UserTxBufferFS, Len);   
  result = USBD_CDC_TransmitPacket(hUsbDevice_0);
  return result;
}

En realidad tuve que agregar el memcpy al código. Después de esta corrección, pude enviar datos desde el microcontrolador al PC con esta función de transmisión. Por ejemplo:

int main(void)
{
  HAL_Init();

  SystemClock_Config();

  MX_GPIO_Init();
  MX_USB_DEVICE_Init();
  configureGPIOs();

  uint8_t Buf[] = "Test";

  HAL_Delay(1000);

  while (1)
  {
      CDC_Transmit_FS(Buf, 4);
      HAL_Delay(1000);
  }
}

La inicialización en MX_USB_DEVICE_Init () es la misma que la tuya.

    
respondido por el ramez
1

Primero, verifique si hUsbDevice_0 es nulo (falta un elemento en su solución):

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

Esto evitará que se cuelgue la unidad uC y no necesita estar ocupado esperando en los retrasos.

Puedes colocarlo en algún lugar de CDC_Transmit_FS:

USBD_StatusTypeDef CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) {

    if (hUsbDevice_0 == NULL)
        return USBD_FAIL;

    USBD_CDC_HandleTypeDef *hcdc = (USBD_CDC_HandleTypeDef*) hUsbDevice_0->pClassData;

    if (hcdc->TxState != 0)
        return USBD_BUSY;

    uint8_t result = USBD_OK;

    USBD_CDC_SetTxBuffer(hUsbDevice_0, Buf, Len);
    result = USBD_CDC_TransmitPacket(hUsbDevice_0);

    return result;
}
    
respondido por el jemdream
0

Tuve el mismo problema pero resultó que lo único que tenía que hacer era volver a enchufar la conexión USB a la computadora. La mayoría de las veces, cambia el código y reinicia el microcontrolador, pero en el lado de la PC no se actualiza la enumeración. Se llama a USBD_CDC_Init cuando el host comienza a probar su dispositivo y es por eso que pClassData es NULL.

    
respondido por el Yuanyi Wu

Lea otras preguntas en las etiquetas