Indholdsfortegnelse:

Del 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 trin
Del 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 trin

Video: Del 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 trin

Video: Del 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 trin
Video: Part 2 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 spin off Exploring The STM32 Nucleo 2024, November
Anonim
Image
Image

Fokus for denne Instructable er STM32 Nucleo mikrokontroller. Motivationen herfor for at kunne skabe et samlingsprojekt ud fra bare knogler. Dette vil hjælpe os med at dykke dybere og forstå MSP432 Launchpad-projektet (TI-RSLK), der allerede har været emne for flere instruktører.

Der er ikke særlig meget hjælp online til at oprette et projekt, der kun er til samling, til MSP432 ved hjælp af Code Composer Studio. Indtil nu har vi bare kopieret/indsat fra et allerede eksisterende montageprojekt. Denne tilgang har tjent os godt.

Men nu, for Lab 7, er vi stødt på lidt af et problem. Eller i det mindste en midlertidig hikke. Lab 7 introducerer finite-state-maskiner, og det første vi støder på er behovet for at oprette og bruge en række værdier. Da TI -kurset hovedsageligt bruger C -programmering - er dette ikke et problem. Men disse instruktører har fokuseret på samling, ikke C.

Da arrayet desuden har skrivebeskyttede værdier, ville det være godt at lægge det i flash-hukommelse, ikke RAM.

Der ser ud til at være meget mere hjælp online til montageprojekter ved hjælp af STM32 MCU, derfor begynder vi med denne Instructable, med det mål at bruge det indlærte, for derefter at ansøge om MSP432 og Code Composer Studio.

På vejen til det mål har vi også fået erfaring med endnu en populær mikrokontroller.

Trin 1: Indledende test af enhed

Indledende test af enheden
Indledende test af enheden
Indledende test af enheden
Indledende test af enheden
Indledende test af enheden
Indledende test af enheden

Igen, hvorfor især vælge STM32 Nucleo?

Ærligt talt? Fordi jeg ledte efter gode artikler om bare-metal-samlingsprojekter til ARM-controllere, og jeg stødte på denne serie. Og også fordi STM32 ser ud til at være en populær MCU.

Jeg lavede nogle undersøgelser (der er mange versioner at vælge imellem - se billedet ovenfor), men i sidste ende blev det, hvad jeg egentlig kan få, da jeg skulle bruge Amazon (i USA).

Den kommer i en enkel, men professionel pakke, med nogle opstartsinstruktioner. Det var lidt sjovt at se, at demoen, der blev brændt ind i controlleren, var næsten præcis, hvad vi har gjort i tidligere Instructables - en LED blinker og ændrer hastigheden i henhold til et tryk på en knap.

Det ser ud til, at dette udviklingsbord ligner meget MSP432, idet der er 2 lysdioder og en bruger-trykknap. MSP432 har 2 brugerknapper.

Som du kan se på billederne, blev jeg lidt overrasket over, at brættet har en mini og ikke en mikro -USB. Var nødt til at løbe ud for at købe en ledning.

En anden god test er, at når du slutter den til din computer (jeg bruger en Linux -boks), vises den i min filhåndtering som et filsystem, kaldet "NODE_F303RE". Åbning, der afslører to filer, en HTML og en tekst.

Det er det, men i det mindste siger det også, at tilslutning virker ret let.

Nu er vi klar til at begynde.

Jeg vil forsøge ikke at gentage nogen af de gode oplysninger fra IVONOMICON Bare Metal -artikelserien, men snarere udvide den.

Trin 2: Det væsentlige

Det første, vi har brug for, er en compiler.

Og så har vi brug for en fejlfinding:

devchu@chubox: ~ $ sudo apt-get install gdb-arm-none-eabiLæsningspakkelister … Udført Bygning af afhængighedstræ Læsning af statens oplysninger … Udført Følgende NYE pakker installeres: gdb-arm-none-eabi 0 opgraderet, 1 nyligt installeret, 0 for at fjerne og 8 ikke opgraderet. Har brug for at få 2, 722 kB arkiver. Efter denne operation vil der blive brugt 7, 738 kB ekstra diskplads. Få: 1 https://us.archive.ubuntu.com/ubuntu xenial/universe amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] Hentede 2, 722 kB i 1s (1, 988 kB/s) Valg af tidligere ikke-valgt pakke gdb-arm-none-eabi. (Læser database … 262428 filer og mapper i øjeblikket installeret.) Forbereder udpakning…/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb… Udpakning af gdb-arm-none-eabi (7.10-1ubuntu3+9)… Behandler udløsere til man-db (2.7.5-1) … Opsætning af gdb-arm-none-eabi (7.10-1ubuntu3+9) …

Trin 3: Essentials - Windows

Ovenstående trin antog, at vi bruger Linux. Hvad hvis vi bruger Windows?

Du kan gå til armen Developer -webstedet, og der er flere tilgængelige downloadmuligheder. Jeg bruger en Windows 8 -maskine.

Under installationen valgte jeg at installere det på root "C: \" - drevet i stedet for programfiler, bare fordi jeg også bruger cygwin, og det var lettere at oprette et link fra min lokale bin til en root C: mappe end alle de rod i stien til programfiler (med mellemrum osv.).

Således ser mit cygwin -miljø og sti osv. Sådan ud:

C: / cygwin64 / home / bin / arm-none-eabi-gcc, hvor arm-none-eabi-gcc er et link til C: / GNUToolsArmEmbedded / 7.2018.q2.update / bin / arm-none-eabi- gcc.

Jeg oprettede derefter en "dev" -mappe under cygwin home, og det var her, jeg placerede core. S -filen og kørte kommandoen compiler. (se yderligere nedenfor for kompilatoren).

Jeg gjorde præcis det samme for gdb (arm-none-eabi-gdb).

Trin 4: Hvad er det væsentlige

Så hvad er "gcc-arm-none-eabi"?

GNU -kompilatoren (GCC) vil kompilere programmeringssprog (som C) til indfødt kode til den maskine, den kører på. For eksempel, hvis du skulle kompilere noget C -kode ved hjælp af GCC på din Windows -maskine, ville den blive bygget til at køre på Windows -maskinen. Den genererede eksekverbare vil ikke (typisk) køre på ARM-mikrokontrolleren.

Så for at bygge programmer, der skal downloades og brændes i ARM-mikrokontrolleren (i vores nuværende tilfælde ville det være STM32 Nucelo), skal vi give GCC noget andet: muligheden for at "krydskompilere". Det vil sige evnen til at generere en eksekverbar, ikke for sit oprindelige system (og processor), men for målsystemet (ARM-mikrokontrolleren). Det er her "gcc-arm-none-eabi" spiller ind.

Så hvad er så "gdb-arm-none-eabi"?

Når vi har downloadet og brændt (flashet) den nygenererede eksekverbare fil i mikro-controlleren, vil vi sandsynligvis gerne fejle den-trin for trin gennem linje i koden. GDB er gnu -fejlfinderen, og den har også brug for en måde at gøre sit arbejde på, men målrettet mod et andet system.

Således er gdb-arm-none-eabi for GDB, hvad gcc-arm-none-eabi er for GCC.

En anden foreslået pakkeinstallation var "libnewlib-arm-none-eabi". Hvad er den?

Newlib er et C -bibliotek og et matematisk bibliotek beregnet til brug på integrerede systemer. Det er et konglomerat af flere biblioteksdele, alle under gratis softwarelicenser, der gør dem let anvendelige på integrerede produkter.

Og endelig pakken "libstdc ++-arm-none-eabi". Den er ret indlysende; det er C ++ bibliotek til kryds-kompilatoren; til indlejrede ARM mikrokontroller.

Trin 5: Linker -filen

Linker -filen
Linker -filen
Linker -filen
Linker -filen

Lad os oprette et linker script.

En nøgledel eller blok i denne fil ville være kommandoen MEMORY.

--- fra sourceware.org:

Linkerens standardkonfiguration tillader allokering af al tilgængelig hukommelse. Du kan tilsidesætte dette ved at bruge kommandoen MEMORY. MEMORY -kommandoen beskriver placeringen og størrelsen af hukommelsesblokke i målet. Du kan bruge den til at beskrive, hvilke hukommelsesområder der kan bruges af linkeren, og hvilke hukommelsesområder den skal undgå. Du kan derefter tildele sektioner til bestemte hukommelsesområder. Linkeren indstiller sektionsadresser baseret på hukommelsesregionerne og advarer om områder, der bliver for fulde. Linkeren vil ikke blande sektioner rundt for at passe ind i de tilgængelige regioner. Et linker -script kan indeholde mange anvendelser af MEMORY -kommandoen, men alle definerede hukommelsesblokke behandles som om de var angivet inde i en enkelt MEMORY -kommando. Syntaksen for MEMORY er:

HUKOMMELSE

{navn [(attr)]: Oprindelse = oprindelse, LÆNGDE = len…}

Eksemplet i artiklen:

/* Definer slutningen på RAM og grænse for stackhukommelse* //* (4KB SRAM på linjen STM32F031x6, 4096 = 0x1000)*//* (RAM starter på adressen 0x20000000) _estack = 0x20001000;

HUKOMMELSE

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

Så vi er nødt til at finde ud af, hvor meget FLASH (til vores program og konstanter osv.) Og hvor meget RAM (til brug af programmet; bunke og stak osv.) Til vores særlige board. Dette bliver lidt interessant.

Det fine lille kort, der følger med Nucleo, siger, at det har flashhukommelse, er 512 Kbytes, og SRAM er 80 Kbytes. Når den tilsluttes USB, bliver den imidlertid monteret som et filsystem med to filer, og både filhåndteringen og GParted angiver, at den har over 540+ Kbytes plads. (VÆDDER?).

MEN, forsøger at slette de to filer ved hjælp af filhåndteringen, afbryde forbindelsen og derefter tilslutte enheden igen, viser de to filer stadig. (og filhåndtereren genkendte noget, fordi der er et lille "lås" -ikon på hver fil.

Så lad os gå med tallene på kortet. Så nu tager vi ovenstående eksempel og konverterer det til vores specifikke bord.

Du vil måske bruge noget som denne online hukommelsesomformer til at gå fra den generelle KB til et bestemt antal bytes.

Så vil du måske bruge en online decimal til hex -konverter.

/ * Definer slutningen på RAM og grænsen for stackhukommelse */

/* (4KB SRAM på linjen STM32F031x6, 4096 = 0x1000)* //* eksemplet*/

/ * trin 1: (80KB SRAM på STM32F303RE, 81920 = 0x14000) * // * vores board */

/* trin 2, tilføj hex -størrelsen til hex -startadressen (nedenfor). */

/ * (RAM starter på adressen 0x20000000) */

_estack = 0x20001000; / * eksemplet */

_estack = 0x20014000; / * vores bestyrelse */

MINNE {

FLASH (rx): Oprindelse = 0x08000000, LÆNGDE = 512K

RAM (rxb): Oprindelse = 0x20000000, LÆNGDE = 80K

}

Lad os kalde ovenstående fil "linker.script.ld".

Trin 6: Vektortabellen

Vektorbordet
Vektorbordet

Nu skal vi oprette en lille forsamlingsfil (med direktiver) til at lave en meget grundlæggende afbrydelse. Vi følger artiklens eksempel og opretter en fil med navnet "core. S".

Igen, her er eksempelfilens indhold, men jeg lavede en ændring for vores specifikke bord:

// Disse instruktioner definerer attributter for vores chip og

// det samlingssprog, vi vil bruge:.syntax unified /*Se nedenfor efter dette kodeområde* //*.cpu cortex-m0* / /*kommenter denne linje i eksemplet* /.cpu cortex-m4 /* tilføj i stedet vores bestyrelses cortex. se billedet ovenfor i dette trin * / /*.fpu softvfp * / / *kommenter denne linje i eksemplet * /.fpu vfpv4 / *tilføj i stedet vores bestyrelses; den har en FPU */.thumb // Global hukommelsesplaceringer..global vtable.global reset_handler / * * Den faktiske vektortabel. * Kun størrelsen på RAM og 'reset' handler er * inkluderet, for enkelheds skyld. */.type vtable, %object vtable:.word _estack.word reset_handler.størrelse vtable,.-vtable

Hmm.. Nej '.align' direktiv

Det er dog ikke kritisk. Mere om det (måske) senere.

.syntax forenet

.syntax [forenet | delt op]

Dette direktiv angiver instruktionssæt-syntaksen som beskrevet i afsnittet ARM-instruktionssæt

9.4.2.1 Syntaks for instruktionssæt To lidt forskellige syntakser understøtter ARM- og THUMB -instruktioner. Standarden, delt, bruger den gamle stil, hvor ARM- og THUMB -instruktioner havde deres egne, separate syntakser. Den nye, forenede syntaks, som kan vælges via.syntax -direktivet.

.fpu vfpv4

GCC -kompilatoren kan producere binære filer med flere muligheder vedrørende flydende punkt: blød - egnet til at køre på CPU'er uden FPU - beregninger udføres i software af kompilatorgenereret softfp - egnet til at køre på CPU'er med eller uden FPU - vil bruge en FPU, hvis den er til stede. For vores specifikke sag (du bliver nødt til at lave din egen research), er denne bestyrelses FPU i overensstemmelse med vfpv4. Du skal muligvis lege med dette. Eller lad det endda stå på softfp.

.tommel (vs.arm)

Disse ARM mikrokontroller har faktisk en blanding af instruktionssæt. Den ene er ARM, den anden er TOMMEL. En forskel er 16-bit instruktioner vs 32-bit instruktioner. Således fortæller dette direktiv kompilatoren om at behandle efterfølgende instruktioner som enten THUMB eller ARM.

Vi tager bare resten af filen som den er, da disse instruktioner endnu ikke er gået ned i afbrydelsesdrevet samlingsprogrammering.

Trin 7: Samlingsversionen af et 'Hello World' -program

Det følgende kan også gå ind i den tidligere oprettede "core. S" -fil. Dette er igen fra eksemplet i artiklen.

/ * * Reset handler. Opkaldt ved nulstilling. */.type reset_handler, %function reset_handler: // Indstil stabelmarkøren til enden af stakken. // Værdien '_estack' er defineret i vores linker script. LDR r0, = _stack MOV sp, r0

// Indstil nogle dummy -værdier. Når vi ser disse værdier

// i vores fejlfinding ved vi, at vores program // er indlæst på chippen og fungerer. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // Tilføj 1 for at registrere 'r0'. ADDS r0, r0, #1 // Sløjfe tilbage. B main_loop.size reset_handler,.-Reset_handler

Så det, der er fokus på ovenstående program, er at indlæse et genkendeligt mønster i et kerne -MCU -register (i dette tilfælde R7) og en stigende værdi, der starter ved nul, til et andet kerne -MCU -register (i dette tilfælde R0). Hvis vi går igennem den eksekverende kode, skulle vi se R0s datastigning.

Hvis du har fulgt med instrukserne vedrørende MSP432 og TI-RSLK-kurset/laboratorierne, burde stort set alle ovenstående programmer være velkendte for dig.

Den eneste nye ting, jeg kan se, er brugen af "=" ved indlæsning af "DEADBEEF" for at registrere R7. Det havde vi ikke brugt.

Filen "core. S", der er vedhæftet her, indeholder nu den komplette kilde.

Trin 8: Kompilering af koden

Det er på tide at lave nogle kommandolinjestoffer. Noget rigtigt, endelig.

Vi er dog ikke helt der. Vi skal igen justere kommandoen i artiklen og ændre den til vores egen situation.

Her er eksempelkoden:

arm -none -eabi -gcc -x assembler -with -cpp -c -O0 -mcpu = cortex -m0 -mumbal -Vægkerne. S -o core.o

Hvis vi går til gnu.org -webstedet for GCC, (i dette tilfælde version 7.3),

x

-X er at angive sproget. Ellers hvis nej -x, så vil kompilatoren forsøge at gætte ved hjælp af filtypen. (i vores tilfælde, *. S).

Ovenstående eksempel fra artiklen angiver assembler-with-cpp, men vi kunne bare lave assembler.

c

-C siger kompilér, men forbind ikke.

O0

-O er at indstille optimeringsniveauet. Brug af -O0 (åh -nul) siger "reducer kompileringstid og få fejlfinding til at producere de forventede resultater. Dette er standard".

mcpu = cortex-m0

-Mcpu angiver navnet på målprocessoren. I vores tilfælde ville det være cortex-m4.

tommelfinger

-Mthumb angiver valg mellem generering af kode, der udfører ARM- og THUMB -tilstande.

Væg

-Væggen er naturligvis meget almindelig og velkendt. Det tænder alle advarselsflag.

Endelig har vi i slutningen af kommandoen inputfilkernen S og outputfilen core.o.

Her er den resulterende nye kommandolinje, der passer til vores specifikke sag.

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

Og det blev samlet.

Trin 9: Tilknytning af programmet

Direkte fra eksemplet i artiklen har vi dette:

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

De fleste af de ovenstående har du set. Nedenfor er hvad der er nyt.

specs = nosys.specs

Denne er lidt vanskelig at forklare.

Det har at gøre med "semihosting" og "retargeting", og det har at gøre med input / output. Det har også at gøre med systemopkald og biblioteker.

Typisk leverer integrerede systemer ikke standard input/output -enheder. Dette vil påvirke system- eller bibliotekopkald (eksempel: printf ()).

Semihosting betyder, at fejlfindingsværktøjet (se trin 11 -billede med fejlfindingsdel cirkuleret i rødt) har en særlig kanal og bruger semihosting -protokollen, og du kan se outputf af printf () på værtsmaskinen (via debuggeren).

Retargeting betyder derimod, at de samme system- eller bibliotekopkald betyder noget andet. De gør noget andet, der giver mening for det integrerede system. På en måde, siger for printf (), er der en ny implementering, en retargetet implementering af denne funktion.

Når alt dette er sagt, betyder --specs = nosys.specs, at vi ikke vil semihostere. Det ville normalt så betyde, at vi målretter igen. Det bringer os til det næste flag.

nostdlib

Linkerindstillingen -nostdlib bruges til at linke et program, der er beregnet til at køre selvstændigt. -nostdlib indebærer de individuelle muligheder -nodefaultlibs og -nostartfiles. Nedenfor diskuterer vi de to muligheder separat, men den mest typiske anvendelse er bare nostdlib til one-stop-shopping. Når du linker et hostet program, er standard systembiblioteker som libc som standard forbundet, hvilket giver programmet adgang til alle standardfunktioner (printf, strlen og venner). Linkerindstillingen -nodefaultlibs deaktiverer forbindelse med disse standardbiblioteker; de eneste biblioteker, der er knyttet, er præcis dem, du eksplicit navngiver til linkeren ved hjælp af -l -flag.

lgcc

libgcc.a er et standardbibliotek, der giver interne underrutiner til at overvinde mangler ved bestemte maskiner. For eksempel inkluderer ARM -processoren ikke en divisionsinstruktion. ARM -versionen af libgcc.a inkluderer en divisionsfunktion, og kompilatoren sender opkald til den funktion, hvor det er nødvendigt.

T

Dette er bare en måde at fortælle linkeren om at bruge denne fil som linker script. I vores tilfælde er filnavnet linker.script.ld.

o main.elf

Endelig fortæller vi linkeren, hvad navnet på den endelige outputbilledfil vil blive brændt/blinket ind i vores enhed.

Her er vores version af den komplette kommandolinje, ændret til vores specifikke situation:

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

Vi sørger for, at scriptfilen og core.o-filen begge er i den samme mappe, hvor vi kører ovenstående kommandolinje.

Og det forbinder uden problemer.

A Check

Vi kører derefter:

arm-none-eabi-nm main.elf

og vi får:

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

Ser godt ud. Arm-none-eabi-nm-kommandoen er en måde at liste symboler på inden for objektfiler.

Trin 10: Testforbindelse til STM32 Nucleo-64

Test Tilslutning til STM32 Nucleo-64
Test Tilslutning til STM32 Nucleo-64
Testning Tilslutning til STM32 Nucleo-64
Testning Tilslutning til STM32 Nucleo-64

Din første mission, hvis du vælger at acceptere det, er at få dit system til at se dit udviklingstavle.

Brug af Windows

Til Windows besluttede jeg at installere TrueSTUDIO fra Atollic (gratis version). Det var en smertefri installation, og den installerede automatisk driveren, så jeg kunne bruge st-link til at teste forbindelsen. Da jeg installerede TrueSTUDIO, og enhedsadministratoren så enheden, downloadede jeg de texan/stlink -værktøjer, der blev foreslået af Bare Metal -artiklen, vi har fulgt. Jeg placerede igen mappen direkte under "C: \", og oprettede igen nogle links fra min lokale cygwin -bakke til kommandoerne.

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

Som en indledende test for at se, om vi virkelig kan kommunikere med enheden, løb jeg:

st-info --probe

Og kom tilbage:

Fundet 1 stlink programmerere

Så nu ved vi, at vi kan tale/forespørge på vores udviklingstavle.

Brug af Linux

Til linux behøver du ikke rigtig en driver. Men for Debian skal du bygge de st værktøjer fra kilden.

git -klon

Sørg for, at du har installeret libusb-1.0-0-dev.

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

Du bør se:

libusb-1.0-0-dev/xenial, nu 2: 1.0.20-1 amd64 [installeret]

eller noget i den stil.

Sådan installeres det:

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

Bemærk, at ovenstående ikke er det samme som:

sudo apt-get install libusb-dev

Den korrekte manglende libusb dev kan få cmake til at have problemer.

CMake -fejl: Følgende variabler bruges i dette projekt, men de er indstillet til NOTFOUND. Indstil dem, eller sørg for, at de er indstillet og testet korrekt i CMake -filerne: LIBUSB_INCLUDE_DIR (ADVANCED)

Skift til projektets rodmappe (… blah /blah /stlink). Lav en "make release".

Efter det er bygget, skal værktøjerne være under ".. /build /Release".

Du kan derefter køre "st-info --probe". Her er output med Nucleo tilsluttet, så ikke.

devchu@chubox: ~/Development/stlink $./build/Release/st-info --probeFundet 1 stlink programmerere seriel: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "flash: 524288 (siderstørrelse: 2048) sram: 65536 chipid: 0x0446 descr: F303 enhed med høj densitet devchu@chubox: ~/Development/stlink $./build/Release/st- info --probe Fundet 0 stlink programmerere devchu@chubox: ~/Development/stlink $

Trin 11: Lad os bruge GDB med Linux

Lad os bruge GDB med Linux
Lad os bruge GDB med Linux
Lad os bruge GDB med Linux
Lad os bruge GDB med Linux

Hvis du har prøvet alt dette, og du er nået så langt - fantastisk! Fremragende. Lad os have det lidt sjovt nu.

Når du køber disse ARM-udviklingsbrætter, uanset om de er MSP432 Launchpad fra Texas Instruments, eller denne vi diskuterer nu, Nucleo-F303 (STM32 Nucleo-64), ankommer de normalt allerede blinket med et kørende program, typisk noget blinkende program, der også inkluderer at trykke på en kontakt for at ændre den hastighed, hvormed LED'erne blinker.

Inden vi er så hurtige til at overskrive det, lad os se, hvad der er at se og gøre.

Med Linux skal du åbne en terminal, ændre bibliotek på det stlink git-projekt, som vi lige har bygget, og finde st-util-værktøjet.

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

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

Kør det værktøj. Da vi allerede tidligere har testet vores forbindelse med st-info --probe, burde vi få noget output sådan:

devchu@chubox: ~/Development/stlink $./build/Release/src/gdbserver/st-util

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 INFO fælles. c: Indlæser enhedsparametre…. 2018-10-20T18: 33: 23 INFO fælles. C: Enhed tilsluttet er: F303 enhed med høj densitet, id 0x10036446 2018-10-20T18: 33: 23 INFO fælles. C: SRAM-størrelse: 0x10000 bytes (64 KiB), Flash: 0x80000 bytes (512 KiB) på sider med 2048 bytes 2018-10-20T18: 33: 23 INFO gdb-server.c: Chip-ID er 00000446, Core ID er 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: Lytning på *: 4242 …

Det er GDB -serveren, der kører nu, og den ser vores udviklingstavle, og endnu vigtigere, den lytter på port 4242 (standardporten).

Nu er vi klar til at fyre GDB -klienten op.

I Linux skal du åbne en anden terminal, indtaste denne:

arm-none-eabi-gdb -tui

Det er bare det samme som at køre gdb strengt kommandolinje, men det producerer i stedet en tekstbaseret terminal (mit gæt er, at den bruger forbandelser).

Vi har GDB -klienten og GDB -serveren kørende. Klienten er dog ikke forbundet til serveren. I øjeblikket ved den intet om vores Nucleo (eller bord efter eget valg). Vi er nødt til at fortælle det. I terminalen skal din prompt nu være "(gdb)". Gå ind:

hjælp mål

Det vil give dig en liste. Bemærk, at den, vi ønsker, er target extended -remote - Brug en fjerncomputer via en seriel linje.

Men vi er også nødt til at give det placeringen. Så indtast ved prompten (gdb):

(gdb) mål udvidet-ekstern lokal vært: 4242

Du bør få et svar tilbage sådan:

(gdb) mål udvidet-ekstern lokal vært: 4242

Fjernfejl ved hjælp af localhost: 4242 0x080028e4 i ?? ()

I mellemtiden fik vi dette på terminalen, der kører st-util gdbserver:

2018-10-20T18: 42: 30 INFO gdb-server.c: Fundet 6 hw breakpoint-registre

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

Trin 12: Lad os gentage, med Windows og flash vores program

Lad os gentage, med Windows og Flash vores program
Lad os gentage, med Windows og Flash vores program
Lad os gentage, med Windows og Flash vores program
Lad os gentage, med Windows og Flash vores program
Lad os gentage, med Windows og Flash vores program
Lad os gentage, med Windows og Flash vores program

Trinnene til at køre st-util gdbserver og arm-none-eabi-gdb-klienten er i det væsentlige de samme som vi gjorde under det foregående trin. Du åbner to terminaler (cygwin, DOS cmd eller Windows Powershell), finder placeringen af st-util, kør den. I den anden terminal køres arm-none-eabi-gdb-klienten. Den eneste forskel er, at tilstanden -tui (terminalbaseret tekstvisning) højst sandsynligt ikke understøttes.

Hvis ovenstående fungerede i Windows, skal du sandsynligvis stoppe (kun klienten). På dette tidspunkt skal du på en eller anden måde køre GDB -klienten, hvor din build -fil er ("core.out"), eller tilføje hele stien til filen som et argument til GDB -klienten.

Jeg forenklede mit liv ved at bruge cygwin og oprette links fra mit lokale $ HOME // bin bibliotek, hvor begge disse værktøjer findes.

Ok, vi har samlet og linket ligesom før, og vi har filen main.elf klar til at blive flashet.

Vi har st-util kørende i et vindue. Vi genstarter GDB-klienten, denne gang gør vi:

arm-none-eabi-gdb main.elf

Vi lader det starte, venter på (gdb) -prompten, laver vores samme forbindelseskommando til GDB-serveren (st-util), og vi er klar til at blinke den eksekverbare. Det er meget anti-klimatisk:

(gdb) belastning

Når der køres med cygwin -terminaler, er der et kendt problem med, at engangskonsolkommandoer ikke udsendes. Så i vores tilfælde var vinduet, der kører serveren, helt stille. Den, der kører klienten, hvor vi kørte belastningen, udsender dette:

Indlæser sektion.tekst, størrelse 0x1c lma 0x8000000 Startadresse 0x8000000, belastningsstørrelse 28 Overførselshastighed: 1 KB/sek, 28 bytes/skriv.

Trin 13: Blinker med Linux - Mere belønning: D

Blinker med Linux - Mere belønning: D
Blinker med Linux - Mere belønning: D

Trin 14: Lad os dykke lidt dybere

Hvis du kom hertil, fremragende. Lad os gå videre.

Hvorfor ikke kigge inde i main.elf -filen, den eksekverbare? Kør følgende:

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

Du skal se et output sådan noget som dette:

main.elf: filformat elf32-littlearm

Afmontering af sektion.tekst:

08000000:

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

08000008:

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

08000010:

8000010: 3001 tilføjer r0, #1 8000012: e7fd b.n 8000010 8000014: 20014000.word 0x20014000 8000018: deadbeef.word 0xdeadbeef

Hvilke små nuggets kan vi få fra ovenstående output?

Hvis du husker tilbage, da vi diskuterede og oprettede filen linker.script.ld, oplyste vi, at disse ARM -enheder har RAM, der starter ved 0x20000000, og at FLASH -hukommelsen starter med 0x08000000.

Således kan vi se, at programmet faktisk er sådan, at det hele findes i FLASH -hukommelse.

Derefter, ovenfor, men et senere trin, da vi diskuterede "Hello World" -delen, var der en erklæring, hvor vi indlæser en umiddelbar, konstant, bogstavelig værdi ("0xDEADBEEF") i et MCU -kerneregister ("R7").

Erklæringen lød:

LDR R7, = 0xDEADBEEF

I vores kode er det det eneste sted, hvor vi selv nævner DEADBEEF. Intet andet sted. Og alligevel, hvis du ser på ovenstående demonterede/rekonstruerede instruktioner osv., Er der mere relateret til DEADBEEF, end vi troede, vi gjorde.

Så kompilatoren/linkeren besluttede på en eller anden måde permanent at blinke værdien af DEADBEEF til en FLASH -adresse på stedet 0x8000018. Og så ændrede kompilatoren vores ovenstående LDR -instruktion til at være:

LDR R7, [PC, #8]

Det genererede endda en kommentar til os. Hvor fint. Og det fortæller os at tage den aktuelle programtællerværdi (pc -registret), tilføje 0x8 til den værdi, og det er her DEADBEEF er blevet brændt, og få den værdi og fylde den i R7.

Så det betyder også, at programtælleren (PC) pegede på adressen 0x8000010, som er starten på main_loop, og at DEADBEEF -værdien sidder på to adresser efter afslutningen af main_loop.

Trin 15: Endelig et kort kig på programkørslen

Selvom du afslutter GDB, skal du bare indtaste kommandoen igen. Du behøver ikke engang at give den nogen fil; vi blinker ikke længere, bare kører det.

Når du har tilsluttet GDB-klienten til GDB-serveren igen, ved kommandoprompten (gdb):

(gdb) inforegistre

Du bør se noget i stil med dette:

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 0x20014000 lr 0xffffffff 4294967295

Men indtast derefter ved prompten (gdb):

(gdb) fortsæt

Og ramte meget hurtigt CTRL-C. Det burde stoppe programmet. Indtast kommandoen "info registre" igen.

Denne gang ser det anderledes ud:

(gdb) inforegistre

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 r11 0x0 0 r10 0ff 000000 0x100000 0x100000 0x100000 0x100000 0x100000 0x100000 0x100000 0x100000 0x100000 0x100000 00x 0000 0000 0000 00000 16777216

Hvad skete der? Præcis hvad vi ville. DEADBEEF blev indlæst i R7, og R0 har været (ekstremt hurtig) stigende. Hvis du gentager, ser du R0 igen med en anden værdi.

Trin 16: Vi ønskede at oprette et skrivebeskyttet array i Flash

En måde at skabe ækvivalent til en matrix ved hjælp af samling og direktiver er som følger:

.type myarray, %object // navnet eller etiketten 'myarray' er defineret som en objekttype.

myarray: // dette er starten på erklæringen om 'myarray' // (hvad den vil bestå af)..word 0x11111111 // det første medlem eller den værdi, der er indeholdt i 'myarray'..word 0x22222222 // den anden værdi (sammenhængende adresser)..word 0x33333333 // og så videre..størrelse myarray,.-myarray // kompilatoren/assembler ved nu, hvor slutningen eller // grænsen for 'myarray'.

Nu hvor vi har konfigureret det i FLASH -hukommelse, kan vi bruge det i programmet. Nedenfor er en portion:

LDR R1, myarray // dette indlæser data indeholdt på 1. placering af 'myarray'. ' // det er ikke det, vi ønsker.

LDR R1, = myarray // dette indlæser selve placeringsværdien (den første adresse), // ikke data.. // det her er hvad vi vil.

MOV R2, #0 // R2 holder en optælling for at sikre, at vi ikke går afsted

// slut på array. LDR R3, = myarrsize // R3 vil svare til 'myarrsize'.

// R0 gemmer vores data

main_loop:

LDR R0, [R1] // Indlæs de data, som R1 ('myarray') peger på, i R0. CMP R2, R3 // Er vi ved grænsen for array? BEQ main_loop // Hvis vi er, er vi færdige, så vi går bare i loop for evigt.

TILFØJ R2, #1 // Ellers kan vi blive ved med at gentage gennem array.

TILFØJ R1, #4 // Tilføj 4 for at registrere R1, så det peger korrekt til næste

// adresse..

B main_loop // Sløjfe tilbage.

Videoen går igennem alt dette, og der er en fejl i den. Det er godt; det viser, at det er vigtigt kørsel og fejlfindingskode. Det viser et klassisk tilfælde af at gå ud af enden af en matrix.

Anbefalede: