STM32F070 - Firmware-gesteuerte USB-Verbindung und HSE-Aktivierung

Ich entwickle Firmware für ein Low-Power-USB-2.0-Full-Speed-Gerät (12 Mbit/s), das einen STM32F070CB -Mikrocontroller verwendet. Die Taktquelle für das USB-Modul ist der High Speed ​​External (HSE)-Oszillator. Ich verwende STM32CubeMX mit Version 1.7.0 von STM32CubeF0 , um die Codebasis zu generieren.

Um unser Energiebudget zu schonen, müssen wir die HSE ausschalten, wenn der USB nicht angeschlossen ist. Ich denke, wir sollten die Firmware veranlassen, die USB-Erkennung durch den Host zu verzögern, bis das Gerät bereit ist, damit die Ereignisse in der Firmware ungefähr so ​​​​aussehen:

  • Ereignis – Physische USB-Verbindung erkennen
    • HSE aktivieren
    • USB initialisieren
    • Connect Data+ Pullup ( DPPU), um die USB-Enumeration nach Host auszulösen
  • Ereignis – Physische USB- Verbindungsunterbrechung erkennen
    • Trennen DPPU(physische Trennung zum Host simulieren)
    • USB deinitialisieren
    • HSE deaktivieren (Laufwerk PF0-OSC_INniedrig)

Fragen

  1. Ist das oben genannte der richtige Weg, um dies zu tun? Sind die Maßnahmen alle erforderlich? Sind sie in der richtigen Reihenfolge?

  2. Muss ich außer USBD_DeInit()dem Deinitieren von USB noch andere Funktionen aufrufen?

  3. Wie kann ich dafür sorgen, dass das Gerät auf dem Host als getrennt angezeigt wird, während es physisch verbunden ist? (dh es sollte aus dem Windows-Geräte-Manager verschwinden.) Warum bewirkt das Anrufen nicht, HAL_PCD_DevDisconnect()dass dies geschieht?

Einzelheiten

In den folgenden Abschnitten bedeutet „physisch verbinden“, das USB-Kabel mit dem Gerät und dem Host-PC zu verbinden.

Ich würde erwarten, dass alle Aufrufe von MX_USB_DEVICE_Init()und MX_USB_DEVICE_DeInit()sofort wirksam werden, dh dass das Gerät im Windows-Geräte-Manager angezeigt/verschwindet, wenn die Funktion aufgerufen wird, während das Gerät physisch verbunden ist. Allerdings habe ich dies nur beim ersten Aufruf von beobachtet MX_USB_DEVICE_Init(). Alle Aufrufe an MX_USB_DEVICE_DeInit()und nachfolgende Aufrufe an führen MX_USB_DEVICE_Init()nicht dazu, dass das Gerät im Windows-Geräte-Manager angezeigt/verschwindet, bis die physische Wiederverbindung erfolgt ist. (dh wenn es verbunden ist, wenn die Funktion aufgerufen wird, keine Änderung im Geräte-Manager bis nach dem Trennen/Wiederverbinden.)

Code

Wie von STM32CubeMX generiert:

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

Ich erschuf:

void MX_USB_DEVICE_DeInit(void)
{
   HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)&hUsbDeviceFS.pData);
   USBD_Stop  (&hUsbDeviceFS);
   USBD_DeInit(&hUsbDeviceFS);
}

Egal ob oder wann ich anrufe HAL_PCD_DevDisconnect(). Ich habe noch nie beobachtet, dass das Gerät aus dem Windows Geräte-Manager verschwindet, während es physisch verbunden ist.

Antworten (1)

  1. Wie kann ich dafür sorgen, dass das Gerät auf dem Host als getrennt angezeigt wird, während es physisch verbunden ist? (dh es sollte aus dem Windows-Geräte-Manager verschwinden.) Warum bewirkt das Anrufen nicht, HAL_PCD_DevDisconnect()dass dies geschieht?

Das Aufrufen HAL_PCD_DevDisconnect()mit den richtigen Parametern trennt tatsächlich DPPU, wodurch das Gerät aus dem Windows-Geräte-Manager verschwindet. Der Fehler in der Frage ist, dass in MX_USB_DEVICE_DeInit(),

HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)&hUsbDeviceFS.pData);

sollte sein

HAL_PCD_DevDisconnect((PCD_HandleTypeDef *)hUsbDeviceFS.pData);

(ohne den Adressoperator &).

Hier ist eine überarbeitete Version der USB-de-init-Funktion:

void MX_USB_DEVICE_DeInit(void)
{
   PCD_HandleTypeDef *hpcd = (PCD_HandleTypeDef *)hUsbDeviceFS.pData;

   if (hpcd != NULL)
   {
      HAL_PCD_DevDisconnect(hpcd);
      USBD_DeInit(&hUsbDeviceFS);
   }
}
  1. Ist das oben genannte der richtige Weg, um dies zu tun? Sind die Maßnahmen alle erforderlich? Sind sie in der richtigen Reihenfolge?

Schließen. Die Uhrenkonfiguration umfasst mehr als nur das Ein- oder Ausschalten von HSE.

STM32CubeMX generiert SystemClock_Config(). Sie können es als Vorlage für die Schritte "Systemuhren konfigurieren" in der folgenden Liste verwenden.

  • Ereignis – Physische USB-Verbindung erkennen
    • Systemuhren konfigurieren
      • HSE aktivieren
      • PLL einschalten
      • Stellen Sie SYSCLKSOURCEeinPLLCLK
      • UsbClockSelectionAuf PLL einstellen
      • Systick konfigurieren
    • Initialisieren Sie USB und verbinden Sie Data+ pull-up ( DPPU), um die USB-Enumeration durch den Host auszulösen – MX_USB_DEVICE_Init()tut all dies
  • Ereignis – Physische USB-Trennung erkennen
    • Trennen DPPU( HAL_PCD_DevDisconnect())
    • USB deinitialisieren ( USBD_DeInit())
    • Konfigurieren Sie Systemuhren (beachten Sie viele Schritte in umgekehrter Reihenfolge von oben)
      • Schalten Sie das USB-Peripheriegerät aus
      • Schalten Sie sysclk wieder auf HSI um
      • Deaktivieren Sie HSE (nicht sicher, ob PF0-OSC_INes notwendig ist, niedrig zu fahren)
      • PLL ausschalten
      • Systick konfigurieren
  1. Muss ich außer USBD_DeInit()dem Deinitieren von USB noch andere Funktionen aufrufen?

Nein, das geht. Stöbern Sie in den Call-Stacks und Sie werden feststellen, dass USBD_DeInit()alles aufgerufen wird, was dies USBD_Stop()tut, und mehr.