Errore VCP USB STM32


8

Ho lavorato a un progetto nelle ultime due settimane e il debug di questo problema è stato ripreso per tutta la settimana. Mi chiedo se qualcuno può aiutare, cercherò di essere il più esplicito e chiaro possibile.

Sto cercando di implementare una porta di comunicazione virtuale USB su un microcontrollore basato su STM32F302K8 (Cortex M4). Ho usato STM32CubMX per generare il codice necessario per configurare un dispositivo USB Full Speed ​​che implementa una classe CDC. Il mio dispositivo viene visualizzato in Windows (Gestione dispositivi) e Linux. Sono in grado di implementare una semplice funzione di eco basata sul codice di esempio, ma quando provo ora ad utilizzare la funzione USBD_CDC_SetTxBuffer per inviare dati al PC, questo fa scattare un gestore di errori hardware. L'ho ridotto al fatto che il campo UsbDeviceFS.pClass (che è necessario per USBD_CDC_SetTxBuffer) non viene mai inizializzato perché USBD_CDC_Init () non viene mai chiamato nell'inizializzazione del dispositivo USB.

Ho implementato correzioni a diversi bug (incluso la modifica della dimensione dell'heap, la correzione del flag di trasmissione in USBD_CDC_TransmitPacket e la modifica della dimensione di CDC_DATA_HS_MAX_PACKET_SIZE a 256 da 512) nel codice di esempio documentato sul forum ST ma ottenendo sempre lo stesso errore.

Il mio codice di configurazione del dispositivo è

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

}

È passato un po 'di tempo dall'ultima volta che ho lavorato con USB su un STM, ma penso che USBD_CDC_Init () provi a fare un malloc. Il problema era che non c'è abbastanza spazio sull'heap nella configurazione predefinita e devi aumentarlo.
brhans,

Ciao, ho aumentato la dimensione dell'heap a 0x600 e non sta succedendo nulla. Quale funzione chiama malloc perché quando inserisco un punto di interruzione, sembra che non venga mai chiamato.
Galaxy

Risposte:


6

Per rispondere alla mia domanda, il problema è che il mio codice non ha aspettato che l'inizializzazione USB finisse e ha iniziato immediatamente a inviare dati. L'inserimento di un'attesa attiva su un valore booleano o l'aggiunta di un ritardo (come sottolineato da @ramez) risolve il problema.

AGGIORNAMENTO Questo errore è stato corretto nelle successive versioni del driver CDC USB da ST. Ora c'è un HAL_Delay nell'installazione. Un avvertimento è che se per qualsiasi motivo Sys_Tick non funziona / è disattivato / non ancora inizializzato, il codice si bloccherà.


1
Sì, dovresti pubblicarlo come una domanda separata. Conservare in questa risposta solo le informazioni rilevanti per la domanda originale.
m.

2

Ho usato CubeMX per generare codice per il rilevamento STM32F4. L'ho usato come porta COM virtuale come te. Non ho usato direttamente la funzione USBD_CDC_SetTxBuffer () . Nel file usbd_cdc_if.c è presente una funzione denominata CDC_Transmit_FS () . Si è verificato un errore nel codice generato, la funzione ha preso un buffer come parametro e non ha fatto nulla con esso. Il codice funzione corretto è il seguente:

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;
}

In realtà ho dovuto aggiungere il memcpy al codice. Dopo questa correzione ho potuto inviare i dati dal microcotroller al PC con questa funzione di trasmissione. Per esempio:

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

L'inizializzazione in MX_USB_DEVICE_Init () è la stessa per te.


1
Grazie ramez. Ho riscontrato il problema, ho dovuto verificare se la porta di comunicazione virtuale aveva terminato l'inizializzazione, ho usato un valore booleano in CDC_Init_FS che il loop principale attendeva essere vero prima di chiamare CDC_Transmit_FS. Penso che HAL_DELAY nel tuo codice ottenga lo stesso effetto. Grazie per l'aiuto.
Galaxy

1

Innanzitutto, controlla se hUsbDevice_0 è null (elemento mancante nella soluzione):

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

Questo eviterà di sospendere il tuo uC e non ha bisogno di aspettare in ritardo.

Puoi posizionarlo da qualche parte in 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;
}

0

Ho avuto lo stesso problema ma si è scoperto che l'unica cosa che dovevo fare era ricollegare la connessione USB al computer. La maggior parte delle volte si esegue il flashing del codice e si reimposta il microcontrollore ma sul lato PC l'enumerazione non viene aggiornata. USBD_CDC_Init viene chiamato quando l'host inizia a sondare il dispositivo ed è per questo che pClassData è NULL.


1
Puoi forzare la re-enumerazione anche nel software. Il secondo modo più stupido dopo aver ricollegato è disabilitare / abilitare la porta in Gestione dispositivi, se non si dispone di un driver personalizzato che lo gestisce in un modo più elegante
stiebrs
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.