STM32 USB VCP-Fehler

8

Ich arbeite jetzt seit zwei Wochen an einem Projekt und das Debuggen dieses einen Problems hat diese ganze Woche in Anspruch genommen. Ich frage mich, ob jemand helfen kann, und werde versuchen, so deutlich und klar wie möglich zu sein.

Ich versuche, einen virtuellen USB-Kommunikationsanschluss auf einem MicroController basierend auf dem STM32F302K8 (Cortex M4) zu implementieren. Ich habe STM32CubMX verwendet, um den Code zu generieren, der zum Einrichten eines USB-Vollgeschwindigkeitsgeräts zur Implementierung einer CDC-Klasse erforderlich ist. Mein Gerät wird sowohl unter Windows (Geräte-Manager) als auch unter Linux angezeigt. Ich kann eine einfache Echofunktion basierend auf dem Beispielcode implementieren, aber wenn ich jetzt versuche, die Funktion USBD_CDC_SetTxBuffer zum Senden von Daten an den PC zu verwenden, wird ein Hard Fault Handler ausgelöst . Ich habe dies auf die Tatsache eingegrenzt, dass das Feld UsbDeviceFS.pClass (das von USBD_CDC_SetTxBuffer benötigt wird) niemals initialisiert wird, da USBD_CDC_Init () bei der Initialisierung des USB-Geräts niemals aufgerufen wird.

Ich habe Korrekturen für mehrere Fehler implementiert (einschließlich Ändern der Heap-Größe, Beheben des Übertragungsflags in USBD_CDC_TransmitPacket und Ändern der Größe von CDC_DATA_HS_MAX_PACKET_SIZE von 512 auf 256) im Beispielcode, wie im ST-Forum dokumentiert, aber immer noch der gleiche Fehler.

Mein Geräte-Setup-Code lautet

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

}
Galaxis
quelle
Es ist schon eine Weile her, seit ich das letzte Mal mit USB an einem STM gearbeitet habe, aber ich denke, dass USBD_CDC_Init () versucht, ein Malloc zu erstellen. Das Problem war, dass im Standard-Setup nicht genügend Speicherplatz auf dem Heap vorhanden ist und Sie ihn erhöhen müssen.
Brhans
Hallo, ich habe die Heap-Größe auf 0x600 erhöht und nichts passiert. Welche Funktion ruft malloc auf, denn wenn ich einen Haltepunkt darauf setze, scheint es, dass er niemals aufgerufen wird.
Galaxy

Antworten:

6

Um meine eigene Frage zu beantworten, besteht das Problem darin, dass mein Code nicht auf den Abschluss der Initialisierung durch USB gewartet hat und sofort mit dem Senden von Daten begonnen hat. Das Einfügen einer aktiven Wartezeit in einen Booleschen Wert oder das Hinzufügen einer Verzögerung (wie von @ramez hervorgehoben) löst das Problem.

UPDATE Dieser Fehler wurde in nachfolgenden USB CDC-Treiberversionen von ST behoben. Es gibt jetzt eine HAL_Delay im Setup. Vorsichtsmaßnahme: Wenn Sys_Tick aus irgendeinem Grund nicht funktioniert / deaktiviert / noch nicht initialisiert ist, bleibt Ihr Code hängen.

Galaxis
quelle
1
Ja, Sie sollten dies als separate Frage posten. Behalten Sie in dieser Antwort nur die Informationen, die für die ursprüngliche Frage relevant sind.
m.Alin
2

Ich habe CubeMX zum Generieren von Code für die STM32F4-Erkennung verwendet. Ich habe es wie Sie als virtuellen COM-Port verwendet. Ich habe die Funktion USBD_CDC_SetTxBuffer () nicht direkt verwendet. In der Datei usbd_cdc_if.c befindet sich eine Funktion namens CDC_Transmit_FS () . Es gab einen Fehler im generierten Code, die Funktion nahm einen Puffer als Parameter und tat nichts damit. Der korrigierte Funktionscode lautet wie folgt:

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

Eigentlich musste ich den memcpy zum Code hinzufügen. Nach dieser Korrektur konnte ich mit dieser Sendefunktion Daten vom Microcrollroller an den PC senden. Zum Beispiel:

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

Die Initialisierung in MX_USB_DEVICE_Init () ist bei mir dieselbe wie bei Ihnen.

Tenkmilan
quelle
1
Danke ramez. Ich habe das Problem gefunden. Ich musste testen, ob der virtuelle Kommunikationsport die Initialisierung abgeschlossen hat. Ich habe in CDC_Init_FS einen Booleschen Wert verwendet, auf den die Hauptschleife gewartet hat, bevor sie CDC_Transmit_FS aufruft. Ich denke, dass HAL_DELAY in Ihrem Code den gleichen Effekt erzielt. Danke für die Hilfe.
Galaxy
1

Überprüfen Sie zunächst, ob hUsbDevice_0 null ist (fehlendes Element in Ihrer Lösung):

    if (hUsbDevice_0 == NULL)
            return USBD_FAIL;

Dies verhindert, dass Ihr uC hängen bleibt, und erfordert kein verzögertes Warten.

Sie können es irgendwo in CDC_Transmit_FS platzieren:

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;
}
jemdream
quelle
0

Ich hatte das gleiche Problem, aber es stellte sich heraus, dass ich nur die USB-Verbindung wieder an den Computer anschließen musste. Meistens flashen Sie den Code und setzen den Mikrocontroller zurück, aber auf der PC-Seite wird die Aufzählung nicht aktualisiert. USBD_CDC_Init wird aufgerufen, wenn der Host beginnt, Ihr Gerät zu testen. Deshalb ist pClassData NULL.

Yuanyi Wu
quelle
1
Sie können die erneute Aufzählung auch in der Software erzwingen. Der zweitdümmste Weg nach dem erneuten Einstecken ist das Deaktivieren / Aktivieren Ihres Ports im Geräte-Manager, wenn Sie keinen benutzerdefinierten Treiber haben, der dies auf ausgefallenere Weise
handhabt