Ich habe ein batteriebetriebenes Gerät mit einem STM32F107 . Das Gerät funktioniert und ich arbeite gerade daran, den Stromverbrauch zu minimieren.
Einer der größeren Stromverbraucher ist das USB-Subsystem selbst, das im Leerlauf etwa 8 mA verbraucht. Der USB wird nur für Konfigurationszwecke verwendet; Es ist fast immer unnötig, es zu aktivieren.
Ich verwende die USB-Bibliothek v2.1.0 von ST . Er kommuniziert als virtueller COM-Port ("VCP") der CDC-Klasse. Ich verwende die eingebettete Full-Speed-PHY.
Beim Einschalten möchte ich, dass der USB initialisiert und beispielsweise 30 Sekunden lang aktiv ist. Danach möchte ich, vorausgesetzt, es besteht keine Verbindung zu einem Host, einfach die USB-Funktionalität herunterfahren. Als ob ich es nie aktiviert hätte.
Ich sehe nichts in der API, was dies möglich machen würde. Es gibt ein paar bemerkenswerte Funktionen, aber sie scheinen nicht das zu sein, was ich brauche:
aus der API-Vorlage:usbDeInit()
Dies ist für benutzerdefinierten Benutzercode vorgesehen. Es wird jedoch von der Gerätetreiberfunktion aufgerufen usbd_cdc_DeInit()
, die, soweit ich sehen kann, nie wirklich aufgerufen wird.
in der cdc_core-Bibliothek:usbd_cdc_DeInit()
Dies ist die Datei, die niemals in der Treiberquelle aufgerufen wird. Es schließt die Endpunkte und ruft dann die (vorher erwähnte) usbDeInit()
Funktion auf. Es scheint vielversprechend; es ist jedoch static
in der Treiberquelle als deklariert. Ich zögere, den Treiberbibliothekscode direkt zu ändern, da dieser bei der zukünftigen Aktualisierung des ST-Treibers überschrieben wird.
aus der device_core-Bibliothek:USBD_DeInit()
Diese wird an einigen Stellen vom Fahrer aufgerufen, ist aber leer. Das heißt, die Funktion enthält überhaupt keinen Code. Auch hier möchte ich die Treiberquelle von ST lieber nicht ändern.
Mein Initialisierungsrouting sieht so aus:
// Configure USB Clock Source
RCC_OTGFSCLKConfig(RCC_OTGFSCLKSource_PLLVCO_Div3);
// Enable USB Clock
RCC_AHBPeriphClockCmd(USB_AHB_CLK, ENABLE);
// Initialize USB
USBD_Init(&USB_OTG_dev, USB_OTG_FS_CORE_ID, &USR_desc, &USBD_CDC_cb, &USR_cb);
Wenn ich die USB-Taktquelle einfach deaktiviere, hängt sich der Mikrocontroller natürlich auf.
Ich habe dafür gesorgt, dass der USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
Schalter in der Datei usb_conf.h aktiviert ist, aber die aktuelle Auslosung bleibt bestehen. Ich gehe davon aus, dass es nicht in den Suspend-Modus wechselt (was, wie Ali Chen sagt, die richtige Lösung wäre).
Das Deaktivieren von Funktionsblöcken wie USB in einem modernen SoC ist etwas, das vom Benutzer nicht auf Registerebene durchgeführt werden sollte. Der USB-IP-Block enthält mehrere Unterblöcke und Schnittstellen zwischen ihnen: Access Fabric, Core Controller, FIFOs/SIPOs, PHY. Alle Schnittstellen arbeiten normalerweise mit einigen Handshake-Protokollen, die normalerweise ein gewisses Vorhandensein von Uhren auf beiden Seiten der Schnittstelle erfordern, sodass willkürliches Mocken mit Uhrensteuerregistern zu Deadlocks führen kann. Daher wird dringend empfohlen, vorgefertigte Funktionen (wie SUSPEND) von Software-IP zu verwenden, um die USB-Blockierung zu verwalten. In der Dokumentation heißt es teilweise:
Die OTG_HS-Schnittstelle hat folgende Features: ... - Powersaving-Features wie Stopp der Systemuhr während USB-Suspend, Abschalten der internen Taktdomänen des digitalen Kerns, PHY- und DFIFO-Power-Management ...
Und
Suspendierung des Geräts Wenn das Gerät einen Suspend-Zustand am USB erkennt, stoppt die Bibliothek alle Operationen und versetzt das System in den Suspend-Zustand (wenn der Energiesparmodus in der Datei usb_conf.h aktiviert ist).
Um die Energiesparaufgabe zu erfüllen, würde ich daher dringend empfehlen, bereits entwickelte Funktionen aus der STM-USB-Bibliothek zu verwenden.
ZUSÄTZLICH: Das STM-Paket scheint eine Einschränkung zu haben, dass der Suspend- oder Disconnect-Modus nicht durch die Benutzer-Firmware erzwungen werden kann. Hier ist eine Idee: Nachdem die Gerätefunktion beendet ist, schalten Sie den OTG-Controller in den HOST-MODUS. Fahren Sie dann aber nicht mit der Initialisierung der HOST-Funktion fort oder beenden Sie die HOST-Funktion. Dies kann zu einer vollständig deaktivierten USB-Blockierung führen.
USB_OTG_FS_LOW_PWR_MGMT_SUPPORT
Schalter in der Datei usb_conf.h aktiviert, aber die aktuelle Auslosung existiert noch. Sollte der Benutzer in der Lage sein, den Suspend-Modus zu erzwingen?Sie müssen wahrscheinlich alles in umgekehrter Reihenfolge deaktivieren. Versuchen:
USBD_DeInit();
RCC_AHBPeriphClockCmd(USB_AHB_CLK, ENABLE);
Oder vielleicht das Gegenteil.
Ale..chenski
Chris Stratton
bitsmack