Inhoudsopgave:

Deel 1 ARM-assemblage TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Ajarnpa
Deel 1 ARM-assemblage TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Ajarnpa

Video: Deel 1 ARM-assemblage TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Ajarnpa

Video: Deel 1 ARM-assemblage TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo - Ajarnpa
Video: Learn Some ARM Assembly - MSP432 - TI-RSLK - Texas Instruments Robotics System Learning Kit - Lab 3 2024, Juli-
Anonim
Image
Image

De focus van deze Instructable is de STM32 Nucleo-microcontroller. De motivatie hiervoor is om van kale botten een montageproject te kunnen maken. Dit zal ons helpen om dieper te graven en het MSP432 Launchpad-project (de TI-RSLK) te begrijpen, dat al het onderwerp is van verschillende Instructables.

Er is niet veel hulp online om een assembly-only project voor de MSP432 te maken met behulp van de Code Composer Studio. Tot nu toe hebben we alleen maar gekopieerd/plakt van een reeds bestaand montageproject. Deze aanpak heeft ons goed gedaan.

Nu, voor Lab 7, zijn we echter een probleem tegengekomen. Of in ieder geval een tijdelijke storing. De Lab 7 introduceert eindige-toestandsmachines, en het eerste dat we tegenkomen is de noodzaak om een reeks waarden te creëren en te gebruiken. Aangezien de TI-cursus voornamelijk C-programmering gebruikt, is dit geen probleem. Maar deze Instructables hebben zich gericht op montage, niet op C.

Verder, aangezien de array alleen-lezen waarden heeft, zou het goed zijn om deze in flash-geheugen te plaatsen, niet in RAM.

Er lijkt veel meer hulp online te zijn voor assemblageprojecten met behulp van de STM32 MCU, dus we beginnen met deze Instructable, met als doel het geleerde te gebruiken, om vervolgens toe te passen op de MSP432 en de Code Composer Studio.

Op weg naar dat doel hebben we ook ervaring opgedaan met weer een andere, populaire microcontroller.

Stap 1: Eerste test van het apparaat

Eerste test van apparaat
Eerste test van apparaat
Eerste test van apparaat
Eerste test van apparaat
Eerste test van apparaat
Eerste test van apparaat

Nogmaals, waarom zou je in het bijzonder voor de STM32 Nucleo kiezen?

Eerlijk gezegd? Omdat ik op zoek was naar goede artikelen over bare-metal montageprojecten voor ARM-controllers, kwam ik deze serie tegen. En ook omdat de STM32 een populaire MCU lijkt te zijn.

Ik heb wat onderzoek gedaan (er zijn veel versies om uit te kiezen - zie afbeelding hierboven), maar uiteindelijk werd het wat ik eigenlijk kon krijgen, aangezien ik Amazon (in de VS) ging gebruiken.

Het wordt geleverd in een eenvoudig maar professioneel pakket, met enkele opstartinstructies. Het was een beetje grappig om te zien dat de demo die in de controller is gebrand, bijna precies was wat we in eerdere Instructables hebben gedaan - een LED knippert en verandert van snelheid met een druk op een knop.

Het lijkt erop dat dit ontwikkelbord erg lijkt op de MSP432 omdat er 2 LED's zijn en één gebruikersdrukknop. De MSP432 heeft 2 gebruikersknoppen.

Zoals je op de foto's kunt zien, was ik een beetje verrast dat het bord een mini- en geen micro-USB heeft. Moest opraken om een snoer te kopen.

Een andere goede test is dat wanneer je het op je computer aansluit (ik gebruik een Linux-box), het in mijn bestandsbeheer verschijnt als een bestandssysteem, genaamd "NODE_F303RE". Opening die twee bestanden onthult, één HTML en één tekst.

Dat is het, maar het zegt in ieder geval ook dat connectiviteit vrij eenvoudig lijkt.

Nu zijn we klaar om te beginnen.

Ik ga proberen de goede informatie uit de IVONOMICON Bare Metal-artikelreeks niet te herhalen, maar deze juist aan te vullen.

Stap 2: De essentie

Het eerste wat we nodig hebben is een compiler.

En dan hebben we een debugger nodig:

devchu@chubox:~$ sudo apt-get install gdb-arm-none-eabi Pakketlijsten lezen… Klaar Bouwen van de afhankelijkheidsboom Statusinformatie lezen… Klaar De volgende NIEUWE pakketten worden geïnstalleerd: gdb-arm-none-eabi 0 geüpgraded, 1 nieuw geïnstalleerd, 0 om te verwijderen en 8 niet geüpgraded. Ik heb 2.722 kB aan archieven nodig. Na deze operatie zal 7.738 kB extra schijfruimte worden gebruikt. Get: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 opgehaald in 1s (1, 988 kB/s) Selecteren van eerder niet geselecteerd pakket gdb-arm-none-eabi. (Database lezen … 262428 bestanden en mappen die momenteel zijn geïnstalleerd.) Voorbereiden voor uitpakken …/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb … Uitpakken gdb-arm-none-eabi (7.10-1ubuntu3+9) … Verwerken triggers voor man-db (2.7.5-1) … gdb-arm-none-eabi (7.10-1ubuntu3+9) instellen …

Stap 3: De essentie - Windows

De bovenstaande stap ging ervan uit dat we Linux gebruiken. Wat als we Windows gebruiken?

U kunt naar de arm Developer-site gaan en er zijn verschillende downloadopties beschikbaar. Ik gebruik een Windows 8-machine.

Tijdens de installatie heb ik ervoor gekozen om het te installeren op de root "C:\" schijf in plaats van Program Files, alleen omdat ik ook cygwin gebruik, en het was gemakkelijker om een link te maken van mijn lokale bin naar een root C: map dan alle rommel in het pad naar Program Files (met spaties, enz.).

Dus mijn cygwin-omgeving en pad, enz. Ziet er als volgt uit:

C:\cygwin64\home\bin\arm-none-eabi-gcc, waarbij de arm-none-eabi-gcc een link is naar C:\GNUToolsArmEmbedded\7.2018.q2.update\bin\arm-none-eabi- gcc.

Ik heb toen een map "dev" gemaakt onder cygwin home, en daar plaatste ik het core. S-bestand en voerde ik de compileropdracht uit. (zie verder hieronder voor de compiler-dingen).

Ik deed precies hetzelfde voor gdb (arm-none-eabi-gdb).

Stap 4: Wat zijn de essentie?

Dus wat is "gcc-arm-none-eabi"?

De gnu-compiler (GCC) zal programmeertalen (zoals C) compileren in native code voor de machine waarop deze draait. Als u bijvoorbeeld wat C-code zou compileren met GCC op uw Windows-machine, zou deze zijn gebouwd om op de Windows-computer te draaien. Het gegenereerde uitvoerbare bestand werkt (meestal) niet op de ARM-microcontroller.

Dus om programma's te bouwen om te downloaden en te branden in de ARM-microcontroller (in ons huidige geval zou dat de STM32 Nucelo zijn), moeten we GCC iets anders geven: de mogelijkheid om te "cross-compileren". Dat wil zeggen, de mogelijkheid om een uitvoerbaar bestand te genereren, niet voor het eigen systeem (en processor), maar voor het doelsysteem (de ARM-microcontroller). Dat is waar "gcc-arm-none-eabi" in het spel komt.

Dus wat is dan "gdb-arm-none-eabi"?

Zodra we het nieuw gegenereerde uitvoerbare bestand hebben gedownload en gebrand (geflitst) in de microcontroller, willen we het waarschijnlijk debuggen - stap voor stap door de code. GDB is de gnu-debugger en ook deze heeft een manier nodig om zijn werk te doen, maar is gericht op een ander systeem.

Dus gdb-arm-none-eabi is voor GDB, wat gcc-arm-none-eabi is voor GCC.

Een andere voorgestelde pakketinstallatie was de "libnewlib-arm-none-eabi". Wat is dat?

Newlib is een C-bibliotheek en een wiskundebibliotheek die bedoeld is voor gebruik op embedded systemen. Het is een conglomeraat van verschillende bibliotheekonderdelen, allemaal onder vrije softwarelicenties waardoor ze gemakkelijk bruikbaar zijn op embedded producten.

En tot slot het pakket "libstdc++-arm-none-eabi". Die is vrij duidelijk; het is een C++-bibliotheek voor de cross-compiler; voor embedded ARM-microcontrollers.

Stap 5: Het Linker-bestand

Het Linker-bestand
Het Linker-bestand
Het Linker-bestand
Het Linker-bestand

Laten we een linkerscript maken.

Een belangrijk onderdeel of blok in dit bestand is het MEMORY-commando.

--- van sourceware.org:

De standaardconfiguratie van de linker maakt toewijzing van al het beschikbare geheugen mogelijk. U kunt dit overschrijven door het MEMORY-commando te gebruiken. Het MEMORY-commando beschrijft de locatie en grootte van geheugenblokken in het doel. U kunt het gebruiken om te beschrijven welke geheugengebieden door de linker mogen worden gebruikt en welke geheugengebieden het moet vermijden. U kunt dan secties toewijzen aan bepaalde geheugenregio's. De linker stelt sectieadressen in op basis van de geheugenregio's en waarschuwt voor regio's die te vol raken. De linker zal geen secties door elkaar schudden om in de beschikbare regio's te passen. Een linker-script kan veel gebruik van de MEMORY-opdracht bevatten, maar alle gedefinieerde geheugenblokken worden behandeld alsof ze zijn gespecificeerd in een enkele MEMORY-opdracht. De syntaxis voor MEMORY is:

GEHEUGEN

{ naam [(attr)]: OORSPRONG = oorsprong, LENGTE = len … }

Het voorbeeld in het artikel:

/* Definieer het einde van het RAM-geheugen en de limiet van het stapelgeheugen *//* (4KB SRAM op de STM32F031x6-regel, 4096 = 0x1000) */ /* (RAM begint op adres 0x20000000) _estack = 0x20001000;

GEHEUGEN

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

We moeten dus uitzoeken hoeveel FLASH (voor ons programma en constanten, enz.) en hoeveel RAM (voor gebruik door het programma; heap en stapel, enz.) voor ons specifieke bord. Dit wordt een beetje interessant.

Het leuke kaartje dat bij de Nucleo wordt geleverd, zegt dat het flashgeheugen 512 Kbytes is en SRAM 80 Kbytes. Als het echter op USB wordt aangesloten, wordt het gemount als een bestandssysteem met twee bestanden, en zowel de bestandsbeheerder als GParted geven aan dat het meer dan 540+ Kbytes aan ruimte heeft. (RAM?).

MAAR, bij een poging om de twee bestanden te verwijderen met behulp van bestandsbeheer, de verbinding met het apparaat te verbreken en vervolgens opnieuw aan te sluiten, worden nog steeds de twee bestanden weergegeven. (en de bestandsbeheerder heeft iets herkend omdat er een klein "slot"-pictogram op elk bestand staat.

Dus laten we gaan met de cijfers op de kaart. Dus nu nemen we het bovenstaande voorbeeld en zetten het om naar ons specifieke bord.

Misschien wilt u zoiets als deze online geheugenconverter gebruiken om van de algemene KB naar een specifiek aantal bytes te gaan.

Dan wilt u misschien een online decimaal naar hex-converter gebruiken.

/* Definieer het einde van het RAM-geheugen en de limiet van het stapelgeheugen */

/* (4KB SRAM op de STM32F031x6 lijn, 4096 = 0x1000) *//* het voorbeeld*/

/* stap 1: (80KB SRAM op de STM32F303RE, 81920 = 0x14000) *//* ons bord */

/* stap 2, voeg de hex-grootte toe aan het hex-startadres (hieronder). */

/* (RAM begint op adres 0x20000000) */

_estack = 0x20001000; /* het voorbeeld */

_estack = 0x20014000; /* ons bord */

GEHEUGEN {

FLASH (rx): OORSPRONG = 0x08000000, LENGTE = 512K

RAM (rxw): OORSPRONG = 0x20000000, LENGTE = 80K

}

Laten we het bovenstaande bestand "linker.script.ld" noemen.

Stap 6: De vectortabel

De vectortabel
De vectortabel

Nu gaan we een klein assembly-bestand maken (met richtlijnen) om een aantal zeer eenvoudige interrupt-afhandeling uit te voeren. We volgen het voorbeeld van het artikel en maken een bestand met de naam "core. S".

Nogmaals, hier is de inhoud van het voorbeeldbestand, maar ik heb een wijziging aangebracht voor ons specifieke bord:

// Deze instructies definiëren attributen van onze chip en

// de assembleertaal die we zullen gebruiken:.syntax unified /* Zie hieronder na dit codegebied */ /*.cpu cortex-m0 */ /*commentaar op deze regel van het voorbeeld */.cpu cortex-m4 /* voeg in plaats daarvan de cortex van ons bord toe. zie bovenstaande afbeelding in deze stap */ /*.fpu softvfp */ /* commentaar op deze regel van het voorbeeld */.fpu vfpv4 /* voeg in plaats daarvan onze borden toe; het heeft wel een FPU */.thumb // Globale geheugenlocaties..global vtable.global reset_handler /* * De werkelijke vectortabel. * Alleen de grootte van het RAM-geheugen en de 'reset'-handler zijn * inbegrepen, voor de eenvoud. */.type vtable, %object vtable:.word _estack.word reset_handler.size vtable,.-vtable

Hmm.. Geen '.align'-richtlijn

Dat is echter niet kritisch. Daarover later (misschien) meer.

.syntaxis verenigd

.syntaxis [verenigd | verdeeld]

Deze richtlijn stelt de instructiesetsyntaxis in zoals beschreven in de sectie ARM-Instruction-Set

9.4.2.1 Syntaxis van instructieset Twee enigszins verschillende syntaxis zijn ondersteuning voor ARM- en THUMB-instructies. De standaard, verdeeld, gebruikt de oude stijl waar ARM- en THUMB-instructies hun eigen, afzonderlijke syntaxis hadden. De nieuwe, uniforme syntaxis, die kan worden geselecteerd via de.syntax-richtlijn.

.fpu vfpv4

De GCC-compiler kan binaire bestanden produceren met verschillende opties met betrekking tot drijvende komma: soft - geschikt om op CPU's zonder FPU te draaien - berekeningen worden in software gedaan door door de compiler gegenereerde softfp - geschikt voor draaien op CPU's met of zonder FPU - zal een FPU gebruiken indien aanwezig. Voor ons specifieke geval (je zult je eigen onderzoek moeten doen), voldoet de FPU van dit specifieke bord aan vfpv4. Het kan zijn dat je hiermee moet spelen. Of laat het zelfs op softfp staan.

.duim (vs.arm)

Deze ARM-microcontroller heeft eigenlijk een mix van instructiesets. Een daarvan is ARM, een andere is DUIM. Een verschil is 16-bits instructies versus 32-bits instructies. Deze instructie vertelt de compiler dus om volgende instructies als THUMB of ARM te behandelen.

We nemen de rest van het bestand gewoon zoals het is, omdat deze Instructables zich nog niet hebben verdiept in het programmeren van assemblages op basis van interrupts.

Stap 7: De montageversie van een 'Hello World'-programma

Het volgende kan ook in het eerder gemaakte "core. S"-bestand worden opgenomen. Dit komt nogmaals uit het voorbeeld in het artikel.

/* * De Reset-handler. Bij reset gebeld. */.type reset_handler, %function reset_handler: // Zet de stapelaanwijzer op het einde van de stapel. // De waarde '_estack' wordt gedefinieerd in ons linkerscript. LDR r0, =_estack MOV sp, r0

// Stel enkele dummy-waarden in. Wanneer we deze waarden zien

// in onze debugger weten we dat ons programma // op de chip is geladen en werkt. LDR r7, =0xDEADBEEF MOVS r0, #0 main_loop: // Voeg 1 toe om 'r0' te registreren. VOEGT r0, r0, #1 // Loop terug toe. B main_loop.size reset_handler,.-reset_handler

De strekking van het bovenstaande programma is dus om een herkenbaar patroon in het ene MCU-kernregister (in dit geval R7) te laden en een oplopende waarde vanaf nul in een ander MCU-kernregister (in dit geval R0). Als we de uitvoerende code doorlopen, zouden we de gegevenstoename van R0 moeten zien.

Als je de Instructables met betrekking tot de MSP432 en de TI-RSLK-cursus/labs hebt gevolgd, dan zou vrijwel al het bovenstaande programma je bekend moeten zijn.

Het enige nieuwe dat ik kan zien, is het gebruik van "=" bij het laden van "DEADBEEF" om R7 te registreren. Daar hadden we geen gebruik van gemaakt.

Het hier bijgevoegde "core. S"-bestand bevat nu de volledige bron.

Stap 8: De code compileren

Het is tijd om wat commandoregel-dingen te doen. Eindelijk iets echts.

We zijn er echter nog niet helemaal. We moeten opnieuw de opdracht in het artikel aanpassen en aanpassen aan onze eigen situatie.

Hier is de voorbeeldcode:

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

Als we naar de gnu.org-site gaan voor GCC (in dit geval versie 7.3),

x

De -x is om de taal te specificeren. Anders, als er geen -x is, zal de compiler proberen te raden met behulp van de bestandsextensie. (in ons geval *. S).

Het bovenstaande voorbeeld uit het artikel specificeert assembler-met-cpp, maar we zouden gewoon assembler kunnen doen.

C

De -c zegt compileer maar koppel niet.

O0

De -O is om het optimalisatieniveau in te stellen. Het gebruik van -O0 (oh-zero) zegt "verminder de compileertijd en zorg ervoor dat foutopsporing de verwachte resultaten oplevert. Dit is de standaardinstelling".

mcpu=cortex-m0

De -mcpu specificeert de naam van de doelprocessor. In ons geval zou het cortex-m4 zijn.

duim

De -mthumb specificeert het selecteren tussen het genereren van code die ARM- en THUMB-statussen uitvoert.

Muur

De -Wall is natuurlijk heel gewoon en bekend. Het zet alle waarschuwingsvlaggen aan.

Ten slotte hebben we aan het einde van het commando het invoerbestand core. S en het uitvoerbestand core.o.

Hier is de resulterende nieuwe opdrachtregel die in ons specifieke geval past.

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

En dat gecompileerd.

Stap 9: Het programma koppelen

Direct uit het voorbeeld in het artikel hebben we dit:

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

De meeste van het bovenstaande heb je gezien. Hieronder staat wat er nieuw is.

specs=nosys.specs

Deze is een beetje lastig uit te leggen.

Het heeft te maken met "semihosting" en "retargeting", en het heeft te maken met input/output. Het heeft ook te maken met systeemaanroepen en bibliotheken.

Ingesloten systemen bieden doorgaans geen standaard invoer-/uitvoerapparaten. Dit zou van invloed zijn op systeem- of bibliotheekaanroepen (voorbeeld: printf()).

Semihosting betekent dat de debugger (zie Stap 11-afbeelding met debugger-gedeelte rood omcirkeld) een speciaal kanaal heeft en het semihosting-protocol gebruikt, en u kunt de uitvoer van printf() op de hostmachine zien (via de debugger).

Retargeting daarentegen betekent dat diezelfde systeem- of bibliotheekaanroepen iets anders betekenen. Ze doen iets anders, wat logisch is voor het embedded systeem. In zekere zin, bijvoorbeeld voor printf(), is er een nieuwe implementatie, een opnieuw getargete implementatie van die functie.

Dat gezegd hebbende, de --specs=nosys.specs betekent dat we niet semi-hosting zullen zijn. Dat zou dan normaal gesproken betekenen dat we retargeten. Dat brengt ons bij de volgende vlag.

nostdlib

De linkeroptie -nostdlib wordt gebruikt om een programma te koppelen dat bedoeld is om standalone te draaien. -nostdlib impliceert de individuele opties -nodefaultlibs en -nostartfiles. Hieronder bespreken we de twee opties afzonderlijk, maar het meest typische gebruik is gewoon nostdlib voor one-stop-shopping. Bij het koppelen van een gehost programma worden standaard systeembibliotheken zoals libc standaard gekoppeld, waardoor het programma toegang heeft tot alle standaardfuncties (printf, strlen en vrienden). De linkeroptie -nodefaultlibs schakelt de koppeling met die standaardbibliotheken uit; de enige gekoppelde bibliotheken zijn precies die bibliotheken die u expliciet aan de linker noemt met behulp van de vlag -l.

lgcc

libgcc.a is een standaardbibliotheek die interne subroutines biedt om tekortkomingen van bepaalde machines te verhelpen. De ARM-processor bevat bijvoorbeeld geen deelinstructie. De ARM-versie van libgcc.a bevat een delingsfunctie en de compiler zendt waar nodig oproepen naar die functie uit.

T

Dit is slechts een manier om de linker te vertellen dit bestand als het linkerscript te gebruiken. In ons geval is de bestandsnaam linker.script.ld.

o hoofd.elf

Ten slotte vertellen we de linker wat de naam zal zijn van het uiteindelijke uitvoerbeeldbestand dat op ons apparaat zal worden gebrand / geflitst.

Hier is onze versie van de volledige opdrachtregel, aangepast voor onze specifieke situatie:

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

We zorgen ervoor dat het scriptbestand en het bestand core.o zich beide in dezelfde map bevinden, waar we de bovenstaande opdrachtregel uitvoeren.

En het koppelt zonder problemen.

Een controle

Wij lopen dan:

arm-none-eabi-nm main.elf

en we krijgen:

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

Ziet er goed uit. De opdracht arm-none-eabi-nm is een manier om symbolen in objectbestanden weer te geven.

Stap 10: Verbinding testen met de STM32 Nucleo-64

TestenVerbinding met de STM32 Nucleo-64
TestenVerbinding met de STM32 Nucleo-64
TestenVerbinding met de STM32 Nucleo-64
TestenVerbinding met de STM32 Nucleo-64

Je eerste missie, als je ervoor kiest om het te accepteren, is om je systeem je ontwikkelbord te laten zien.

Windows gebruiken

Voor Windows besloot ik TrueSTUDIO van Atollic te installeren (gratis versie). Het was een pijnloze installatie en het installeerde automatisch de driver, zodat ik st-link kon gebruiken om de verbinding te testen. Nadat ik TrueSTUDIO had geïnstalleerd en de apparaatbeheerder het apparaat zag, heb ik de Texaanse/stlink-tools gedownload die worden voorgesteld in het Bare Metal-artikel dat we hebben gevolgd. Ik plaatste de map opnieuw direct onder "C:\", en maakte opnieuw enkele links van mijn lokale cygwin-homebin naar de opdrachten.

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

Als eerste test om te zien of we echt met het apparaat kunnen communiceren, heb ik het volgende uitgevoerd:

st-info --probe

En teruggekomen:

1 stlink programmeurs gevonden

Dus nu weten we dat we met ons ontwikkelbord kunnen praten/vragen.

Linux gebruiken

Voor Linux heb je niet echt een driver nodig. Maar voor Debian moet u de st-tools vanaf de broncode bouwen.

git clone

Zorg ervoor dat libusb-1.0-0-dev is geïnstalleerd.

geschikte lijst | grep -E "*libusb.*dev*"

Je zou moeten zien:

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

of zoiets.

Om het te installeren:

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

Merk op dat het bovenstaande niet hetzelfde is als:

sudo apt-get install libusb-dev

De juiste ontbrekende libusb-ontwikkelaar kan ervoor zorgen dat cmake problemen heeft.

CMake-fout: de volgende variabelen worden in dit project gebruikt, maar ze zijn ingesteld op NOTFOUND. Stel ze in of zorg ervoor dat ze correct zijn ingesteld en getest in de CMake-bestanden: LIBUSB_INCLUDE_DIR (ADVANCED)

Ga naar de hoofdmap van het project (…blah/blah /stlink). Doe een "make release".

Na die builds zouden de tools onder ".. /build/Release" moeten staan.

U kunt dan "st-info --probe" uitvoeren. Hier is de output met de Nucleo aangesloten, dan niet.

devchu@chubox:~/Development/stlink$./build/Release/st-info --probeFound 1 stlink programmeurs serial: 303636414646353034393535363537 openocd: "\x30\x36\x36\x41\x46\x46\x35\x30\x34\ x39\x35\x35\x36\x35\x37" flash: 524288 (paginaformaat: 2048) sram: 65536 chipid: 0x0446 descr: F303 high-density device devchu@chubox:~/Development/stlink$./build/Release/st- info --probe 0 stlink programmeurs gevonden devchu@chubox:~/Development/stlink$

Stap 11: Laten we GDB gebruiken met Linux

Laten we GDB gebruiken met Linux
Laten we GDB gebruiken met Linux
Laten we GDB gebruiken met Linux
Laten we GDB gebruiken met Linux

Als je dit allemaal hebt geprobeerd en je bent zo ver gekomen - geweldig! Excellent. Laten we nu een beetje plezier hebben.

Wanneer je deze ARM-ontwikkelingsborden koopt, of het nu de MSP432 Launchpad van Texas Instruments is, of deze die we nu bespreken, de Nucleo-F303 (STM32 Nucleo-64), komen ze meestal al geflitst aan met een draaiend programma, meestal een of ander knipperend programma dat ook het indrukken van een schakelaar omvat om de snelheid waarmee de LED('s) knipperen te veranderen.

Voordat we dat zo snel overschrijven, laten we eens kijken wat er te zien en te doen is.

Open met Linux een terminal, verander de directory van het stlink git-project dat we zojuist hebben gebouwd en zoek de st-util-tool.

devchu@chubox:~/Development/stlink$ vinden. -naam st-util

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

Voer dat hulpprogramma uit. Omdat we onze verbinding met st-info --probe al eerder hebben getest, zouden we wat uitvoer moeten krijgen, zoals:

st-util 1.4.0-50-g7fafee2 2018-10-20T18:33:23 INFO common.c: Apparaatparameters laden…. 2018-10-20T18:33:23 INFO common.c: Verbonden apparaat is: F303 apparaat met hoge dichtheid, id 0x10036446 2018-10-20T18:33:23 INFO common.c: SRAM-grootte: 0x10000 bytes (64 KiB), Flash: 0x80000 bytes (512 KiB) in pagina's van 2048 bytes 2018-10-20T18:33:23 INFO gdb-server.c: Chip ID is 00000446, Core ID is 2ba01477. 2018-10-20T18:33:23 INFO gdb-server.c: Luisteren op *:4242…

Dat is de GDB-server die nu draait, en hij ziet ons ontwikkelbord, en nog belangrijker, hij luistert op poort 4242 (de standaardpoort).

Nu zijn we klaar om de GDB-client op te starten.

Open in Linux een andere terminal, voer dit in:

arm-none-eabi-gdb -tui

Dat is precies hetzelfde als gdb strikt via de opdrachtregel uitvoeren, maar in plaats daarvan produceert het een op tekst gebaseerde terminal (ik vermoed dat het vloeken gebruikt).

We hebben de GDB-client en de GDB-server draaien. De client is echter niet verbonden met de server. Op dit moment weet het niets over onze Nucleo (of board naar keuze). We moeten het vertellen. In de terminal zou uw prompt nu de "(gdb)" moeten zijn. Binnenkomen:

helpen richten

Het geeft je een lijst. Merk op dat degene die we willen is target extended-remote - Gebruik een externe computer via een seriële lijn.

Maar we moeten het ook de locatie geven. Dus, bij de (gdb) prompt, voer het volgende in:

(gdb) target extended-remote localhost:4242

U zou een antwoord moeten krijgen als volgt:

(gdb) target extended-remote localhost:4242

Foutopsporing op afstand met localhost:4242 0x080028e4 in ?? ()

Ondertussen, op de terminal met de st-util gdbserver, kregen we dit:

2018-10-20T18:42:30 INFO gdb-server.c: 6 hw-breekpuntregisters gevonden

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

Stap 12: Laten we herhalen, met Windows en Flash ons programma

Laten we herhalen, met Windows en Flash ons programma
Laten we herhalen, met Windows en Flash ons programma
Laten we herhalen, met Windows en Flash ons programma
Laten we herhalen, met Windows en Flash ons programma
Laten we herhalen, met Windows en Flash ons programma
Laten we herhalen, met Windows en Flash ons programma

De stappen voor het uitvoeren van de st-util gdbserver en de arm-none-eabi-gdb-client zijn in wezen hetzelfde als tijdens de vorige stap. U opent twee terminals (cygwin, DOS cmd of Windows Powershell), zoekt de locatie van het st-util op en voert het uit. Voer in de andere terminal de arm-none-eabi-gdb-client uit. Het enige verschil is dat de -tui-modus (op een terminal gebaseerde tekstweergave) hoogstwaarschijnlijk niet wordt ondersteund.

Als het bovenstaande werkte in Windows, dan zul je waarschijnlijk moeten stoppen (alleen de client). Op dit punt moet je op de een of andere manier de GDB-client uitvoeren waar je buildbestand is ("core.out"), of het volledige pad naar dat bestand toevoegen als argument voor de GDB-client.

Ik heb mijn leven vereenvoudigd door cygwin te gebruiken en links te maken vanuit mijn lokale $HOME//bin-directory naar waar beide tools zich bevinden.

Ok, we hebben net als voorheen gecompileerd en gelinkt, en we hebben het bestand main.elf klaar om te worden geflitst.

We hebben st-util in één venster. We herstarten de GDB-client, deze keer doen we:

arm-none-eabi-gdb main.elf

We laten het opstarten, wachten op de (gdb) prompt, doen hetzelfde verbindingscommando met de GDB-server (st-util), en we zijn klaar om het uitvoerbare bestand te flashen. Het is erg anti-klimatologisch:

(gdb) laden

Werkend met cygwin-terminals, is er een bekend probleem waarbij console-opdrachten soms niet worden uitgevoerd. Dus in ons geval was het venster waarop de server werd uitgevoerd volledig stil. Degene die de client uitvoert, waar we de belasting hebben uitgevoerd, voert dit uit:

Laadsectie.text, grootte 0x1c lma 0x8000000Startadres 0x8000000, laadgrootte 28 Overdrachtssnelheid: 1 KB/sec, 28 bytes/schrijven.

Stap 13: Knipperen met Linux - Meer lonend: D

Knipperen met Linux - Meer lonend:D
Knipperen met Linux - Meer lonend:D

Stap 14: Laten we een beetje dieper duiken

Als je hier bent, uitstekend. Laten we verder gaan.

Waarom kijk je niet in het main.elf-bestand, het uitvoerbare bestand? Voer het volgende uit:

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

Je zou een output moeten zien die er ongeveer zo uitziet:

main.elf: bestandsformaat elf32-littlearm

Demontage van sectie.text:

08000000:

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

08000008:

80000008: 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 voegt r0 toe, #1 8000012: e7fd b.n 8000010 8000014: 20014000.word 0x20014000 8000018: deadbeef.word 0xdeadbeef

Welke kleine goudklompjes kunnen we uit de bovenstaande output halen?

Als je je herinnert toen we het linker.script.ld-bestand bespraken en maakten, hebben we verklaard dat deze ARM-apparaten RAM hebben vanaf 0x20000000 en dat FLASH-geheugen begint bij 0x08000000.

We kunnen dus zien dat het programma inderdaad zo is dat het allemaal in het FLASH-geheugen staat.

Toen, hierboven, maar een latere stap, toen we het gedeelte "Hallo wereld" bespraken, was er een verklaring waarin we een onmiddellijke, constante, letterlijke waarde ("0xDEADBEEF") in een MCU-kernregister ("R7") laden.

De verklaring luidde:

LDR R7, =0xDEADBEEF

In onze code is dat de enige plaats waar we zelfs DEADBEEF noemen. Nergens anders. En toch, als je kijkt naar de bovenstaande gedemonteerde/gereconstrueerde instructies, enz., is er meer gerelateerd aan DEADBEEF dan we dachten dat we deden.

Dus de compiler/linker besloot op de een of andere manier om de waarde van DEADBEEF permanent te flashen naar een FLASH-adres, op locatie 0x8000018. En toen veranderde de compiler onze bovenstaande LDR-instructie in:

LDR R7, [PC, #8]

Het genereerde zelfs een opmerking voor ons. Wat leuk. En het vertelt ons om de huidige programmatellerwaarde (het pc-register) te nemen, 0x8 bij die waarde op te tellen, en dat is waar DEADBEEF is gebrand, en die waarde te krijgen en in R7 te stoppen.

Dus dat betekent ook dat de programmateller (PC) naar adres 0x8000010 wees, wat het begin is van de main_loop, en dat de DEADBEEF-waarde op twee adressen na het einde van de main_loop staat.

Stap 15: Eindelijk een korte blik op het programma dat wordt uitgevoerd

Zelfs als u GDB afsluit, voert u de opdracht gewoon opnieuw in. Je hoeft het niet eens een bestand te geven; we knipperen niet meer, we voeren het gewoon uit.

Nadat u de GDB-client opnieuw hebt verbonden met de GDB-server, bij de (gdb) opdrachtprompt:

(gdb) info registers

Je zou zoiets als dit moeten zien:

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 0x20014000x0x20014000 lrps 0x20014000

Maar voer dan bij de prompt (gdb) het volgende in:

(gdb) doorgaan

En druk heel snel op CTRL-C. Dat zou het programma moeten pauzeren. Voer het commando "info registers" opnieuw in.

Deze keer ziet het er anders uit:

(gdb) info registers

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 ffr12 0x095 0 pc 16777216

Wat is er gebeurd? Precies wat we wilden. DEADBEEF is in R7 geladen en R0 is (extreem snel) aan het toenemen. Als je herhaalt, zie je R0 weer met een andere waarde.

Stap 16: We wilden een alleen-lezen array in Flash maken

Een manier om het equivalent van een array te maken met behulp van assembly en richtlijnen, is als volgt:

.type myarray, %object // de naam of het label 'myarray' is gedefinieerd als een objecttype.

myarray: // dit is het begin van de declaratie van 'myarray' // (waar het uit zal bestaan)..word 0x11111111 // het eerste lid of de eerste waarde in 'myarray'..word 0x222222222 // de tweede waarde (aaneengesloten adressen)..word 0x33333333 // enzovoort..size myarray,.-myarray // de compiler/assembler weet nu waar het einde of de // grens van 'myarray'.

Nu we het in het FLASH-geheugen hebben ingesteld, kunnen we het in het programma gebruiken. Hieronder een gedeelte:

LDR R1, myarray // dit laadt gegevens op de eerste locatie van 'myarray'.' // dit is niet wat we willen.

LDR R1, =myarray // dit laadt de locatiewaarde zelf (het 1e adres), // niet de gegevens.. // dit IS wat we willen.

MOV R2, #0 // R2 houdt een telling bij om ervoor te zorgen dat we niet weglopen

// einde van array. LDR R3, =myarrsize // R3 zal het equivalent zijn van 'myarrsize'.

// R0 houdt onze gegevens vast

Hoofdlus:

LDR R0, [R1] // Laad de gegevens waarnaar wordt verwezen door R1 ('myarray') in R0. CMP R2, R3 // Zijn we aan de limiet van de array? BEQ main_loop // Als dat zo is, zijn we klaar, dus we blijven voor altijd in een lus.

ADD R2, #1 // Anders kunnen we door de array blijven itereren.

ADD R1, #4 // Voeg 4 toe om R1 te registreren, zodat het correct naar de volgende verwijst

// adres..

B main_loop // Loop terug.

De video doorloopt dit allemaal en er zit een bug in. Het is goed; het laat zien dat het belangrijk is om code uit te voeren en te debuggen. Het toont een klassiek geval van het einde van een array lopen.

Aanbevolen: