Muss ich den stm32-Mikrocontroller wirklich in den Bootloader-Modus versetzen, um ihn zu programmieren?

Ich habe eine Weile angefangen, den stm32-Mikrocontroller mit einem sehr kleinen Entwicklungsboard "stm32f103c8t6" (oder blaue Pille) zu lernen. Als ich anfing, lernte ich aus einigen Tutorials, dass ich einen Jumper umstecken muss, um ihn zu programmieren.

Geben Sie hier die Bildbeschreibung ein(Das Foto ist ein Screenshot aus einem zufälligen Tutorial, aber jedes Tutorial, das ich mir angesehen habe, sagte das auch)

Geben Sie hier die Bildbeschreibung ein

Der Jumper ändert - soweit ich weiß - nur den Boot-Modus des Prozessors, um ihn aus dem Systemspeicher (dem Bootloader) zu laden, was nur wirksam wird, wenn ich das Board neu starte, um von dort aus zu booten.

Ich weiß nicht, wie das ein "Programmiermodus" sein soll, da ich einen externen ST-Link-Programmierer verwende, der SWD verwendet.

Geben Sie hier die Bildbeschreibung ein

Also meine Frage hier, gibt es wirklich so etwas wie "Programmiermodus"? und wenn ja, wie genau funktioniert das?

Erwähnenswert ist auch, dass ich gerade versucht habe, es zu programmieren, und das Programm funktionierte so, wie es sollte (ich hoffe, ich habe nichts vermasselt :d ).

Antworten (4)

Sie müssen den Mikrocontroller nur in den Bootloader-Modus versetzen, wenn Sie ihn mit dem Bootloader über den UART programmieren möchten.

Grundsätzlich können Sie den Mikrocontroller jederzeit über SWD programmieren.

Die primären Ausnahmen sind, wenn der Mikrocontroller ein Programm ausführt, das SWD durch Setzen eines SWJ_CFGBits deaktiviert AFIO->MAPR(z. B. um die zugehörigen Pins als GPIOs zu verwenden), oder wenn die MCU im Energiesparmodus läuft, ohne dass die entsprechenden DBGMCUFlags gesetzt sind, um die Debug-Schnittstelle in diesen Modi aktiv. Wenn einer dieser Fälle zutrifft, ist es eine einfache Problemumgehung, den Mikrocontroller in den Bootloader-Modus zu versetzen, da die SWD-Schnittstelle aktiv ist (und keine Schlafmodi verwendet werden), während der Bootloader ausgeführt wird.

Dazu müssen Sie nicht einmal mit den BOOT0/1-Pins spielen. Ich habe den ROM-Bootloader bei mehreren STM32-Familien durch sorgfältige Codierung erfolgreich neu gestartet. Die BOOT-Pins sind praktisch, aber nicht zwingend erforderlich.
Beachten Sie auch, dass der ROM-Bootloader mehrere Arten von Schnittstellen unterstützt, nicht nur UART. Obwohl der `103 über USB verfügt, ist dies keine der vom ROM-Bootloader unterstützten Schnittstellen. Bei späteren STM32-Varianten ist dies der Fall.
@ChrisStratton Es ist nicht unbedingt ganz so einfach wie "spätere" Varianten, aber Sie haben im Wesentlichen Recht. ST Application Note AN2606 hat einen langen Überblick darüber, welche STM32-Teile welche Bootloader haben und welche Funktionen unterstützt werden.
@akohlsmith, das keine Raketenwissenschaft ist (6-7 Codezeilen zum Aufrufen). Der interne Bootloader ist jedoch etwas nutzlos, da er nicht überprüft, ob das Image korrekt ist, das geladene Image nicht entschlüsselt und nicht funktioniert, wenn Sie den Speicher schützen. Ich benutze in der Produktion meine eigenen Geräte - das Schreiben ist recht unkompliziert und einfach.
@duskwuff-inactive- wartet dieser Bootloader nach dem Einschalten für immer auf ein Programm über UART? oder prüft es auf ein Programm und fährt mit der Ausführung des vorhandenen Codes fort?

Es gibt möglicherweise viele Möglichkeiten, das Board mit verschiedenen Tools zu programmieren. Eine davon, die ziemlich einfach zu sein scheint, ist die Verwendung von ST-Link V2 (google it) und OpenOCD.

  1. Lassen Sie beide Bootjumper auf "0". Verbinden Sie die Pins SWDIO, SWCLK, GND mit den entsprechenden Pins des ST Link. Legen Sie Strom an die Platine an und achten Sie darauf, ob es 5 V oder 3,3 V beträgt. Der ST-Link verfügt praktischerweise über einen 3,3-V-Ausgang, der verwendet werden kann. Da die Platine 5 V vom USB-Anschluss erhält, verbinden Sie keine anderen Stromanschlüsse gleichzeitig mit dem USB-Anschluss. Es kann sinnvoll sein, ein Kabel mit 4 Anschlüssen auf der ST-Link-Seite und geteilten 3+1-Anschlüssen auf der Platinenseite zu haben. Die Platine sollte eine LED aufleuchten und kann mit der anderen blinken, wenn sie programmiert ist.

  2. Haben Sie OpenOCD installiert, neuere Versionen können weniger fehlerhaft sein (z. B. mindestens 0.9.x oder besser 0.10.x). Ältere Versionen, wie sie in Linux-Distributionen enthalten sind, haben möglicherweise Probleme mit z. B. dem Zurücksetzen der Konfiguration und erfordern das Hantieren mit Konfigurationsdateien.

  3. [optional] Wenn Sie Linux ausführen und OpenOCD nicht als Root ausführen möchten, erstellen Sie eine Datei /etc/udev/rules.dmit folgendem Inhalt:

    SUBSYSTEMS=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3748", MODE="0664", GROUP="stlink"
    

Dadurch können Mitglieder der stlinkGruppe auf das ST-Link-Gerät zugreifen. Erstellen Sie diese Gruppe und fügen Sie sich selbst hinzu. Sie können jede geeignete Gruppe verwenden.

  1. Unter der Annahme eines Linux-Hosts und einer systemweiten OpenOCD-Standardinstallation prüfen Sie, ob die Konnektivität in Ordnung ist, die MCU am Leben ist und OpenOCD mit ihr kommunizieren kann:

     openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg
    

Je nach OpenOCD-Version kann auch Folgendes funktionieren:

     openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg

Wenn die Dinge gut sind, druckt OpenOCD einige Informationen über die MCU (Spannung, Anzahl der HW-Haltepunkte usw.) und läuft weiter.

  1. Es ist möglicherweise möglich, OpenOCD als Daemon auszuführen und Telnet zu verwenden, aber ich denke, es ist bequemer, es jedes Mal zu starten. Angenommen, Sie haben eine ordnungsgemäß kompilierte Binärdatei, sagen wir, blinky.bin, können Sie sie mit dem folgenden Skript in die MCU programmieren:

    OPENOCD="openocd -f interface/stlink-v2.cfg -f target/stm32f1x_stlink.cfg"
    $OPENOCD -c "init" -c "reset halt" -c "stm32f1x mass_erase 0" -c "flash write_bank 0 blinky.bin 0" -c "reset run" -c "shutdown"
    

Beachten Sie, dass sich in diesem Skript der Dateiname befindet, den Sie anpassen müssen. Es ist wahrscheinlich eine gute Idee, mit etwas wirklich Einfachem zu beginnen.

Das Obige geht hauptsächlich von Linux als Host aus, aber die Schritte sollten in Windows konzeptionell ähnlich sein, nachdem Sie Treiber installiert und Anpassungen an der Installation vorgenommen haben, wie z. B. Pfade und so weiter.

Wenn Sie einen ST-Link (SWD)-Programmierer verwenden, müssen Sie die Karte nicht in den "Programmiermodus" versetzen.

Ein Bootloader ermöglicht es dem Chip, ein neues Programm herunterzuladen und auszuführen. Der "Programmiermodus"-Jumper verwendet die BOOT-Pins, um dem ROM-Bootloader zu signalisieren, dass er bereit sein muss, ein neues Programm herunterzuladen, andernfalls beginnt der Chip mit der Ausführung des Programms, das sich bereits im Speicher befindet. Da Sie SWD zum Programmieren verwenden, wird der ROM-Bootloader nicht benötigt.

[Bearbeiten]: Wie Chris Stratton und Duskwuff unten hervorheben, unterstützt der STM32F103-ROM-Bootloader keine Programmierung über USB, sondern nur UART, und er kann nicht gelöscht werden. Es gibt einen separaten Benutzer-Flash-Bootloader , der auf das Board geladen werden kann, der die Programmierung über USB unterstützt (dh zur Verwendung mit Arduino IDE), aber die BOOT-Pins nicht verwendet (also nicht vom Jumper "Programmiermodus" betroffen ist). .

Der hier beteiligte Bootloader befindet sich im ROM (oder zumindest im nicht vom Benutzer änderbaren Flash). Es ist vom Benutzer-Flash getrennt und kann nicht über SWD gelöscht werden.
@duskwuff, danke für die Korrektur! Ich dachte an einen anderen Chip.
Dies ist falsch - der werkseitige ROM-Bootloader auf dem STM32F103 unterstützt USB nicht , obwohl dies bei vielen späteren STM32-Varianten der Fall ist. Daher müsste jeder funktionierende USB-Bootloader für den '103 im Anwendungs-Flash und nicht im ROM resident sein, und daher würden die Boot-Pins für einen normalen Flash-Boot eingestellt, nicht für einen ROM-Bootloader-Boot, um darauf zuzugreifen.
@ChrisStratton, danke für die Korrektur! Anscheinend habe ich nur STM32-Teile verwendet, die USB/DFU für den werkseitigen Bootloader unterstützten, daher war mir nicht bewusst, dass es auf diesem Chip nicht unterstützt wird.
"nur UART" ist auch nicht korrekt - es unterstützt eine Reihe von Schnittstellen, nur nicht (auf dem `103) USB.
@ChrisStratton, gemäß der STM32F103x8-Spezifikation und AN2606 scheint es, dass nur USART1 für den Bootloader auf diesem Chip unterstützt wird. Können Sie einen Link bereitstellen, der die anderen unterstützten Schnittstellen zeigt?

Aus dem Produktspezifikationsdatenblatt DS5319 PDF , Rev. 17 (vom August 2015), Abschnitt 2.3.8, Boot-Modi:

Beim Start werden Boot-Pins verwendet, um eine von drei Boot-Optionen auszuwählen:

  • Booten Sie vom Benutzer-Flash
  • Booten Sie vom Systemspeicher
  • Booten Sie vom eingebetteten SRAM

Der Bootloader befindet sich im Systemspeicher. Es wird verwendet, um den Flash-Speicher mithilfe von USART1 neu zu programmieren. Weitere Einzelheiten entnehmen Sie bitte AN2606.

Aus der Einführung von AN2606 PDF (Rev. 42, vom Dez. 2019) : „Der Bootloader ist im internen Boot-ROM-Speicher (Systemspeicher) von STM32-Geräten gespeichert. Er wird von ST während der Produktion programmiert. Seine Hauptaufgabe besteht darin, die Anwendung herunterzuladen Programmieren Sie über eines der verfügbaren seriellen Peripheriegeräte (USART, CAN, USB, I2C, SPI usw.) in den internen Flash-Speicher. Für jede serielle Schnittstelle ist ein Kommunikationsprotokoll mit einem kompatiblen Befehlssatz und kompatiblen Sequenzen definiert. Dieses Dokument gilt für die in Tabelle 1 aufgeführten Produkte. Sie werden im gesamten Dokument als STM32 bezeichnet.“

Im Kapitel über den Bootloader der STM32F10xxx-Geräte heißt es: „Nach der Initialisierung lautet die USART1-Konfiguration: 8 Bits, gerade Parität und 1 Stoppbit.“ "PA10-Stift: USART1 im Empfangsmodus", "PA9-Stift: USART1 im Sendemodus".

Dann gibt es AN3155 , das das eigentliche USART-Protokoll beschreibt, das initiiert wird, wenn der STM32 das Byte empfängt 0x7F.