Innehållsförteckning:

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

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

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

Fokus för denna Instructable är STM32 Nucleo mikrokontroller. Motiveringen för detta för att kunna skapa ett monteringsprojekt av bara ben. Detta hjälper oss att fördjupa oss djupare och förstå MSP432 Launchpad-projektet (TI-RSLK) som redan har varit ämne för flera instruktioner.

Det finns inte särskilt mycket hjälp online för att skapa ett projekt som bara är monterat för MSP432, med hjälp av Code Composer Studio. Hittills har vi bara kopierat/klistrat in från ett redan existerande monteringsprojekt. Detta tillvägagångssätt har tjänat oss väl.

Men nu, för Lab 7, har vi stött på lite problem. Eller åtminstone en tillfällig hicka. Lab 7 introducerar finite-state-maskiner, och det första vi möter är behovet av att skapa och använda en rad värden. Eftersom TI -kursen huvudsakligen använder C -programmering - är detta inget problem. Men dessa instruktioner har fokuserat på montering, inte C.

Eftersom matrisen är av skrivskyddade värden skulle det vara bra att lägga den i flashminne, inte RAM.

Det verkar finnas mycket mer hjälp online för monteringsprojekt som använder STM32 MCU, därför börjar vi med den här instruerbara, med målet att använda det inlärda, för att sedan ansöka om MSP432 och Code Composer Studio.

På vägen mot det målet har vi också fått erfarenhet av ännu en populär mikrokontroller.

Steg 1: Första testet av enheten

Första testet av enheten
Första testet av enheten
Första testet av enheten
Första testet av enheten
Första testet av enheten
Första testet av enheten

Återigen, varför välja STM32 Nucleo i synnerhet?

Ärligt? Eftersom jag letade efter bra artiklar om nakna metallmonteringsprojekt för ARM-styrenheter, och jag stötte på den här serien. Och också för att STM32 verkar vara en populär MCU.

Jag gjorde några undersökningar (det finns många versioner att välja mellan - se bilden ovan), men i slutändan blev det vad jag faktiskt kan få, eftersom jag tänkte använda Amazon (i USA).

Den kommer i ett enkelt men professionellt paket, med några startinstruktioner. Det var lite roligt att se att demoen som brändes in i handkontrollen var nästan exakt vad vi har gjort i tidigare instruktioner - en lysdiod blinkar och ändrar hastighet enligt ett tryck på en knapp.

Det verkar som att denna utvecklingskort är mycket lik MSP432 genom att det finns 2 lysdioder och en användarknapp. MSP432 har 2 användarknappar.

Som du kan se på bilderna blev jag lite förvånad över att kortet har en mini och inte ett mikro -USB. Var tvungen att springa ut för att köpa en sladd.

Ett annat bra test är att när du ansluter den till din dator (jag använder en Linux -låda) visas den i min filhanterare som ett filsystem, kallat "NODE_F303RE". Öppning som avslöjar två filer, en HTML och en text.

Det är det, men åtminstone står det också att anslutning verkar ganska lätt.

Nu är vi redo att börja.

Jag ska försöka att inte upprepa någon av de goda uppgifterna från IVONOMICON Bare Metal -artikelserien, utan snarare förstärka den.

Steg 2: Essentials

Det första vi behöver är en kompilator.

Och då behöver vi en felsökare:

devchu@chubox: ~ $ sudo apt-get install gdb-arm-none-eabiLäs paketlistor … Klart Byggnadsberoende-träd Läser tillståndsinformation … Klart Följande NYA paket installeras: gdb-arm-none-eabi 0 uppgraderade, 1 nyligen installerat, 0 att ta bort och 8 inte uppgraderade. Behöver skaffa 2, 722 kB arkiv. Efter denna operation kommer 7, 738 kB extra diskutrymme att användas. Skaffa: 1 https://us.archive.ubuntu.com/ubuntu xenial/universe amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] Hämtade 2, 722 kB på 1s (1, 988 kB/s) Väljer tidigare ovalat paket gdb-arm-none-eabi. (Läser databas … 262428 filer och kataloger för närvarande installerade.) Förbereder att packa upp …/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb… Packa upp gdb-arm-none-eabi (7.10-1ubuntu3+9) … Bearbetar utlösare för man-db (2.7.5-1) … Konfigurera gdb-arm-none-eabi (7.10-1ubuntu3+9) …

Steg 3: Essentials - Windows

Steget ovan antog att vi använder Linux. Vad händer om vi använder Windows?

Du kan gå till armen Developer -webbplatsen, och det finns flera nedladdningsalternativ tillgängliga. Jag använder en Windows 8 -maskin.

Under installationen valde jag att installera den på roten "C: \" i stället för programfiler bara för att jag också använder cygwin, och det var lättare att skapa en länk från mitt lokala fack till en rot C: mapp än alla röra i sökvägen till programfiler (med mellanslag, etc).

Således ser min cygwin -miljö och sökväg osv ut så här:

C: / cygwin64 / home / bin / arm-none-eabi-gcc, där arm-none-eabi-gcc är en länk till C: / GNUToolsArmEmbedded / 7.2018.q2.update / bin / arm-none-eabi- gcc.

Jag skapade sedan en "dev" -mapp under cygwin home, och det var där jag placerade core. S -filen och körde kompilatorkommandot. (se vidare nedan för kompilatorgrejer).

Jag gjorde exakt samma sak för gdb (arm-none-eabi-gdb).

Steg 4: Vad är det väsentliga

Så vad är "gcc-arm-none-eabi"?

GNU -kompilatorn (GCC) kommer att sammanställa programmeringsspråk (som C) till inbyggd kod för maskinen som den körs på. Till exempel, om du skulle kompilera lite C -kod med GCC på din Windows -maskin, skulle den byggas för att köras på Windows -maskinen. Den genererade körbara filen körs (vanligtvis) inte på ARM-mikrokontrollern.

Så, för att bygga program som ska laddas ner och brännas in i ARM-mikrokontrollen (i vårt nuvarande fall skulle det vara STM32 Nucelo), måste vi ge GCC något annat: möjligheten att "korskompilera". Det vill säga möjligheten att generera en körbar, inte för sitt inbyggda system (och processor), utan för målsystemet (ARM-mikrostyrenheten). Det är där "gcc-arm-none-eabi" spelar in.

Så vad är då "gdb-arm-none-eabi"?

När vi har laddat ner och bränt (blinkat) den nygenererade körbara filen i mikrokontrollen, kommer vi förmodligen att vilja felsöka den-steg för rad i rad i koden. GDB är gnu -felsökaren, och den behöver också ett sätt att göra sitt jobb, men riktar in sig på ett annat system.

Således är gdb-arm-none-eabi för GDB, vad gcc-arm-none-eabi är för GCC.

En annan föreslagen paketinstallation var "libnewlib-arm-none-eabi". Vad är den där?

Newlib är ett C -bibliotek och mattebibliotek avsett för användning på inbäddade system. Det är en sammanslagning av flera biblioteksdelar, allt under gratis mjukvarulicenser som gör dem lättanvändbara på inbäddade produkter.

Och slutligen paketet "libstdc ++-arm-none-eabi". Den där är ganska uppenbar; det är C ++-bibliotek för tvärkompilatorn; för inbyggda ARM-mikrokontroller.

Steg 5: Linker -filen

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

Låt oss skapa ett länkskript.

En nyckeldel eller block i den här filen är kommandot MEMORY.

--- från sourceware.org:

Länkarens standardkonfiguration tillåter tilldelning av allt tillgängligt minne. Du kan åsidosätta detta genom att använda kommandot MEMORY. MEMORY -kommandot beskriver platsen och storleken på minnesblock i målet. Du kan använda den för att beskriva vilka minnesregioner som kan användas av länken, och vilka minnesregioner den måste undvika. Du kan sedan tilldela sektioner till specifika minnesregioner. Linkeren kommer att ställa in sektionsadresser baserat på minnesregionerna och varnar för regioner som blir för fulla. Linkeren blandar inte in sektioner för att passa in i de tillgängliga regionerna. Ett länkarskript kan innehålla många användningsområden för MEMORY -kommandot, men alla definierade minnesblock behandlas som om de specificerats i ett enda MEMORY -kommando. Syntaxen för MEMORY är:

MINNE

{namn [(attr)]: ORIGIN = ursprung, LÄNGD = len…}

Exemplet i artikeln:

/* Definiera slutet på RAM och gränsen för stackminne* //* (4KB SRAM på linjen STM32F031x6, 4096 = 0x1000)*//* (RAM börjar på adressen 0x20000000) _estack = 0x20001000;

MINNE

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

Så vi måste räkna ut hur mycket FLASH (för vårt program och konstanter, etc.) och hur mycket RAM (för användning av programmet; hög och stapel, etc) för vårt specifika kort. Det här blir lite intressant.

Det fina lilla kortet som följer med Nucleo säger att det har flashminne är 512 Kbytes och SRAM är 80 Kbyte. Men när du ansluter den till USB monteras den som ett filsystem med två filer, och både filhanteraren och GParted indikerar att den har över 540+ Kbytes utrymme. (BAGGE?).

MEN, försöker ta bort de två filerna med hjälp av filhanteraren, koppla bort och sedan ansluta enheten igen, visar fortfarande de två filerna. (och filhanteraren kände igen något eftersom det finns en liten "lås" -ikon på varje fil.

Så låt oss gå med siffrorna på kortet. Så nu tar vi exemplet ovan och konverterar det till vårt specifika kort.

Du kanske vill använda något liknande den här online -minneskonverteraren för att gå från den allmänna KB till specifikt antal byte.

Då kanske du vill använda en online decimal till hex -omvandlare.

/ * Definiera slutet på RAM och gränsen för stackminne */

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

/ * steg 1: (80KB SRAM på STM32F303RE, 81920 = 0x14000) * // * vårt kort */

/* steg 2, lägg till hexstorleken till hex -startadressen (nedan). */

/ * (RAM börjar på adressen 0x20000000) */

_stack = 0x20001000; /* Exemplet */

_stack = 0x20014000; / * vår styrelse */

MINNE {

FLASH (rx): ORIGIN = 0x08000000, LÄNGD = 512K

RAM (rxb): ORIGIN = 0x20000000, LÄNGD = 80K

}

Låt oss kalla ovanstående fil "linker.script.ld".

Steg 6: Vektortabellen

Vektorbordet
Vektorbordet

Nu ska vi skapa en liten monteringsfil (med direktiv) för att göra en mycket grundläggande avbrottshantering. Vi följer artikelns exempel och skapar en fil med namnet "core. S".

Återigen, här är exempelfilinnehållet, men jag gjorde en ändring för vårt specifika kort:

// Dessa instruktioner definierar attribut för vårt chip och

// det monteringsspråk vi ska använda:.syntax unified /*Se nedan efter detta kodområde* //*.cpu cortex-m0* / /*kommentera denna rad i exemplet* /.cpu cortex-m4 /* lägg istället till vår styrels cortex. se bilden ovan i detta steg * / /*.fpu softvfp * / / *kommentera denna rad i exemplet * /.fpu vfpv4 / *lägg till istället vår styrelse; den har en FPU */.thumb // Globala minnesplatser..global vtable.global reset_handler / * * Själva vektortabellen. * Endast storleken på RAM och "reset" -hanterare * ingår, för enkelhetens skull. */.typ vtable, %object vtable:.word _estack.word reset_handler.size vtable,.-vtable

Hmm.. Nej ".align" -direktiv

Det är dock inte kritiskt. Mer om det (kanske) senare.

.syntax unified

.syntax [enat | dividerat]

Detta direktiv anger Syntaxen för instruktionsuppsättningar enligt beskrivningen i avsnittet ARM-instruktionsuppsättning

9.4.2.1 Syntax för instruktionsuppsättning Två lite olika syntaxer stöder ARM- och THUMB -instruktioner. Standardvärdet, uppdelat, använder den gamla stilen där ARM- och THUMB -instruktioner hade sina egna, separata syntaxer. Den nya, enhetliga syntaxen, som kan väljas via.syntax -direktivet.

.fpu vfpv4

GCC -kompilatorn kan producera binärer med flera alternativ när det gäller flytpunkt: mjuk - lämplig för körning på processorer utan FPU - beräkningar görs i programvara av kompilatorgenererad softfp - lämplig för körning på processorer med eller utan FPU - kommer att använda en FPU om den finns. För vårt specifika fall (du måste göra din egen forskning), överensstämmer den här styrelsens FPU med vfpv4. Du kanske måste spela med det här. Eller till och med lämna det på softfp.

.thumb (vs.arm)

Dessa ARM -mikrokontroller har faktiskt en blandning av instruktionsuppsättningar. En är ARM, en annan är THUMB. En skillnad är 16-bitars instruktioner mot 32-bitars instruktioner. Således uppmanar detta direktiv kompilatorn att behandla efterföljande instruktioner som antingen THUMB eller ARM.

Vi kommer bara att ta resten av filen som den är eftersom dessa instruktioner ännu inte har fördjupat sig i avbrottsdriven monteringsprogrammering.

Steg 7: Monteringsversionen av ett "Hello World" -program

Följande kan också gå in i den tidigare skapade "core. S" -filen. Detta återigen är från exemplet i artikeln.

/ * * Återställ hanteraren. Ringde vid återställning. */.typ reset_handler, %function reset_handler: // Ställ stackpekaren i slutet av stacken. // Värdet '_estack' definieras i vårt länkarskript. LDR r0, = _stack MOV sp, r0

// Ställ in några dummyvärden. När vi ser dessa värden

// i vår felsökning vet vi att vårt program // laddas på chipet och fungerar. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // Lägg till 1 för att registrera 'r0'. ADDS r0, r0, #1 // Loop back. B main_loop.size reset_handler,.-Reset_handler

Så, syftet med ovanstående program är att ladda ett igenkännbart mönster i ett kärn -MCU -register (i detta fall R7), och ett ökande värde som börjar med noll till ett annat kärn -MCU -register (i detta fall R0). Om vi går igenom den exekverande koden bör vi se R0s datainkrement.

Om du har följt med instruktionerna angående MSP432 och TI-RSLK-kursen/labben, så borde i stort sett allt ovanstående program vara bekant för dig.

Det enda nya jag kan se är användningen av "=" när du laddar "DEADBEEF" för att registrera R7. Vi hade inte använt det.

"Core. S" -filen som bifogas här innehåller nu hela källan.

Steg 8: Sammanställning av koden

Det är dags att göra några kommandoradsgrejer. Något riktigt, äntligen.

Men vi är inte riktigt där. Vi måste återigen justera kommandot i artikeln och ändra det till vår egen situation.

Här är exempelkoden:

arm -none -eabi -gcc -x assembler -with -cpp -c -O0 -mcpu = cortex -m0 -mumba -Väggkärna. S -o core.o

Om vi går till gnu.org -webbplatsen för GCC, (i det här fallet version 7.3),

x

-X är att ange språket. Annars om ingen -x, kommer kompilatorn att försöka gissa med hjälp av filtillägget. (i vårt fall, *. S).

Ovanstående exempel från artikeln specificerar assembler-with-cpp, men vi kan bara göra assembler.

c

-C säger kompilera men länka inte.

O0

-O är att ställa in optimeringsnivån. Använda -O0 (oh -zero) säger "minska kompileringstiden och få felsökning att ge de förväntade resultaten. Detta är standard".

mcpu = cortex-m0

-Mcpu anger namnet på målprocessorn. I vårt fall skulle det vara cortex-m4.

tummen

-Mthumb anger att välja mellan att generera kod som kör ARM- och THUMB -tillstånd.

Vägg

-Väggen är naturligtvis mycket vanlig och välkänd. Den tänder alla varningsflaggor.

Slutligen, i slutet av kommandot har vi inmatningsfilen core. S och utdatafilen core.o.

Här är den nya kommandoraden som passar vårt specifika fall.

arm -none -eabi -gcc -x assembler -c -O0 -mcpu = cortex -m4 -mumma -Väggkärna. S -o kärna.o

Och det sammanställde.

Steg 9: Länka programmet

Direkt från exemplet i artikeln har vi detta:

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

De flesta av ovanstående har du sett. Nedan är vad som är nytt.

-specs = nosys.specs

Det här är lite knepigt att förklara.

Det har att göra med "semihosting" och "retargeting", och det har att göra med input / output. Det har också att göra med systemsamtal och bibliotek.

Normalt tillhandahåller inbäddade system inte vanliga in-/utgångsenheter. Detta skulle påverka system- eller bibliotekssamtal (exempel: printf ()).

Semihosting betyder att felsökaren (se steg 11 -bild med felsökningsdelen inringad i rött) har en speciell kanal och använder semihosting -protokollet, och du kan se utdata från printf () på värddatorn (via felsökaren).

Retargeting, å andra sidan, innebär att samma system- eller bibliotekssamtal betyder något annat. De gör något annat, som är vettigt för det inbäddade systemet. På ett sätt, säg för printf (), det finns en ny implementering, en omriktad implementering av den funktionen.

Med allt detta betyder --specs = nosys.specs att vi inte kommer att vara semihostande. Det skulle normalt då betyda att vi ommålar. Det tar oss till nästa flagga.

nostdlib

Länkaralternativet -nostdlib används för att länka ett program avsett att köra fristående. -nostdlib innebär de enskilda alternativen -nodefaultlibs och -nostartfiles. Nedan diskuterar vi de två alternativen separat, men den mest typiska användningen är bara nostdlib för one-stop shopping. När du länkar ett värdprogram, är standardsystembibliotek som libc länkade som standard, vilket ger programmet åtkomst till alla standardfunktioner (printf, strlen och vänner). Länkaralternativet -nodefaultlibs inaktiverar länkning till dessa standardbibliotek; de enda bibliotek som är länkade är exakt de som du uttryckligen namnge länken med hjälp av -l -flaggan.

lgcc

libgcc.a är ett standardbibliotek som tillhandahåller interna underrutiner för att övervinna brister i vissa maskiner. Till exempel innehåller ARM -processorn ingen divisionsinstruktion. ARM -versionen av libgcc.a innehåller en delningsfunktion och kompilatorn avger samtal till den funktionen där det behövs.

T

Detta är bara ett sätt att berätta för länkaren att använda den här filen som länkarskriptet. I vårt fall är filnamnet linker.script.ld.

o main.elf

Slutligen berättar vi för länkaren vad namnet på den slutliga utgående bildfilen som kommer att brännas/blinkas in i vår enhet.

Här är vår version av den kompletta kommandoraden, anpassad för vår specifika 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 ser till att skriptfilen och core.o-filen finns i samma katalog, där vi kör ovanstående kommandorad.

Och det länkar utan problem.

En check

Vi kör sedan:

arm-none-eabi-nm main.elf

och vi får:

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

Ser bra ut. Kommandot arm-none-eabi-nm är ett sätt att lista symboler i objektfiler.

Steg 10: Testa anslutning till STM32 Nucleo-64

Testa anslutning till STM32 Nucleo-64
Testa anslutning till STM32 Nucleo-64
Testa anslutning till STM32 Nucleo-64
Testa anslutning till STM32 Nucleo-64

Ditt första uppdrag, om du väljer att acceptera det, är att få ditt system att se din utvecklingstavla.

Använda Windows

För Windows bestämde jag mig för att installera TrueSTUDIO från Atollic (gratisversion). Det var en smärtfri installation och den installerade automatiskt drivrutinen så att jag kunde använda st-link för att testa anslutningen. När jag installerade TrueSTUDIO och enhetshanteraren såg enheten laddade jag ner texan/stlink -verktygen som föreslogs av Bare Metal -artikeln som vi har följt. Jag placerade igen mappen direkt under "C: \" och skapade igen några länkar från min lokala cygwin -papperskorg till kommandona.

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

Som ett första test för att se om vi verkligen kan kommunicera med enheten sprang jag:

st-info --probe

Och kom tillbaka:

Hittade 1 stlink -programmerare

Så nu vet vi att vi kan prata/fråga vår utvecklingstavla.

Använda Linux

För Linux behöver du inte riktigt en drivrutin. Men för Debian måste du bygga verktygen från källan.

git -klon

Se till att du har libusb-1.0-0-dev installerat.

lämplig lista | grep -E "*libusb.*dev*"

Du borde se:

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

eller något sådant.

För att installera det:

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

Observera att ovanstående inte är detsamma som:

sudo apt-get install libusb-dev

Den korrekta saknade libusb -dev kan orsaka att cmake har problem.

CMake -fel: Följande variabler används i detta projekt, men de är inställda på NOTFOUND. Vänligen ställ in dem eller se till att de är inställda och testade korrekt i CMake -filerna: LIBUSB_INCLUDE_DIR (ADVANCED)

Byt till projektets rotkatalog (… bla /bla /stlink). Gör en "make release".

Efter det har byggts bör verktygen stå under ".. /build /Release".

Du kan sedan köra "st-info --probe". Här är utgången med Nucleo ansluten, då inte.

devchu@chubox: ~/Development/stlink $./build/Release/st-info --probeHittade 1 stlink-programmerare serie: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "blixt: 524288 (sidstorlek: 2048) sram: 65536 chipid: 0x0446 descr: F303 enhet med hög densitet devchu@chubox: ~/Development/stlink $./build/Release/st- info --probe Hittade 0 stlink programmerare devchu@chubox: ~/Development/stlink $

Steg 11: Låt oss använda GDB med Linux

Låt oss använda GDB med Linux
Låt oss använda GDB med Linux
Låt oss använda GDB med Linux
Låt oss använda GDB med Linux

Om du har försökt allt detta, och du har kommit så här långt - bra! Excellent. Låt oss ha lite kul nu.

När du köper dessa ARM-utvecklingsbrädor, oavsett om de är MSP432 Launchpad från Texas Instruments, eller den vi diskuterar nu, Nucleo-F303 (STM32 Nucleo-64), kommer de vanligtvis redan blinkade med ett igång program, vanligtvis något blinkande program som också inkluderar att trycka på en strömbrytare för att ändra hastigheten med vilken LED (erna) blinkar.

Innan vi är så snabba att skriva över det, låt oss se vad det finns att se och göra.

Med Linux, öppna en terminal, ändra katalog för stlink git-projektet som vi just byggde och hitta st-util-verktyget.

devchu@chubox: ~/Development/stlink $ hitta. -namn st-util

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

Kör det verktyget. Eftersom vi redan tidigare har testat vår anslutning till st-info --probe, bör vi få lite utmatning så här:

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

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 INFO vanligt. c: Läser in enhetsparametrar…. 2018-10-20T18: 33: 23 INFO common.c: Enhet ansluten är: F303 enhet med hög densitet, id 0x10036446 2018-10-20T18: 33: 23 INFO common.c: SRAM-storlek: 0x10000 byte (64 KiB), Flash: 0x80000 byte (512 KiB) på sidor om 2048 byte 2018-10-20T18: 33: 23 INFO gdb-server.c: Chip-ID är 00000446, Core ID är 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: Lyssnar på *: 4242 …

Det är GDB -servern som körs nu, och den ser vårt utvecklingskort, och ännu viktigare, den lyssnar på port 4242 (standardporten).

Nu är vi redo att skjuta upp GDB -klienten.

I Linux, öppna en annan terminal, ange detta:

arm-none-eabi-gdb -tui

Det är precis samma sak som att köra gdb strikt kommandorad, men det producerar istället en textbaserad terminal (min gissning är att den använder förbannelser).

Vi har GDB -klienten och GDB -servern igång. Klienten är dock inte ansluten till servern. För närvarande vet den ingenting om vår Nucleo (eller styrelse efter eget val). Vi måste berätta det. I terminalen ska din uppmaning nu vara "(gdb)". Stiga på:

hjälp mål

Det kommer att ge dig en lista. Lägg märke till att den vi vill ha är target extended -remote - Använd en fjärrdator via en seriell linje.

Men vi måste också ge platsen. Så, vid prompten (gdb), ange:

(gdb) target extended-remote localhost: 4242

Du borde få tillbaka ett svar ungefär så här:

(gdb) target extended-remote localhost: 4242

Fjärrfelsökning med localhost: 4242 0x080028e4 i ?? ()

Under tiden fick vi följande på terminalen som kör st-util gdbserver:

2018-10-20T18: 42: 30 INFO gdb-server.c: Hittade 6 hw brytpunktsregister

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

Steg 12: Låt oss upprepa, med Windows och Flash vårt program

Låt oss upprepa, med Windows och Flash vårt program
Låt oss upprepa, med Windows och Flash vårt program
Låt oss upprepa, med Windows och Flash vårt program
Låt oss upprepa, med Windows och Flash vårt program
Låt oss upprepa, med Windows och Flash vårt program
Låt oss upprepa, med Windows och Flash vårt program

Stegen för att köra st-util gdbserver och arm-none-eabi-gdb-klienten är i huvudsak desamma som vi gjorde under föregående steg. Du öppnar två terminaler (cygwin, DOS cmd eller Windows Powershell), hitta platsen för st-util, kör den. I den andra terminalen kör du armen-none-eabi-gdb-klienten. Den enda skillnaden är att läget -tui (terminalbaserad textvy) sannolikt inte stöds.

Om ovanstående fungerade i Windows måste du förmodligen sluta (bara klienten). Vid denna tidpunkt måste du på något sätt köra GDB -klienten där din byggfil är ("core.out"), eller lägga till hela sökvägen till filen som ett argument för GDB -klienten.

Jag förenklade mitt liv genom att använda cygwin och skapa länkar från min lokala $ HOME // bin -katalog till där båda dessa verktyg finns.

Ok, vi har sammanställt och länkat precis som tidigare, och vi har filen main.elf redo att bli flashad.

Vi har st-util som körs i ett fönster. Vi startar om GDB-klienten, den här gången gör vi:

arm-none-eabi-gdb main.elf

Vi låter den starta, väntar på (gdb) -prompten, gör samma anslutningskommando till GDB-servern (st-util) och vi är redo att blinka den körbara filen. Det är väldigt antiklimatiskt:

(gdb) belastning

Körs med cygwin -terminaler, det finns ett känt problem med att någon gång konsolkommandon inte matas ut. Så i vårt fall var fönstret som körde servern helt tyst. Den som kör klienten, där vi körde belastningen, mata ut detta:

Laddningsavsnitt.text, storlek 0x1c lma 0x8000000 Startadress 0x8000000, laststorlek 28 Överföringshastighet: 1 KB/sek, 28 byte/skriv.

Steg 13: Blinkar med Linux - Mer belöning: D

Blinkar med Linux - Mer belöning: D
Blinkar med Linux - Mer belöning: D

Steg 14: Låt oss dyka lite djupare

Om du kom hit, utmärkt. Låt oss gå vidare.

Varför inte titta inuti huvudfilen, den körbara filen? Kör följande:

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

Du borde se en utgång ungefär så här:

main.elf: filformat elf32-littlearm

Demontering av sektion.text:

08000000:

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

08000008:

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

08000010:

8000010: 3001 lägger till r0, #1 8000012: e7fd b.n 8000010 8000014: 20014000.word 0x20014000 8000018: deadbeef.word 0xdeadbeef

Vilka små nuggets kan vi få från ovanstående utmatning?

Om du kommer ihåg när vi diskuterade och skapade filen linker.script.ld, konstaterade vi att dessa ARM -enheter har RAM från 0x20000000 och att FLASH -minne börjar med 0x08000000.

Således kan vi se att programmet verkligen är sådant att allt finns i FLASH -minne.

Sedan ovan, men ett senare steg, när vi diskuterade "Hello World" -delen, fanns det ett uttalande där vi läser in ett omedelbart, konstant, bokstavligt värde ("0xDEADBEEF") i ett MCU -kärnregister ("R7").

Uttalandet var:

LDR R7, = 0xDEADBEEF

I vår kod är det det enda stället där vi till och med nämner DEADBEEF. Ingen annan stans. Och ändå, om du tittar på ovanstående demonterade/rekonstruerade instruktioner osv, finns det mer där relaterat till DEADBEEF än vi trodde att vi gjorde.

Så kompilatorn/länken bestämde sig på något sätt för att permanent blinka värdet på DEADBEEF till en FLASH -adress, på plats 0x8000018. Och sedan ändrade kompilatorn vår ovanstående LDR -instruktion till att vara:

LDR R7, [PC, #8]

Det genererade till och med en kommentar för oss. Vad trevligt. Och det berättar för oss att ta det aktuella programräknaren (PC -registret), lägga till 0x8 till det värdet, och det är där DEADBEEF har bränts, och få det värdet och stoppa det i R7.

Så det betyder också att programräknaren (PC) pekade på adressen 0x8000010, som är starten på main_loop, och att DEADBEEF -värdet sitter på två adresser efter slutet av main_loop.

Steg 15: Slutligen en kort titt på programkörningen

Även om du slutar med GDB anger du bara kommandot igen. Du behöver inte ens ge den någon fil; vi blinkar inte längre, bara kör det.

När du har återanslutit GDB-klienten till GDB-servern, vid kommandotolken (gdb):

(gdb) inforegister

Du borde se något så här:

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 429496789595

Men sedan, vid prompten (gdb), ange:

(gdb) fortsätt

Och mycket snabbt träffade CTRL-C. Det borde pausa programmet. Ange kommandot "info register" igen.

Den här gången ser det annorlunda ut:

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

Vad hände? Precis vad vi ville. DEADBEEF laddades in i R7 och R0 har ökat (extremt snabbt). Om du upprepar ser du R0 igen med ett annat värde.

Steg 16: Vi ville skapa en skrivskyddad matris i Flash

Ett sätt att skapa motsvarigheten till en array med hjälp av sammansättning och direktiv är följande:

.typ myarray, %object // namnet eller etiketten 'myarray' definieras som en objekttyp.

myarray: // detta är början på deklarationen om 'myarray' // (vad den kommer att bestå av)..word 0x11111111 // den första medlemmen eller värdet i 'myarray'..word 0x22222222 // det andra värdet (sammanhängande adresser)..word 0x33333333 // och så vidare..size myarray,.-myarray // kompilatorn/assembler vet nu var slutet eller // gränsen för 'myarray'.

Nu när vi har ställt in det i FLASH -minne kan vi använda det i programmet. Nedan är en portion:

LDR R1, myarray // detta läser in data som finns på första platsen för 'myarray'. ' // detta är inte vad vi vill.

LDR R1, = myarray // detta läser in själva platsvärdet (den första adressen), // inte data.. // det här är vad vi vill.

MOV R2, #0 // R2 håller en räkning för att se till att vi inte går iväg

// slutet av matrisen. LDR R3, = myarrsize // R3 kommer att motsvara 'myarrsize'.

// R0 kommer att lagra våra data

main_loop:

LDR R0, [R1] // Ladda data som R1 ('myarray') pekar på i R0. CMP R2, R3 // Har vi gränsen för array? BEQ main_loop // Om vi är det är vi klara, så vi slingrar bara för alltid.

ADD R2, #1 // Annars kan vi fortsätta iterera genom array.

ADD R1, #4 // Lägg till 4 för att registrera R1, så det pekar rätt till nästa

// adress..

B main_loop // Loop back.

Videon går igenom allt detta, och det finns en bugg i den. Det är bra; det visar att det är viktigt körning och felsökningskod. Det visar ett klassiskt fall av att gå utanför slutet av en array.

Rekommenderad: