Inhaltsverzeichnis:

Teil 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Gunook
Teil 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Gunook

Video: Teil 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Gunook

Video: Teil 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Gunook
Video: What's a Microcontroller w/ Python Educator Workshop Part 1 of 3 (July 19, 2021) 2024, Juli
Anonim
Image
Image

Der Fokus dieses Instructable ist der STM32 Nucleo-Mikrocontroller. Die Motivation dafür, aus dem Rohbau ein Montageprojekt erstellen zu können. Dies wird uns helfen, tiefer einzutauchen und das MSP432 Launchpad-Projekt (das TI-RSLK) zu verstehen, das bereits Gegenstand mehrerer Instructables war.

Es gibt nicht viel Online-Hilfe zum Erstellen eines Nur-Assembly-Projekts für den MSP432 mit Code Composer Studio. Bisher haben wir nur aus einem bereits vorhandenen Baugruppenprojekt kopiert/eingefügt. Dieser Ansatz hat uns gute Dienste geleistet.

Bei Lab 7 sind wir jetzt jedoch auf ein kleines Problem gestoßen. Oder zumindest ein vorübergehender Schluckauf. Das Lab 7 führt endliche Automaten ein, und das erste, was uns begegnet, ist die Notwendigkeit, ein Array von Werten zu erstellen und zu verwenden. Da der TI-Kurs hauptsächlich C-Programmierung verwendet - ist dies kein Problem. Aber diese Instructables haben sich auf die Montage konzentriert, nicht auf C.

Da das Array aus schreibgeschützten Werten besteht, wäre es außerdem gut, es im Flash-Speicher und nicht im RAM abzulegen.

Es scheint online viel mehr Hilfe für Montageprojekte mit der STM32-MCU zu geben. Daher beginnen wir mit diesem Instructable, mit dem Ziel, das Gelernte zu verwenden, um es dann auf das MSP432 und das Code Composer Studio anzuwenden.

Auf dem Weg zu diesem Ziel haben wir auch Erfahrungen mit einem weiteren, beliebten Mikrocontroller gesammelt.

Schritt 1: Erster Test des Geräts

Erster Test des Geräts
Erster Test des Geräts
Erster Test des Geräts
Erster Test des Geräts
Erster Test des Geräts
Erster Test des Geräts

Nochmals, warum sollten Sie sich speziell für den STM32 Nucleo entscheiden?

Mal ehrlich? Da ich auf der Suche nach guten Artikeln zu Bare-Metal-Assembly-Projekten für ARM-Controller war, bin ich auf diese Serie gestoßen. Und auch, weil der STM32 eine beliebte MCU zu sein scheint.

Ich habe etwas recherchiert (es gibt viele Versionen zur Auswahl - siehe Bild oben), aber am Ende wurde es das, was ich tatsächlich bekommen kann, da ich Amazon (in den USA) verwenden wollte.

Es kommt in einem einfachen, aber professionellen Paket mit einigen Inbetriebnahmeanleitungen. Es war ein bisschen lustig zu sehen, dass die in den Controller gebrannte Demo fast genau das war, was wir in früheren Instructables gemacht haben - eine LED blinkt und ändert die Geschwindigkeit auf Knopfdruck.

Es scheint, dass dieses Entwicklungsboard dem MSP432 sehr ähnlich ist, da es 2 LEDs und eine Benutzertaste gibt. Das MSP432 verfügt über 2 Benutzertasten.

Wie Sie auf den Fotos sehen können, war ich etwas überrascht, dass das Board einen Mini- und keinen Micro-USB hat. Musste ausgehen, um ein Kabel zu kaufen.

Ein weiterer guter Test ist, dass es in meinem Dateimanager als Dateisystem namens "NODE_F303RE" angezeigt wird, wenn Sie es an Ihren Computer anschließen (ich verwende eine Linux-Box). Beim Öffnen werden zwei Dateien angezeigt, eine HTML- und eine Textdatei.

Das war's, aber zumindest sagt es auch, dass die Konnektivität recht einfach scheint.

Jetzt können wir beginnen.

Ich werde versuchen, keine der guten Informationen aus der IVONOMICON-Bare-Metal-Artikelserie zu wiederholen, sondern zu ergänzen.

Schritt 2: Das Wesentliche

Als erstes brauchen wir einen Compiler.

Und dann brauchen wir einen Debugger:

devchu@chubox:~$ sudo apt-get install gdb-arm-none-eabiPaketlisten lesen… Fertig Abhängigkeitsbaum erstellen Statusinformationen lesen… Fertig Die folgenden NEUEN Pakete werden installiert: gdb-arm-none-eabi 0 aktualisiert, 1 neu installiert, 0 zu entfernen und 8 nicht aktualisiert. Benötigen Sie 2.722 kB an Archiven. Nach diesem Vorgang werden 7, 738 kB zusätzlicher Speicherplatz verwendet. Holen:1 https://us.archive.ubuntu.com/ubuntu xenial/universe amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] 2, 722 kB in 1s abgerufen (1, 988.) kB/s) Auswahl des zuvor nicht ausgewählten Pakets gdb-arm-none-eabi. (Lesen der Datenbank … 262428 derzeit installierte Dateien und Verzeichnisse.) Entpacken wird vorbereitet …/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb … Entpacken von gdb-arm-none-eabi (7.10-1ubuntu3+9) … Verarbeitung triggers for man-db (2.7.5-1) … Einrichtung von gdb-arm-none-eabi (7.10-1ubuntu3+9) …

Schritt 3: Das Wesentliche - Windows

Der obige Schritt ging davon aus, dass wir Linux verwenden. Was ist, wenn wir Windows verwenden?

Sie können zur arm Developer-Site gehen, und es stehen mehrere Download-Optionen zur Verfügung. Ich verwende einen Windows 8-Rechner.

Während der Installation habe ich mich dafür entschieden, es auf dem Root-Laufwerk "C:\" anstelle von Program Files zu installieren, nur weil ich auch Cygwin verwende, und es war einfacher, einen Link von meinem lokalen Bin zu einem Root-C:-Ordner zu erstellen als alle Durcheinander im Pfad zu den Programmdateien (mit Leerzeichen usw.).

Somit sieht meine Cygwin-Umgebung und mein Pfad usw. so aus:

C:\cygwin64\home\bin\arm-none-eabi-gcc, wobei arm-none-eabi-gcc ein Link zu C:\GNUToolsArmEmbedded\7.2018.q2.update\bin\arm-none-eabi- ist. gcc.

Ich habe dann unter cygwin home einen Ordner "dev" erstellt, dort die Datei core. S abgelegt und den Compiler-Befehl ausgeführt. (Siehe weiter unten für die Compiler-Zeug).

Ich habe das gleiche für gdb gemacht (arm-none-eabi-gdb).

Schritt 4: Was sind die Essentials?

Was ist also "gcc-arm-none-eabi" ?

Der Gnu-Compiler (GCC) kompiliert Programmiersprachen (wie C) in nativen Code für die Maschine, auf der er läuft. Wenn Sie beispielsweise C-Code mit GCC auf Ihrem Windows-Rechner kompilieren, wird er für die Ausführung auf dem Windows-Rechner erstellt. Die generierte ausführbare Datei wird (normalerweise) nicht auf dem ARM-Mikrocontroller ausgeführt.

Um also Programme zu erstellen, die heruntergeladen und in den ARM-Mikrocontroller (in unserem vorliegenden Fall wäre das der STM32 Nucelo) gebrannt werden, müssen wir GCC noch etwas anderes geben: die Fähigkeit zum "Cross-Compile". Das heißt, die Fähigkeit, eine ausführbare Datei zu generieren, nicht für das native System (und den Prozessor), sondern für das Zielsystem (den ARM-Mikrocontroller). Hier kommt "gcc-arm-none-eabi" ins Spiel.

Was ist dann "gdb-arm-none-eabi" ?

Sobald wir die neu generierte ausführbare Datei heruntergeladen und in den Mikrocontroller gebrannt (geflasht) haben, möchten wir sie wahrscheinlich debuggen - Schritt für Schritt durch den Code. GDB ist der Gnu-Debugger, und auch er braucht einen Weg, um seine Arbeit zu erledigen, zielt aber auf ein anderes System ab.

Somit ist gdb-arm-none-eabi für GDB, was gcc-arm-none-eabi für GCC ist.

Eine andere vorgeschlagene Paketinstallation war "libnewlib-arm-none-eabi". Was ist das?

Newlib ist eine C-Bibliothek und eine mathematische Bibliothek, die für die Verwendung auf eingebetteten Systemen gedacht ist. Es ist ein Konglomerat aus mehreren Bibliotheksteilen, die alle unter freien Softwarelizenzen stehen, die sie leicht auf eingebetteten Produkten verwenden können.

Und schließlich das Paket "libstdc++-arm-none-eabi". Das ist ziemlich offensichtlich; es ist die C++-Bibliothek für den Cross-Compiler; für eingebettete ARM-Mikrocontroller.

Schritt 5: Die Linker-Datei

Die Linker-Datei
Die Linker-Datei
Die Linker-Datei
Die Linker-Datei

Lassen Sie uns ein Linker-Skript erstellen.

Ein wichtiger Teil oder Block in dieser Datei wäre der MEMORY-Befehl.

--- von sourceware.org:

Die Standardkonfiguration des Linkers ermöglicht die Zuweisung des gesamten verfügbaren Speichers. Sie können dies überschreiben, indem Sie den Befehl MEMORY verwenden. Der Befehl MEMORY beschreibt die Position und Größe von Speicherblöcken im Ziel. Sie können damit beschreiben, welche Speicherbereiche der Linker verwenden darf und welche Speicherbereiche er vermeiden muss. Sie können dann Abschnitte bestimmten Speicherbereichen zuweisen. Der Linker legt Abschnittsadressen basierend auf den Speicherbereichen fest und warnt vor zu vollen Bereichen. Der Linker mischt Abschnitte nicht so, dass sie in die verfügbaren Regionen passen. Ein Linker-Skript kann viele Verwendungen des MEMORY-Befehls enthalten, jedoch werden alle definierten Speicherblöcke so behandelt, als ob sie in einem einzigen MEMORY-Befehl spezifiziert wären. Die Syntax für MEMORY ist:

ERINNERUNG

{ name [(attr)]: ORIGIN = Herkunft, LENGTH = len … }

Das Beispiel im Artikel:

/* Definiere das Ende des RAM und das Limit des Stack-Speichers *//* (4KB SRAM auf der STM32F031x6-Zeile, 4096 = 0x1000) */ /* (RAM beginnt bei Adresse 0x20000000) _estack = 0x20001000;

ERINNERUNG

{ FLASH (rx): ORIGIN = 0x08000000, LENGTH = 32K RAM (rxw): ORIGIN = 0x20000000, LENGTH = 4K }

Wir müssen also herausfinden, wie viel FLASH (für unser Programm und Konstanten usw.) und wie viel RAM (für die Verwendung durch das Programm; Heap und Stack usw.) für unser spezielles Board erforderlich ist. Das wird ein bisschen interessant.

Die nette kleine Karte, die mit dem Nucleo geliefert wird, sagt, dass es 512 KByte Flash-Speicher und 80 KByte SRAM hat. Wenn es jedoch an USB angeschlossen wird, wird es als Dateisystem mit zwei Dateien gemountet, und sowohl der Dateimanager als auch GParted geben an, dass es über mehr als 540 Kbyte Speicherplatz verfügt. (RAM?).

ABER, wenn Sie versuchen, die beiden Dateien mit dem Dateimanager zu löschen, das Gerät zu trennen und dann erneut zu verbinden, werden die beiden Dateien immer noch angezeigt. (und der Dateimanager hat etwas erkannt, weil sich auf jeder Datei ein kleines "Schloss"-Symbol befindet.

Kommen wir also zu den Zahlen auf der Karte. Nun nehmen wir das obige Beispiel und konvertieren es in unser spezifisches Board.

Vielleicht möchten Sie so etwas wie diesen Online-Speicherkonverter verwenden, um von der allgemeinen KB zu einer bestimmten Anzahl von Bytes zu wechseln.

Dann möchten Sie vielleicht einen Online-Dezimal-zu-Hex-Konverter verwenden.

/* Definiere das Ende des RAM und das Limit des Stack-Speichers */

/* (4KB SRAM auf der STM32F031x6-Leitung, 4096 = 0x1000) *//* das Beispiel*/

/* Schritt 1: (80KB SRAM auf dem STM32F303RE, 81920 = 0x14000) *//* unser Board */

/* Schritt 2, füge die Hex-Größe zur Hex-Startadresse hinzu (unten). */

/* (RAM beginnt bei Adresse 0x20000000) */

_stack = 0x20001000; /* das Beispiel */

_stack = 0x20014000; /* unser Vorstand */

ERINNERUNG {

FLASH (rx): URSPRUNG = 0x08000000, LÄNGE = 512K

RAM (rxw): HERKUNFT = 0x20000000, LÄNGE = 80K

}

Nennen wir die obige Datei "linker.script.ld".

Schritt 6: Die Vektortabelle

Die Vektortabelle
Die Vektortabelle

Jetzt erstellen wir eine kleine Assembly-Datei (mit Direktiven), um einige sehr grundlegende Interrupt-Behandlungen durchzuführen. Wir folgen dem Beispiel des Artikels und erstellen eine Datei namens "core. S".

Auch hier ist der Inhalt der Beispieldatei, aber ich habe eine Änderung für unser spezielles Board vorgenommen:

// Diese Anleitung definiert Attribute unseres Chips und

// die Assemblersprache, die wir verwenden werden:.syntax unified /* Siehe unten nach diesem Codebereich */ /*.cpu cortex-m0 */ /*Kommentiere diese Zeile des Beispiels */.cpu cortex-m4 /* fügen Sie stattdessen den Cortex unseres Boards hinzu. siehe obiges Bild in diesem Schritt */ /*.fpu softvfp */ /* diese Zeile des Beispiels auskommentieren */.fpu vfpv4 /* stattdessen unsere Boards hinzufügen; es hat eine FPU */.thumb // Globale Speicherorte..global vtable.global reset_handler /* * Die aktuelle Vektortabelle. * Der Einfachheit halber sind nur die Größe des RAM und der 'Reset'-Handler * enthalten. */.type vtable, %object vtable:.word _estack.word reset_handler.size vtable,.-vtable

Hmm.. Keine '.align'-Richtlinie

Das ist jedoch nicht kritisch. Mehr dazu (vielleicht) später.

. Syntax vereinheitlicht

.syntax [vereinheitlicht | geteilt]

Diese Direktive legt die Befehlssatzsyntax fest, wie im Abschnitt ARM-Befehlssatz beschrieben

9.4.2.1 Befehlssatzsyntax Zwei leicht unterschiedliche Syntaxen werden für ARM- und THUMB-Befehle unterstützt. Der Standard, geteilt, verwendet den alten Stil, bei dem ARM- und THUMB-Befehle ihre eigene, separate Syntax hatten. Die neue, einheitliche Syntax, die über die.syntax-Direktive ausgewählt werden kann.

.fpu vfpv4

Der GCC-Compiler kann Binärdateien mit mehreren Gleitkomma-Optionen erzeugen: soft - geeignet für die Ausführung auf CPUs ohne FPU - Berechnungen werden in der Software durch vom Compiler generierte softfp durchgeführt - geeignet für die Ausführung auf CPUs mit oder ohne FPU - verwendet eine FPU, falls vorhanden. Für unseren speziellen Fall (Sie müssen Ihre eigenen Nachforschungen anstellen) entspricht die FPU dieses speziellen Boards vfpv4. Möglicherweise müssen Sie damit spielen. Oder belasse es sogar bei softfp.

. Daumen (gegen. Arm)

Diese ARM-Mikrocontroller haben tatsächlich eine Mischung aus Befehlssätzen. Einer ist ARM, ein anderer ist THUMB. Ein Unterschied sind 16-Bit-Befehle gegenüber 32-Bit-Befehlen. Somit weist diese Direktive den Compiler an, nachfolgende Anweisungen entweder als THUMB oder ARM zu behandeln.

Wir werden nur den Rest der Datei so nehmen, wie er ist, da diese Instructables noch nicht mit der Interrupt-gesteuerten Assemblerprogrammierung befasst sind.

Schritt 7: Die Assembly-Version eines 'Hello World'-Programms

Folgendes kann auch in die zuvor erstellte Datei "core. S" eingefügt werden. Dies ist wiederum aus dem Beispiel im Artikel.

/* * Der Reset-Handler. Beim Zurücksetzen aufgerufen. */.type reset_handler, %function reset_handler: // Setze den Stack-Pointer auf das Ende des Stack. // Der Wert '_estack' ist in unserem Linker-Skript definiert. LDR r0, =_estapel MOV sp, r0

// Setze einige Dummy-Werte. Wenn wir diese Werte sehen

// In unserem Debugger wissen wir, dass unser Programm // auf dem Chip geladen ist und funktioniert. LDR r7, =0xDEADBEEF MOVS r0, #0 main_loop: // Addiere 1 zum Register 'r0'. HINZUGEFÜGT r0, r0, #1 // Schleife zurück. B main_loop.size reset_handler,.-reset_handler

Der Kern des obigen Programms besteht also darin, ein erkennbares Muster in ein Kern-MCU-Register (in diesem Fall R7) und einen inkrementierenden Wert, der bei Null beginnt, in ein anderes Kern-MCU-Register (in diesem Fall R0) zu laden. Wenn wir den ausführenden Code durchlaufen, sollten wir das Dateninkrement von R0 sehen.

Wenn Sie die Instructables bezüglich des MSP432 und des TI-RSLK-Kurses / -Labors verfolgt haben, sollten Ihnen so ziemlich alle oben genannten Programme bekannt sein.

Die einzige neue Sache, die ich sehen kann, ist die Verwendung von "=" beim Laden von "DEADBEEF" in die Registrierung von R7. Das hatten wir nicht genutzt.

Die hier angehängte Datei "core. S" enthält nun den kompletten Quellcode.

Schritt 8: Kompilieren des Codes

Es ist Zeit, einige Kommandozeilen-Zeug zu tun. Endlich etwas Echtes.

Allerdings sind wir noch nicht ganz da. Wir müssen den im Artikel angegebenen Befehl erneut anpassen und an unsere eigene Situation anpassen.

Hier ist der Beispielcode:

arm-none-eabi-gcc -x Assembler-with-cpp -c -O0 -mcpu=cortex-m0 -mthumb -Wall core. S -o core.o

Wenn wir die gnu.org-Site für GCC aufrufen (in diesem Fall Version 7.3),

x

Das -x gibt die Sprache an. Andernfalls, wenn kein -x vorhanden ist, versucht der Compiler anhand der Dateierweiterung zu erraten. (in unserem Fall *. S).

Das obige Beispiel aus dem Artikel spezifiziert Assembler-mit-cpp, aber wir könnten einfach Assembler machen.

C

Das -c sagt kompilieren, aber nicht verknüpfen.

O0

Das -O dient zum Einstellen der Optimierungsstufe. Die Verwendung von -O0 (oh-zero) sagt "Kompilierungszeit reduzieren und Debuggen zu den erwarteten Ergebnissen führen. Dies ist die Standardeinstellung".

mcpu=cortex-m0

-mcpu gibt den Namen des Zielprozessors an. In unserem Fall wäre es cortex-m4.

mthumb

-mthumb gibt an, zwischen dem Generieren von Code auszuwählen, der ARM- und THUMB-Zustände ausführt.

Mauer

Die -Mauer ist natürlich sehr verbreitet und bekannt. Es schaltet alle Warnflaggen ein.

Schließlich haben wir am Ende des Befehls die Eingabedatei core. S und die Ausgabedatei core.o.

Hier ist die resultierende neue Befehlszeile, die unserem speziellen Fall entspricht.

arm-none-eabi-gcc -x Assembler -c -O0 -mcpu=cortex-m4 -mthumb -Wall core. S -o core.o

Und das zusammengestellt.

Schritt 9: Verknüpfen des Programms

Direkt aus dem Beispiel im Artikel haben wir dies:

arm-none-eabi-gcc core.o -mcpu=cortex-m0 -mthumb -Wall --specs=nosys.specs -nostdlib -lgcc -T./STM32F031K6T6.ld -o main.elf

Die meisten der oben genannten haben Sie gesehen. Unten ist, was es Neues gibt.

specs=nosys.specs

Dieser ist etwas schwierig zu erklären.

Es hat mit "Semihosting" und "Retargeting" zu tun, und es hat mit Input / Output zu tun. Es hat auch mit Systemaufrufen und Bibliotheken zu tun.

Typischerweise bieten eingebettete Systeme keine standardmäßigen Eingabe-/Ausgabegeräte. Dies würde sich auf System- oder Bibliotheksaufrufe auswirken (Beispiel: printf()).

Semihosting bedeutet, dass der Debugger (siehe Bild von Schritt 11 mit rot eingekreistem Debugger-Teil) einen speziellen Kanal hat und das Semihosting-Protokoll verwendet, und Sie können die Ausgabe von printf() auf dem Host-Rechner (über den Debugger) sehen.

Retargeting hingegen bedeutet, dass dieselben System- oder Bibliotheksaufrufe etwas anderes bedeuten. Sie machen etwas anderes, das für das eingebettete System sinnvoll ist. In gewisser Weise, sagen wir für printf(), gibt es eine neue Implementierung, eine neu ausgerichtete Implementierung dieser Funktion.

Abgesehen davon bedeutet --specs=nosys.specs, dass wir kein Semihosting durchführen. Das würde normalerweise bedeuten, dass wir ein Retargeting durchführen. Das bringt uns zur nächsten Flagge.

nostdlib

Die Linker-Option -nostdlib wird verwendet, um ein Programm zu verknüpfen, das eigenständig ausgeführt werden soll. -nostdlib impliziert die einzelnen Optionen -nodefaultlibs und -nostartfiles. Im Folgenden besprechen wir die beiden Optionen separat, aber die typischste Verwendung ist nur nostdlib für den One-Stop-Shopping. Beim Binden eines gehosteten Programms werden standardmäßig Standardsystembibliotheken wie libc gelinkt, wodurch das Programm Zugriff auf alle Standardfunktionen (printf, strlen und Freunde). Die Linker-Option -nodefaultlibs deaktiviert die Verknüpfung mit diesen Standardbibliotheken; die einzigen verlinkten Bibliotheken sind genau die, die Sie dem Linker explizit mit dem Flag -l nennen.

lgcc

libgcc.a ist eine Standardbibliothek, die interne Subroutinen bereitstellt, um Unzulänglichkeiten bestimmter Maschinen zu überwinden. Zum Beispiel enthält der ARM-Prozessor keinen Divisionsbefehl. Die ARM-Version von libgcc.a enthält eine Divisionsfunktion und der Compiler gibt bei Bedarf Aufrufe an diese Funktion aus.

T

Dies ist nur eine Möglichkeit, dem Linker mitzuteilen, dass er diese Datei als Linker-Skript verwenden soll. In unserem Fall lautet der Dateiname linker.script.ld.

o main.elf

Schließlich teilen wir dem Linker den Namen der endgültigen Ausgabe-Image-Datei mit, die in unser Gerät gebrannt/geflasht wird.

Hier ist unsere Version der vollständigen Befehlszeile, die für unsere spezielle Situation modifiziert wurde:

arm-none-eabi-gcc core.o -mcpu=cortex-m4 -mthumb -Wall --specs=nosys.specs -nostdlib -lgcc -T./linker.script.ld -o main.elf

Wir stellen sicher, dass sich die Skriptdatei und die Datei core.o beide im selben Verzeichnis befinden, in dem wir die obige Befehlszeile ausführen.

Und es verbindet sich ohne Probleme.

Ein Test

Wir laufen dann:

arm-keine-eabi-nm main.elf

und wir bekommen:

devchu@chubox:~/Development/Atollic/TrueSTUDIO/STM32_workspace_9.1$ arm-none-eabi-nm main.elf 20014000 A _estack 08000010 t main_loop 08000008 T reset_handler 08000000 T vtable

Sieht gut aus. Der Befehl arm-none-eabi-nm ist eine Möglichkeit, Symbole in Objektdateien aufzulisten.

Schritt 10: Testen der Verbindung zum STM32 Nucleo-64

TestenVerbindung zum STM32 Nucleo-64
TestenVerbindung zum STM32 Nucleo-64
TestenVerbindung zum STM32 Nucleo-64
TestenVerbindung zum STM32 Nucleo-64

Ihre erste Mission ist es, Ihr System dazu zu bringen, Ihr Entwicklungsboard zu sehen.

Verwenden von Windows

Für Windows habe ich mich entschieden, TrueSTUDIO von Atollic (kostenlose Version) zu installieren. Es war eine schmerzlose Installation und der Treiber wurde automatisch installiert, sodass ich st-link verwenden konnte, um die Verbindung zu testen. Nachdem ich TrueSTUDIO installiert hatte und der Gerätemanager das Gerät sah, habe ich die Texan/Stlink-Tools heruntergeladen, die in dem Bare-Metal-Artikel vorgeschlagen wurden, dem wir gefolgt sind. Ich habe den Ordner wieder direkt unter "C:\" platziert und wieder einige Links von meinem lokalen Cygwin-Home-Bin zu den Befehlen erstellt.

ln -s /c/STM32. MCU/stlink-1.3.0-win64/bin/st-info.exe ~/bin/st-info

Als ersten Test, um zu sehen, ob wir wirklich mit dem Gerät kommunizieren können, habe ich ausgeführt:

st-info --probe

Und zurückgekommen:

1 Stlink-Programmierer gefunden

Jetzt wissen wir also, dass wir unser Entwicklungsboard besprechen/abfragen können.

Verwendung von Linux

Für Linux brauchst du nicht wirklich einen Treiber. Aber für Debian müssen Sie die st-Tools aus dem Quellcode erstellen.

git-Klon

Stellen Sie sicher, dass libusb-1.0-0-dev installiert ist.

passende Liste | grep -E "*libusb.*dev*"

Das solltest du sehen:

libusb-1.0-0-dev/xenial, jetzt 2:1.0.20-1 amd64 [installiert]

oder etwas ähnliches.

Um es zu installieren:

sudo apt-get install libusb-1.0-0-dev

Beachten Sie, dass das obige nicht dasselbe ist wie:

sudo apt-get install libusb-dev

Das richtige fehlende libusb dev kann dazu führen, dass cmake Probleme hat.

CMake-Fehler: Die folgenden Variablen werden in diesem Projekt verwendet, aber sie sind auf NOTFOUND gesetzt. Bitte setzen Sie sie oder stellen Sie sicher, dass sie in den CMake-Dateien richtig gesetzt und getestet wurden: LIBUSB_INCLUDE_DIR (ADVANCED)

Wechseln Sie in das Stammverzeichnis des Projekts (…blah/blah /stlink). Mach ein "Make-Release".

Danach sollten sich die Tools unter ".. /build/Release" befinden.

Sie können dann "st-info --probe" ausführen. Hier ist der Ausgang mit angeschlossenem Nucleo, dann nicht.

devchu@chubox:~/Development/stlink$./build/Release/st-info --probeFound 1 Stlink-Programmierer Seriennummer: 303636414646353034393535363537 openocd: "\x30\x36\x36\x41\x46\x46\x35\x30\x34\ x39\x35\x35\x36\x35\x37" flash: 524288 (pagesize: 2048) sram: 65536 chipid: 0x0446 descr: F303 High Density Device devchu@chubox:~/Development/stlink$./build/Release/st- info --probe 0 Stlink-Programmierer gefunden devchu@chubox:~/Development/stlink$

Schritt 11: Verwenden wir GDB mit Linux

Lassen Sie uns GDB mit Linux verwenden
Lassen Sie uns GDB mit Linux verwenden
Lassen Sie uns GDB mit Linux verwenden
Lassen Sie uns GDB mit Linux verwenden

Wenn Sie all dies versucht haben und es so weit gekommen ist - großartig! Exzellent. Lass uns jetzt ein bisschen Spaß haben.

Wenn Sie diese ARM-Entwicklungsboards kaufen, sei es das MSP432 Launchpad von Texas Instruments oder dieses, über das wir gerade sprechen, das Nucleo-F303 (STM32 Nucleo-64), werden sie normalerweise bereits mit einem laufenden Programm geflasht geliefert ein blinkendes Programm, das auch das Drücken eines Schalters beinhaltet, um die Geschwindigkeit zu ändern, mit der die LED(s) blinken.

Bevor wir das so schnell überschreiben, wollen wir sehen, was es zu sehen und zu tun gibt.

Öffnen Sie unter Linux ein Terminal, wechseln Sie das Verzeichnis des gerade erstellten stlink-git-Projekts und suchen Sie das st-util-Tool.

devchu@chubox:~/Development/stlink$ find. -name st-util

./build/Release/src/gdbserver/st-util

Führen Sie dieses Tool aus. Da wir unsere Verbindung bereits mit st-info --probe getestet haben, sollten wir eine Ausgabe wie diese erhalten:

st-util 1.4.0-50-g7fafee2 2018-10-20T18:33:23 INFO common.c: Geräteparameter laden…. 2018-10-20T18:33:23 INFO common.c: Angeschlossenes Gerät ist: F303 High Density Device, ID 0x10036446 2018-10-20T18:33:23 INFO common.c: SRAM-Größe: 0x10000 Byte (64 KiB), Flash: 0x80000 Byte (512 KiB) in Seiten von 2048 Byte 2018-10-20T18:33:23 INFO gdb-server.c: Chip-ID ist 00000446, Core-ID ist 2ba01477. 2018-10-20T18:33:23 INFO gdb-server.c: Abhören bei *:4242…

Das ist der GDB-Server, der jetzt läuft, und er sieht unser Entwicklungsboard und, was noch wichtiger ist, er lauscht auf Port 4242 (dem Standardport).

Jetzt können wir den GDB-Client starten.

Öffnen Sie unter Linux ein anderes Terminal und geben Sie Folgendes ein:

arm-kein-eabi-gdb -tui

Das ist genau das gleiche wie das Ausführen von gdb ausschließlich über die Befehlszeile, es erzeugt jedoch stattdessen ein textbasiertes Terminal (ich vermute, dass es Flüche verwendet).

Wir haben den GDB-Client und den GDB-Server laufen. Der Client ist jedoch nicht mit dem Server verbunden. Im Moment weiß es nichts über unser Nucleo (oder Board deiner Wahl). Wir müssen es erzählen. Im Terminal sollte Ihre Eingabeaufforderung jetzt "(gdb)" sein. Eintreten:

Hilfe Ziel

Es wird Ihnen eine Liste geben. Beachten Sie, dass das gewünschte ist Target Extended-Remote - Verwenden Sie einen Remote-Computer über eine serielle Leitung.

Aber wir müssen ihm auch den Standort geben. Geben Sie an der Eingabeaufforderung (gdb) Folgendes ein:

(gdb) Ziel erweiterter Remote-Localhost:4242

Sie sollten eine Antwort wie diese erhalten:

(gdb) Ziel-Localhost mit erweiterter Ferne:4242

Remote-Debugging mit localhost:4242 0x080028e4 in ?? ()

In der Zwischenzeit haben wir auf dem Terminal, auf dem der st-util gdbserver ausgeführt wird, Folgendes erhalten:

2018-10-20T18:42:30 INFO gdb-server.c: 6 HW-Breakpoint-Register gefunden

2018-10-20T18:42:30 INFO gdb-server.c: GDB verbunden.

Schritt 12: Wiederholen wir unser Programm mit Windows und Flash

Lassen Sie uns mit Windows und Flash unser Programm wiederholen
Lassen Sie uns mit Windows und Flash unser Programm wiederholen
Lassen Sie uns unser Programm mit Windows und Flash wiederholen
Lassen Sie uns unser Programm mit Windows und Flash wiederholen
Lassen Sie uns unser Programm mit Windows und Flash wiederholen
Lassen Sie uns unser Programm mit Windows und Flash wiederholen

Die Schritte zum Ausführen des st-util gdbserver und des arm-none-eabi-gdb-Clients sind im Wesentlichen die gleichen wie im vorherigen Schritt. Sie öffnen zwei Terminals (cygwin, DOS cmd oder Windows Powershell), suchen den Speicherort der st-util und führen sie aus. Führen Sie im anderen Terminal den arm-none-eabi-gdb-Client aus. Der einzige Unterschied besteht darin, dass der Modus -tui (terminalbasierte Textansicht) höchstwahrscheinlich nicht unterstützt wird.

Wenn das obige in Windows funktioniert hat, müssen Sie wahrscheinlich aufhören (nur den Client). An dieser Stelle müssen Sie irgendwie den GDB-Client ausführen, in dem sich Ihre Build-Datei befindet ("core.out"), oder den gesamten Pfad zu dieser Datei als Argument zum GDB-Client hinzufügen.

Ich habe mein Leben vereinfacht, indem ich cygwin verwendet und Links von meinem lokalen $HOME//bin-Verzeichnis zu den beiden Tools erstellt habe.

Ok, wir haben wie zuvor kompiliert und verlinkt, und wir haben die Datei main.elf bereit zum Flashen.

Wir haben st-util in einem Fenster ausgeführt. Wir starten den GDB-Client neu, diesmal tun wir:

arm-none-eabi-gdb main.elf

Wir lassen es starten, warten auf die Eingabeaufforderung (gdb), führen den gleichen Verbindungsbefehl zum GDB-Server (st-util) aus und sind bereit, die ausführbare Datei zu flashen. Es ist sehr antiklimatisch:

(gdb) laden

Bei der Ausführung mit Cygwin-Terminals gibt es ein bekanntes Problem, bei dem manchmal Konsolenbefehle nicht ausgegeben werden. In unserem Fall war das Fenster, in dem der Server ausgeführt wurde, also völlig stumm. Derjenige, der den Client ausführt, auf dem wir die Last ausgeführt haben, gibt Folgendes aus:

Ladeabschnitt.text, Größe 0x1c lma 0x8000000Startadresse 0x8000000, Ladegröße 28 Übertragungsrate: 1 KB/s, 28 Bytes/Schreiben.

Schritt 13: Flashen mit Linux - lohnender:D

Flashen mit Linux - lohnender:D
Flashen mit Linux - lohnender:D

Schritt 14: Lass uns ein bisschen tiefer tauchen

Wenn Sie hierher kommen, ausgezeichnet. Lass uns weitermachen.

Warum schauen Sie nicht in die main.elf-Datei, die ausführbare Datei? Führen Sie Folgendes aus:

arm-none-eabi-objdump -d main.elf

Sie sollten eine Ausgabe wie diese sehen:

main.elf: Dateiformat elf32-littlearm

Demontage des Abschnitts.text:

08000000:

8000000: 00 40 01 20 09 00 00 08.@. ….

08000008:

8000008: 4802 ldr r0, [Stk, #8]; (8000014) 800000a: 4685 mov sp, r0 800000c: 4f02 ldr r7, [pc, #8]; (8000018) 800000e: 2000 Bewegungen r0, #0

08000010:

8000010: 3001 fügt r0 hinzu, #1 8000012: e7fd b.n 8000010 8000014: 20014000.word 0x20014000 8000018: deadbeef.word 0xdeadbeef

Welche kleinen Nuggets können wir aus der obigen Ausgabe erhalten?

Wenn Sie sich erinnern, als wir die Datei linker.script.ld besprochen und erstellt haben, haben wir festgestellt, dass diese ARM-Geräte RAM ab 0x20000000 und FLASH-Speicher ab 0x08000000 haben.

Somit können wir sehen, dass das Programm tatsächlich so ist, dass sich alles im FLASH-Speicher befindet.

Dann, oben, aber ein späterer Schritt, als wir den Abschnitt "Hello World" diskutierten, gab es eine Anweisung, bei der wir einen sofortigen, konstanten Literalwert ("0xDEADBEEF") in ein MCU-Kernregister ("R7") laden.

Die Aussage lautete:

LDR R7, =0xDEADBEEF

In unserem Code ist das die einzige Stelle, an der wir DEADBEEF überhaupt erwähnen. Nirgendwo sonst. Und doch, wenn Sie sich die obigen zerlegten / rekonstruierten Anweisungen usw. ansehen, gibt es mehr zu DEADBEEF, als wir dachten.

Also hat der Compiler/Linker irgendwie beschlossen, den Wert von DEADBEEF permanent in eine FLASH-Adresse an der Position 0x8000018 zu flashen. Und dann änderte der Compiler unsere obige LDR-Anweisung wie folgt:

LDR R7, [PC, #8]

Es hat sogar einen Kommentar für uns generiert. Wie schön. Und es sagt uns, den aktuellen Programmzählerwert (das PC-Register) zu nehmen, 0x8 zu diesem Wert hinzuzufügen, und dort wurde DEADBEEF gebrannt, und diesen Wert zu erhalten und in R7 zu stopfen.

Das bedeutet also auch, dass der Programmzähler (PC) auf die Adresse 0x8000010 zeigte, was der Beginn der main_loop ist, und dass der DEADBEEF-Wert an zwei Adressen nach dem Ende von main_loop sitzt.

Schritt 15: Abschließend ein kurzer Blick auf das laufende Programm

Auch wenn Sie GDB beenden, geben Sie den Befehl einfach erneut ein. Sie müssen ihm nicht einmal eine Datei geben; Wir flashen nicht mehr, sondern führen es einfach aus.

Nachdem Sie den GDB-Client wieder mit dem GDB-Server verbunden haben, an der (gdb)-Eingabeaufforderung:

(gdb) Inforegister

Sie sollten so etwas sehen:

r0 0x0 0

r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0x0 0 r8 0x0 0 r9 0x0 0 r10 0x0 0 r11 0x0 0 r12 0x0 0 sp 0x20014000 0x20014000ffr4

Geben Sie dann an der Eingabeaufforderung (gdb) Folgendes ein:

(gdb) weiter

Und sehr schnell STRG-C drücken. Das sollte das Programm pausieren. Geben Sie den Befehl "info registers" erneut ein.

Diesmal sieht es anders aus:

(gdb) Inforegister

r0 0x350ffa 3477498 r1 0x0 0 r2 0x0 0 r3 0x0 0 r4 0x0 0 r5 0x0 0 r6 0x0 0 r7 0xdeadbeef 3735928559 r8 0x0 0 r9 0x0 0 r10 0x0 0 r1000 0x0000ffx 16777216

Was ist passiert? Genau das, was wir wollten. DEADBEEF wurde in R7 geladen und R0 wurde (extrem schnell) inkrementiert. Wenn Sie es wiederholen, sehen Sie R0 erneut mit einem anderen Wert.

Schritt 16: Wir wollten ein schreibgeschütztes Array in Flash erstellen

Eine Möglichkeit, das Äquivalent eines Arrays mithilfe von Assembly und Direktiven zu erstellen, ist wie folgt:

.type myarray, %object // Der Name oder das Label 'myarray' ist als Objekttyp definiert.

myarray: // Dies ist der Beginn der Deklaration von 'myarray' // (woraus sie bestehen wird)..word 0x11111111 //der erste Member oder Wert, der in 'myarray' enthalten ist..word 0x22222222 //der zweite Wert (zusammenhängende Adressen)..word 0x33333333 //und so weiter..size myarray,.-myarray // der Compiler/Assembler weiß jetzt wo das Ende oder // die Grenze von 'myarray' ist.

Nachdem wir es nun im FLASH-Speicher eingerichtet haben, können wir es im Programm verwenden. Unten ist ein Teil:

LDR R1, myarray // dies lädt Daten, die an der ersten Stelle von 'myarray' enthalten sind.' // Das ist nicht das, was wir wollen.

LDR R1, =myarray // dies lädt den Standortwert selbst (die 1. Adresse), // nicht die daten.. // das ist was wir wollen.

MOV R2, #0 // R2 wird zählen, um sicherzustellen, dass wir nicht weglaufen

// Ende des Arrays. LDR R3, =myarrsize // R3 entspricht 'myarrsize'.

// R0 wird unsere Daten speichern

Hauptschleife:

LDR R0, [R1] // Laden Sie die Daten, auf die R1 zeigt ('myarray') in R0. CMP R2, R3 // Sind wir am Limit des Arrays? BEQ main_loop // Wenn wir es sind, sind wir fertig, also machen wir eine Endlosschleife.

ADD R2, #1 // Andernfalls können wir das Array weiter durchlaufen.

ADD R1, #4 // Füge 4 zu Register R1 hinzu, damit es richtig auf das nächste zeigt

// die Anschrift..

B main_loop // Schleife zurück.

Das Video geht all dies durch, und es ist ein Fehler darin. Das ist gut; es zeigt, dass es wichtig ist, Code auszuführen und zu debuggen. Es zeigt einen klassischen Fall des Verlassens des Endes eines Arrays.

Empfohlen: