STM32 USB CDC: cómo detener la transmisión del dispositivo a través de USB cuando no está conectado

1

Después de más de 3 semanas de pruebas y depuración, finalmente obtuve mi STM32 transmitiendo datos de manera confiable a través de USB. El problema es que NECESITA una aplicación en el otro lado del USB para consumir los datos. Cuando estoy conectado a mi PC, y un programa que muestra los datos está activo (Realterm, script de Python, etc.) funcionará de forma indefinida.

Si por alguna razón el programa en la PC se cierra, o nunca se abre, el µC funcionará durante medio minuto y luego se congelará. Aquí está el código para mi transmisión. He intentado que el µC compruebe si hay actividad en el bus antes de enviar datos, pero eso aparentemente no funciona. El µC se congela en la condición while (pCDC- > TxState). Después de no poder enviar los datos, la bandera nunca se restablece.

uint8_t CDC_Transmit_FS(uint8_t* Buf, uint16_t Len){

uint8_t result = USBD_OK;
volatile uint8_t bDeviceState = (volatile uint8_t) hUsbDevice_0->dev_state

// If no activity on the bus for past 3 seconds fail
if(bDeviceState == USBD_STATE_SUSPENDED)   // <----- This doesn't seem to work
       return USBD_FAIL;

// wait for previous transfer to complete 
USBD_CDC_HandleTypeDef *pCDC = (USBD_CDC_HandleTypeDef * hUsbDevice_0->pClassData;
while (pCDC->TxState) { }

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

// wait until transfer is done
while (pCDC->TxState) { } 
return result;
}

Mi pregunta es ¿cómo le hago saber a la aplicación en el µC que no está conectada y que sigue funcionando? es decir. Si no hay una aplicación host que reciba datos, simplemente regrese de la función CDC_Transmit_FS. Si elimino el tiempo, la velocidad a la que envío los datos termina sobrescribiendo los datos en el búfer. Si lo pongo, el µC se bloquea cuando no está conectado a un host.

    
pregunta Galaxy

2 respuestas

2

En el nivel más bajo, el host USB sondea el dispositivo para verificar los datos disponibles.

Desde el dispositivo, no es posible determinar si el host está ocupado y seguirá recibiendo datos más tarde, o si no hay ninguna aplicación que haya abierto el dispositivo serie.

Si tiene la capacidad de cancelar un paquete de transmisión, podría implementar un tiempo de espera. De lo contrario, debe detener lo que está haciendo y esperar hasta que el paquete se haya transmitido realmente.

    
respondido por el CL.
1

Primero, verifica si hUsbDevice_0 es nulo:

if (hUsbDevice_0 == NULL)
        return USBD_FAIL;

Código completo:

USBD_StatusTypeDef CDC_Transmit_FS(uint8_t* Buf, uint16_t Len) {
    uint8_t result = USBD_OK;

    if (hUsbDevice_0 == NULL)
        return USBD_FAIL;

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

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

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

    return result;
}
    
respondido por el jemdream

Lea otras preguntas en las etiquetas