Përmbajtje:

Pjesa 1 Kuvendi i ARM TI RSLK Laboratori i Kurrikulës së Mësimit Robotik 7 STM32 Bërthamë: 16 Hapa
Pjesa 1 Kuvendi i ARM TI RSLK Laboratori i Kurrikulës së Mësimit Robotik 7 STM32 Bërthamë: 16 Hapa

Video: Pjesa 1 Kuvendi i ARM TI RSLK Laboratori i Kurrikulës së Mësimit Robotik 7 STM32 Bërthamë: 16 Hapa

Video: Pjesa 1 Kuvendi i ARM TI RSLK Laboratori i Kurrikulës së Mësimit Robotik 7 STM32 Bërthamë: 16 Hapa
Video: Солярис. Серия 2 (FullHD, фантастика, реж. Андрей Тарковский, 1972 г.) 2024, Korrik
Anonim
Image
Image

Fokusi i këtij Instructable është mikrokontrolluesi STM32 Nucleo. Motivimi për këtë që të jetë në gjendje të krijojë një projekt montimi nga kockat e zhveshura. Kjo do të na ndihmojë të thellohemi dhe të kuptojmë projektin MSP432 Launchpad (TI-RSLK) që tashmë ka qenë temë e disa Instructables.

Nuk ka shumë ndihmë në internet për të krijuar një projekt vetëm për montim për MSP432, duke përdorur Studio Composer Studio. Deri tani ne thjesht kemi kopjuar/ngjitur nga një projekt montimi para-ekzistues. Kjo qasje na ka shërbyer mirë.

Sidoqoftë, tani, për Lab 7, ne kemi hasur pak në një problem. Ose të paktën një lemzë të përkohshme. Lab 7 prezanton makina me gjendje të fundme, dhe gjëja e parë që hasim është nevoja për të krijuar dhe përdorur një grup vlerash. Meqenëse kursi TI përdor kryesisht programimin C - ky nuk është problem. Por këto udhëzime janë përqendruar në montimin, jo C.

Më tej, meqenëse grupi ka vlera vetëm për lexim, do të ishte mirë ta vendosnim në flash memorie, jo në RAM.

Duket se ka shumë më tepër ndihmë në internet për projektet e montimit duke përdorur STM32 MCU, kështu që, ne fillojmë me këtë Instructable, me qëllim të përdorimit të asaj që është mësuar, për të aplikuar më pas në MSP432 dhe Studio Composer Code.

Në rrugën drejt këtij qëllimi, ne gjithashtu do të kemi marrë përvojë me një mikrokontrollues tjetër popullor.

Hapi 1: Testi fillestar i pajisjes

Testi fillestar i pajisjes
Testi fillestar i pajisjes
Testi fillestar i pajisjes
Testi fillestar i pajisjes
Testi fillestar i pajisjes
Testi fillestar i pajisjes

Përsëri, pse të zgjedhim STM32 Nucleo në veçanti?

Sinqerisht? Sepse po kërkoja artikuj të mirë për projektet e montimit të metaleve të zhveshura për kontrolluesit ARM, dhe hasa në këtë seri. Dhe gjithashtu sepse STM32 duket të jetë një MCU popullore.

Unë bëra disa kërkime (ka shumë versione për të zgjedhur - shiko imazhin më lart), por në fund u bë ajo që mund të marr në të vërtetë, pasi do të përdorja Amazon (në SHBA).

Vjen në një paketë të thjeshtë por profesionale, me disa udhëzime fillestare. Ishte pak qesharake të shihje se demonstrimi i djegur në kontrollues ishte pothuajse pikërisht ajo që kemi bërë në Instructables të kaluar - një LED ndizet dhe ndryshon shpejtësinë sipas shtypjes së një butoni.

Duket se ky bord zhvillimi është shumë i ngjashëm me MSP432 në atë që ka 2 LED, dhe një buton të përdoruesit. MSP432 ka 2 butona përdoruesi.

Siç mund ta shihni në fotografi, u befasova pak se bordi ka një mini dhe jo një mikro USB. Duhej të mbaronte për të blerë një kordon.

Një test tjetër i mirë është se kur e lidhni me kompjuterin tuaj (unë jam duke përdorur një kuti Linux), ai shfaqet në menaxherin tim të skedarëve, si një sistem skedarësh, i quajtur "NODE_F303RE". Hapja që zbulon dy skedarë, një HTML dhe një tekst.

Kjo është e gjitha, por të paktën thotë gjithashtu se lidhja duket mjaft e lehtë.

Tani jemi gati për të filluar.

Unë do të përpiqem të mos përsëris asnjë nga informacionet e mira nga seria e artikujve IVONOMICON Bare Metal, por përkundrazi ta shtoj atë.

Hapi 2: Thelbësore

Gjëja e parë që na nevojitet është një përpilues.

Dhe pastaj, ne kemi nevojë për një korrigjues:

devchu@chubox: ~ $ sudo apt-get install gdb-arm-none-eabiLeximi i listave të paketave … U krye Ndërtimi i pemës së varësisë Leximi i informacionit të gjendjes… U krye Pakot e reja të mëposhtme do të instalohen: gdb-arm-none-eabi 0 të azhurnuara, 1 të reja instaluar, 0 për të hequr dhe 8 jo të azhurnuar. Duhet të merrni 2, 722 kB arkiva. Pas këtij operacioni, do të përdoren 7, 738 kB hapësirë shtesë në disk. Merrni: 1 https://us.archive.ubuntu.com/ubuntu xenial/univers amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3+9 [2, 722 kB] Marrë 2, 722 kB në 1s (1, 988 kB/s) Zgjedhja e paketës së pazgjedhur më parë gdb-arm-none-eabi. (Leximi i bazës së të dhënave… 262428 skedarë dhe drejtori aktualisht të instaluara.) Përgatitja për shpaketimin…/gdb-arm-none-eabi_7.10-1ubuntu3+9_amd64.deb… Shpaketimi i gdb-arm-none-eabi (7.10-1ubuntu3+9)… Përpunimi shkakton për njeriun-db (2.7.5-1)… Konfigurimi i gdb-arm-none-eabi (7.10-1ubuntu3+9)…

Hapi 3: Thelbësore - Windows

Hapi i mësipërm supozoi se ne po përdorim Linux. Po sikur të përdorim Windows?

Ju mund të shkoni në faqen e zhvilluesit të krahut, dhe ka disa mundësi shkarkimi në dispozicion. Unë jam duke përdorur një makinë Windows 8.

Gjatë instalimit, unë zgjodha ta instaloja atë në rrënjën "C: \" në vend të Program Files vetëm sepse po përdor gjithashtu cygwin, dhe ishte më e lehtë të krijoja një lidhje nga koshi im lokal në një dosje rrënjë C: sesa të gjitha rrëmujë në rrugën për Program Files (me hapësira, etj).

Kështu, mjedisi dhe rruga ime cygwin, etj., Duket kështu:

C: / cygwin64 / home / bin / arm-none-eabi-gcc, ku krah-none-eabi-gcc është një lidhje me C: / GNUToolsArmEmbedded / 7.2018.q2.update / bin / arm-none-eabi- gcc

Unë pastaj krijova një dosje "dev" nën cygwin home, dhe aty vendosa skedarin core. S dhe ekzekutova komandën e përpiluesit. (shih më poshtë më poshtë për artikujt e përpiluesit).

Unë bëra të njëjtën gjë për gdb (arm-none-eabi-gdb).

Hapi 4: Cilat janë gjërat thelbësore

Pra, çfarë është "gcc-arm-none-eabi"?

Përpiluesi gnu (GCC) do të përpilojë gjuhë programimi (si C) në kodin amë për makinën në të cilën po funksionon. Për shembull, nëse do të përpilonit ndonjë kod C duke përdorur GCC në kompjuterin tuaj Windows, ai do të ndërtohej për të funksionuar në kompjuterin Windows. Ekzekutivi i krijuar nuk do të funksionojë (zakonisht) në mikrokontrolluesin ARM.

Pra, në mënyrë që të ndërtojmë programe që do të shkarkohen dhe digjen në mikrokontrolluesin ARM (në rastin tonë aktual që do të ishte STM32 Nucelo), ne duhet t'i japim GCC diçka tjetër: aftësinë për të "përpiluar kryq". Kjo është, aftësia për të gjeneruar një ekzekutues, jo për sistemin e tij amë (dhe procesorin), por për sistemin e synuar (mikrokontrolluesi ARM). Aty hyn në lojë "gcc-arm-none-eabi".

Atëherë, çfarë është "gdb-arm-none-eabi"?

Pasi të kemi shkarkuar dhe djegur (ndezur) ekzekutuesin e ri të krijuar në mikrokontrollues, me siguri do të duam ta korrigjojmë atë-hap pas rreshti për rreshtin e kodit. GDB është korrigjuesi i gnu, dhe gjithashtu ka nevojë për një mënyrë për të bërë punën e tij, por duke synuar një sistem tjetër.

Kështu, gdb-arm-none-eabi është për GDB, çfarë gcc-arm-none-eabi është për GCC.

Një tjetër instalim i sugjeruar i paketës ishte "libnewlib-arm-none-eabi". Çfarë është ai?

Newlib është një bibliotekë C dhe bibliotekë matematikore e destinuar për përdorim në sistemet e ngulitura. Shtë një konglomerat i disa pjesëve të bibliotekës, të gjitha nën licenca të softuerit falas që i bëjnë ato lehtësisht të përdorshme në produktet e ngulitura.

Dhe së fundi, paketa "libstdc ++-arm-none-eabi". Kjo është mjaft e qartë; është biblioteka C ++ për përpiluesin ndër-përbërës; për mikrokontrolluesit e integruar të ARM.

Hapi 5: Skedari Linker

Skedari Linker
Skedari Linker
Skedari Linker
Skedari Linker

Le të krijojmë një skenar lidhës.

Një pjesë kryesore ose bllok në këtë skedar do të ishte komanda MEMORY.

--- nga sourceware.org:

Konfigurimi i paracaktuar i lidhësit lejon ndarjen e të gjithë kujtesës në dispozicion. Ju mund ta anashkaloni këtë duke përdorur komandën MEMORY. Komanda MEMORY përshkruan vendndodhjen dhe madhësinë e blloqeve të kujtesës në objektiv. Mund ta përdorni për të përshkruar se cilat zona të kujtesës mund të përdoren nga lidhësi dhe cilat zona të kujtesës duhet të shmangë. Pastaj mund të caktoni seksione në rajone të veçanta të kujtesës. Lidhësi do të vendosë adresat e seksioneve bazuar në rajonet e kujtesës dhe do të paralajmërojë për rajonet që bëhen shumë të plota. Lidhësi nuk do të ndryshojë seksionet për t'u përshtatur në rajonet në dispozicion. Një skenar lidhës mund të përmbajë shumë përdorime të komandës MEMORY, megjithatë, të gjitha blloqet e kujtesës të përcaktuara trajtohen sikur të ishin specifikuar brenda një komande të vetme MEMORY. Sintaksa për MEMORY është:

KUJTIMI

{emri [(atr)]: ORIGJINA = origjina, Gjatësia = len…}

Shembulli në artikull:

/* Përcaktoni fundin e RAM -it dhe kufirin e kujtesës së stekut* //* (4KB SRAM në linjën STM32F031x6, 4096 = 0x1000)*//* (RAM fillon në adresën 0x20000000) _estack = 0x20001000;

KUJTIMI

{FLASH (rx): ORIGJINA = 0x08000000, LENGTH = 32K RAM (rxw): ORIGJINA = 0x20000000, Gjatësia = 4K}

Pra, ne duhet të kuptojmë se sa FLASH (për programin dhe konstantet tona, etj) dhe sa RAM (për përdorim nga programi; grumbull dhe grumbull, etj) për bordin tonë të veçantë. Kjo bëhet pak interesante.

Karta e bukur e vogël që vjen me Nucleo thotë se ajo ka memorie flash është 512 Kbytes, dhe SRAM është 80 Kbytes. Sidoqoftë, duke e lidhur atë me USB, montohet si një sistem skedarësh me dy skedarë, dhe menaxheri i skedarëve dhe GParted tregojnë se ka mbi 540+ Kbytes hapësirë. (RAM?).

POR, përpjekja për të fshirë dy skedarë duke përdorur menaxherin e skedarëve, shkëputjen dhe rilidhjen e pajisjes, ende i tregon dy skedarët. (dhe menaxheri i skedarëve vërtet njohu diçka sepse ka një ikonë të vogël "bllokimi" në secilën skedar.

Pra, le të shkojmë me figurat në kartelë. Pra, tani marrim shembullin e mësipërm dhe e konvertojmë atë në tabelën tonë specifike.

Ju mund të dëshironi të përdorni diçka si ky konvertues i kujtesës në internet, për të kaluar nga KB e përgjithshme në një numër specifik të bajtëve.

Atëherë mund të dëshironi të përdorni një konvertues dhjetor në gjashtëkëndësh në internet.

/ * Përcaktoni fundin e RAM -it dhe kufirin e kujtesës së stivës */

/* (4KB SRAM në linjën STM32F031x6, 4096 = 0x1000)* //* shembulli*/

/ * hapi 1: (80KB SRAM në STM32F303RE, 81920 = 0x14000) * // * bordi ynë */

/* hapi 2, shtoni madhësinë gjashtëkëndore në adresën fillestare gjashtëkëndore (më poshtë). */

/ * (RAM fillon në adresën 0x20000000) */

_stack = 0x20001000; / * shembulli */

_stack = 0x20014000; / * bordi ynë */

MEMORY {

FLASH (rx): ORIGJINA = 0x08000000, Gjatësia = 512K

RAM (rxw): ORIGJINA = 0x20000000, Gjatësia = 80K

}

Le ta quajmë skedarin e mësipërm "linker.script.ld".

Hapi 6: Tabela e vektorit

Tabela e vektorit
Tabela e vektorit

Tani ne do të krijojmë një skedar të vogël montimi (me direktiva) për të bërë një trajtim shumë themelor të ndërprerjeve. Ne do të ndjekim shembullin e artikullit dhe do të krijojmë një skedar të quajtur "core. S".

Përsëri, këtu është shembulli i përmbajtjes së skedarit, por unë bëra një ndryshim për tabelën tonë specifike:

// Këto udhëzime përcaktojnë atributet e çipit tonë dhe

// gjuha e asamblesë që do të përdorim:. sintaksë e unifikuar /*Shih më poshtë pas kësaj zone kodi* //*.cpu cortex-m0* / /*komentoni këtë linjë të shembullit* /.cpu cortex-m4 /* në vend të kësaj shtoni korteksin e bordit tonë. shihni imazhin e mësipërm në këtë hap * / /*.fpu softvfp * / / *komentoni këtë rresht të shembullit * /.fpu vfpv4 / *shtoni në vend të bordit tonë; ai ka një FPU */.thumb // Vendndodhjet e kujtesës globale..global vtable.global reset_handler / * * Tabela aktuale vektoriale. * Përfshihen vetëm madhësia e RAM -it dhe mbajtësi i 'rivendosjes', për thjeshtësi. */.type vtable, %object vtable:.word _estack.word reset_handler. madhësi vtable,.-vtable

Hmm.. Jo ". Align" Direktiva

Megjithatë, kjo nuk është kritike. Më shumë për këtë (ndoshta) më vonë.

.sintaksë e unifikuar

.sintaksë [e unifikuar | e ndare]

Kjo direktivë vendos Sintaksën e Set Instruksioneve siç përshkruhet në seksionin ARM-Instruction-Set

9.4.2.1 Sintaksa e Set Instruksioneve Dy sintaksa pak të ndryshme janë mbështetje për udhëzimet ARM dhe THUMB. Parazgjedhja, e ndarë, përdor stilin e vjetër ku udhëzimet ARM dhe THUMB kishin sintaksat e tyre të veçanta. Sintaksa e re, e unifikuar, e cila mund të zgjidhet nëpërmjet direktivës.sintaksë.

.fpu vfpv4

Përpiluesi GCC mund të prodhojë binare me disa opsione në lidhje me pikën lundruese: soft - i përshtatshëm për të punuar në CPU pa FPU - llogaritjet bëhen në softuer nga softfp i krijuar nga përpiluesi - i përshtatshëm për të punuar në CPU me ose pa FPU - do të përdorë një FPU nëse është i pranishëm Me Për rastin tonë specifik (do t'ju duhet të bëni kërkimin tuaj), FPU -ja e këtij bordi të veçantë përputhet me vfpv4. Ju mund të keni për të luajtur me këtë. Ose edhe lëreni në softfp.

.thumb (kundrejt armës)

Këta mikrokontrollues ARM në fakt kanë një përzierje të grupeve udhëzuese. Njëra është ARM, një tjetër është THUMB. Një ndryshim janë udhëzimet 16-bit kundrejt udhëzimeve 32-bit. Kështu, kjo direktivë i thotë përpiluesit të trajtojë udhëzimet pasuese si THUMB ose ARM.

Ne do të marrim vetëm pjesën e mbetur të skedarit ashtu siç është, pasi këto Instructables ende nuk janë futur në programimin e montimit të drejtuar nga ndërprerja.

Hapi 7: Versioni i Asamblesë i një Programi 'Përshëndetje Botërore'

Më poshtë mund të hyni gjithashtu në skedarin "core. S" të krijuar më parë. Kjo, përsëri, është nga shembulli në artikull.

/ * * Trajtuesi i Rivendosjes. Thirret në rivendosje. */.type reset_handler, %function reset_handler: // Vendosni treguesin e pirgut në fund të pirgut. // Vlera '_estack' përcaktohet në skenarin tonë të lidhësit. LDR r0, = _estack MOV sp, r0

// Vendosni disa vlera fals. Kur i shohim këto vlera

// në korrigjuesin tonë, ne do të dimë që programi ynë // është i ngarkuar në çip dhe punon. LDR r7, = 0xDEADBEEF MOVS r0, #0 main_loop: // Shto 1 për të regjistruar 'r0'. ADDS r0, r0, #1 // Lak mbrapa. B main_loop.size reset_handler,.-Reset_handler

Pra, qëllimi i programit të mësipërm është të ngarkojë një model të njohur në një regjistër bazë MCU (në këtë rast R7), dhe një vlerë në rritje duke filluar nga zero në një regjistër tjetër bazë MCU (në këtë rast R0). Nëse kalojmë nëpër kodin ekzekutues, duhet të shohim rritjen e të dhënave të R0.

Nëse keni qenë duke ndjekur së bashku me Instructables në lidhje me MSP432 dhe kursin/laboratorët TI-RSLK, atëherë pothuajse i gjithë programi i mësipërm duhet të jetë i njohur për ju.

Një gjë e re që mund të shoh është përdorimi i "=" kur ngarkoni "DEADBEEF" për të regjistruar R7. Ne nuk e kishim përdorur atë.

Skedari "core. S" i bashkangjitur këtu tani përmban burimin e plotë.

Hapi 8: Përpilimi i Kodit

Timeshtë koha për të bërë disa gjëra të linjës së komandës. Diçka e vërtetë, më në fund.

Sidoqoftë, ne nuk jemi fare atje. Ne përsëri duhet të ndryshojmë komandën e dhënë në artikull dhe ta modifikojmë atë në situatën tonë.

Këtu është kodi shembull:

arm -none -eabi -gcc -x assembler -with -cpp -c -O0 -mcpu = cortex -m0 -mthumb -Bërthama e murit. S -o core.o

Nëse shkojmë në faqen e gnu.org për GCC, (në këtë rast versioni 7.3),

x

-X është të specifikoni gjuhën. Përndryshe nëse jo -x, atëherë përpiluesi do të përpiqet të marrë me mend duke përdorur shtesën e skedarit. (në rastin tonë, *. S).

Shembulli i mësipërm nga artikulli specifikon assembler-with-cpp, por ne thjesht mund të bëjmë montues.

c

-C thotë përpiloni por mos lidhni.

O0

-O është të vendosë nivelin e optimizimit. Përdorimi i -O0 (oh -zero) thotë "zvogëloni kohën e përpilimit dhe bëni që korrigjimi të prodhojë rezultatet e pritura. Ky është parazgjedhja".

mcpu = korteksi-m0

-Mcpu specifikon emrin e procesorit të synuar. Në rastin tonë, do të ishte lëvore-m4.

mumbi

-Mthumb specifikon zgjedhjen midis kodit gjenerues që ekzekuton gjendjet ARM dhe THUMB.

Mur

-Muri është sigurisht shumë i zakonshëm dhe i mirënjohur. Ndiz të gjithë flamujt paralajmërues.

Së fundi, në fund të komandës kemi fajllin hyrës core. S dhe skedarin dalës core.o.

Këtu është linja e re e komandës që rezulton për t'iu përshtatur rastit tonë specifik.

arm -none -eabi -gcc -x assembler -c -O0 -mcpu = korteksi -m4 -mthumb -Bërthama e murit. S -o thelb.o

Dhe kjo u përpilua.

Hapi 9: Lidhja e Programit

Direkt nga shembulli në artikull, kemi këtë:

arm -none -eabi -gcc core.o -mcpu = korteksi -m0 -mthumb -Mur --specs = nosys.specs -nostdlib -lgcc -T./STM32F031K6T6.ld -o kryesore.elf

Shumica e sa më sipër që keni parë. Më poshtë është ajo që ka të re.

-specs = nosys.specs

Ky është pak i ndërlikuar për tu shpjeguar.

Ka të bëjë me "semihosting" dhe "retargeting", dhe ka të bëjë me input / output. Ajo gjithashtu ka të bëjë me thirrjet e sistemit dhe bibliotekat.

Në mënyrë tipike, sistemet e ngulitura nuk ofrojnë pajisje standarde hyrje/dalje. Kjo do të ndikonte në thirrjet e sistemit ose të bibliotekës (shembull: printf ()).

Semihosting do të thotë që korrigjuesi (shiko figurën e Hapit 11 me pjesën e korrigjuesit të rrethuar me të kuqe) ka një kanal të veçantë dhe përdor protokollin semihosting, dhe ju mund të shihni daljen e printf () në makinën pritëse (përmes korrigjuesit).

Rivënia në shënjestër, nga ana tjetër, do të thotë që ato të njëjtat thirrje të sistemit ose bibliotekës nënkuptojnë diçka tjetër. Ata bëjnë diçka tjetër, që ka kuptim për sistemin e ngulitur. Në një kuptim, të themi për printf (), ka një zbatim të ri, një zbatim të synuar të atij funksioni.

Duke thënë të gjitha këto, --specs = nosys.specs do të thotë që ne nuk do të jemi semihosting. Kjo normalisht do të thotë atëherë ne jemi duke u synuar përsëri. Kjo na çon në flamurin tjetër.

nostdlib

Opsioni lidhës -nostdlib përdoret për të lidhur një program që synon të ekzekutohet i pavarur. -nostdlib nënkupton opsionet individuale -nodefaultlibs dhe -nostartfiles. Më poshtë ne diskutojmë dy opsionet veç e veç, por përdorimi më tipik është vetëm nostdlib për blerje me një ndalesë. Kur lidhni një program të pritur, bibliotekat standarde të sistemit si libc lidhen si parazgjedhje, duke i dhënë programit akses në të gjitha funksionet standarde (printf, strlen dhe miq). Opsioni lidhës -nodefaultlibs çaktivizon lidhjen me ato biblioteka të paracaktuara; bibliotekat e vetme të lidhura janë pikërisht ato që ju i vendosni në mënyrë eksplicite në lidhësin duke përdorur flamurin -l.

lgcc

libgcc.a është një bibliotekë standarde që ofron nënrutina të brendshme për të kapërcyer mangësitë e makinave të veçanta. Për shembull, procesori ARM nuk përfshin një udhëzim të ndarjes. Versioni ARM i libgcc.a përfshin një funksion ndarjeje dhe përpiluesi lëshon thirrje në atë funksion aty ku është e nevojshme.

T

Kjo është vetëm një mënyrë për t'i thënë lidhësit të përdorë këtë skedar si skenar lidhës. Në rastin tonë, emri i skedarit është linker.script.ld.

o kryesore.vete

Së fundi, ne i themi lidhësit se si do të jetë emri i skedarit përfundimtar të imazhit që do të digjet/ndizet në pajisjen tonë.

Këtu është versioni ynë i vijës së plotë të komandës, i modifikuar për situatën tonë specifike:

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

Ne sigurohemi që skedari skript, dhe skedari core.o, të jenë të dy në të njëjtin drejtori, ku do të ekzekutojmë vijën e komandës së mësipërme.

Dhe lidhet pa probleme.

Nje kontroll

Ne pastaj vrapojmë:

krah-askush-eabi-nm kryesor.vete

dhe marrim:

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

Duket mirë. Komanda arm-none-eabi-nm është një mënyrë për të renditur simbolet brenda skedarëve të objektit.

Hapi 10: Testimi i lidhjes me STM32 Nucleo-64

Testimi Lidhja me STM32 Nucleo-64
Testimi Lidhja me STM32 Nucleo-64
Testimi Lidhja me STM32 Nucleo-64
Testimi Lidhja me STM32 Nucleo-64

Misioni juaj i parë, nëse zgjidhni ta pranoni atë, është që ta bëni sistemin tuaj të shohë tabelën tuaj të zhvillimit.

Duke përdorur Windows

Për Windows, vendosa të instaloj TrueSTUDIO nga Atollic (version falas). Ishte një instalim pa dhimbje dhe instaloi automatikisht drejtuesin, kështu që unë mund të përdor st-link për të testuar lidhjen. Sapo instalova TrueSTUDIO dhe menaxheri i pajisjes pa pajisjen, unë shkarkova mjetet texan/stlink të sugjeruara nga artikulli Bare Metal që kemi ndjekur. Unë përsëri e vendosa dosjen drejtpërdrejt nën "C: \", dhe përsëri krijova disa lidhje nga koshi im lokal i cygwin në komandat.

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

Si një test fillestar për të parë nëse vërtet mund të komunikojmë me pajisjen, unë vrapova:

st-info-sondë

Dhe u ktheva:

U gjetën 1 programues të ndërlikuar

Pra, tani e dimë që mund të flasim/pyesim bordin tonë të zhvillimit.

Duke përdorur Linux

Për linux, nuk keni nevojë vërtet për një shofer. Por për Debian, do t'ju duhet të krijoni mjetet e st nga burimi.

git klon

Sigurohuni që keni të instaluar libusb-1.0-0-dev.

lista e përshtatshme | grep -E "*libusb.*dev*"

Ju duhet të shihni:

libusb-1.0-0-dev/xenial, tani 2: 1.0.20-1 amd64 [instaluar]

ose diçka e tillë.

Për ta instaluar:

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

Vini re se sa më sipër nuk është e njëjtë me:

sudo apt-get install libusb-dev

Zhvilluesi i saktë i libusb që mungon mund të bëjë që cmake të ketë probleme.

Gabim CMake: Variablat e mëposhtëm përdoren në këtë projekt, por ato janë vendosur në NOTFOUND. Ju lutemi vendosni ato ose sigurohuni që ato janë vendosur dhe testuar saktë në skedarët CMake: LIBUSB_INCLUDE_DIR (PVRPARA)

Ndryshimi në drejtorinë rrënjësore të projektit (… blah /blah /stlink). Bëni një "lëshim".

Pas ndërtimit, mjetet duhet të jenë nën ".. /build /Release".

Atëherë mund të ekzekutoni "st-info --probe". Këtu është dalja me Nucleo të lidhur, atëherë jo.

devchu@chubox: ~/Development/stlink $./build/Release/st-info --probeGjetur 1 serial programuesish stlink: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "flash: 524288 (madhësia e faqeve: 2048) sram: 65536 chipid: 0x0446 descr: F303 pajisje me densitet të lartë devchu@chubox: ~/Development/stlink $./build/Release/st- info -sonda u gjetën 0 stlink programmers devchu@chubox: ~/Development/stlink $

Hapi 11: Le të përdorim GDB Me Linux

Le të përdorim GDB Me Linux
Le të përdorim GDB Me Linux
Le të përdorim GDB Me Linux
Le të përdorim GDB Me Linux

Nëse i keni provuar të gjitha këto dhe keni arritur deri këtu - shkëlqyeshëm! Shkëlqyeshëm. Le të argëtohemi pak tani.

Kur blini këto borde zhvillimi ARM, qofshin ato MSP432 Launchpad nga Texas Instruments, ose këtë që po diskutojmë tani, Nucleo-F303 (STM32 Nucleo-64), ato zakonisht mbërrijnë tashmë të ndezura me një program drejtimi, zakonisht ndonjë program blinky që përfshin gjithashtu shtypjen e një çelësi për të ndryshuar shkallën në të cilën LED (et) ndizen.

Përpara se të jemi kaq të shpejtë për të shkruar mbi këtë, le të shohim se çfarë ka për të parë dhe bërë.

Me Linux, hapni një terminal, ndryshoni drejtorinë projektin stlink git që sapo kemi ndërtuar dhe gjeni mjetin st-util.

devchu@chubox: ~/Development/stlink $ find. -emër st-util

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

Drejtojeni atë mjet. Meqenëse ne tashmë e kemi testuar lidhjen tonë me sondën st-info, duhet të marrim një dalje si kjo:

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

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 INFO e zakonshme.c: Po ngarkoni parametrat e pajisjes…. 2018-10-20T18: 33: 23 INFO e zakonshme.c: Pajisja e lidhur është: F303 pajisje me densitet të lartë, id 0x10036446 2018-10-20T18: 33: 23 INFO e zakonshme.c: Madhësia SRAM: 0x10000 bajt (64 KiB), Flash: 0x80000 bytes (512 KiB) në faqe të 2048 bytes 2018-10-20T18: 33: 23 INFO gdb-server.c: ID e çipit është 00000446, ID bazë është 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: Dëgjimi në *: 4242…

Ky është serveri GDB që funksionon tani, dhe sheh bordin tonë të zhvillimit, dhe më e rëndësishmja, ai po dëgjon në portin 4242 (porta e paracaktuar).

Tani ne jemi gati të ndezim klientin GDB.

Në Linux, hapni një terminal tjetër, futni këtë:

krah-asnjë-eabi-gdb -tui

Kjo është e njëjtë me drejtimin e linjës komanduese të gdb, por në vend të kësaj prodhon një terminal të bazuar në tekst (supozimi im është se përdor mallkime).

Ne kemi klientin GDB dhe serverin GDB që funksionojnë. Sidoqoftë, klienti nuk është i lidhur me serverin. Për momentin nuk di asgjë për Nucleo -në tonë (ose bordin e zgjedhur nga ju). Duhet ta themi. Në terminal, kërkesa juaj tani duhet të jetë "(gdb)". Shkruani:

objektivi i ndihmës

Do t'ju japë një listë. Vini re se ai që duam është synimi i zgjeruar -i largët - Përdorni një kompjuter në distancë përmes një linje serike.

Por ne gjithashtu duhet t'i japim vendndodhjen. Pra, në kërkesën (gdb), futni:

(gdb) synimi i zgjeruar-i largët localhost: 4242

Ju duhet të merrni një përgjigje diçka si kjo:

(gdb) synimi i zgjeruar-i largët localhost: 4242

Korrigjimi në distancë duke përdorur localhost: 4242 0x080028e4 in ?? ()

Ndërkohë, në terminalin që drejton st-util gdbserver, morëm këtë:

2018-10-20T18: 42: 30 INFO gdb-server.c: U gjetën regjistra të pikave të prishjes 6 hw

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

Hapi 12: Le të përsërisim, me Windows dhe Flash Programin tonë

Le të Përsërisim, Me Windows dhe Flash Programin tonë
Le të Përsërisim, Me Windows dhe Flash Programin tonë
Le të Përsërisim, Me Windows dhe Flash Programin tonë
Le të Përsërisim, Me Windows dhe Flash Programin tonë
Le të Përsërisim, Me Windows dhe Flash Programin tonë
Le të Përsërisim, Me Windows dhe Flash Programin tonë

Hapat për drejtimin e st-util gdbserver, dhe klienti arm-none-eabi-gdb janë në thelb të njëjta me ato që bëmë gjatë Hapit të mëparshëm. Ju hapni dy terminale (cygwin, DOS cmd ose Windows Powershell), gjeni vendndodhjen e st-util, drejtojeni atë. Në terminalin tjetër, drejtoni klientin arm-none-eabi-gdb. Dallimi i vetëm është se mënyra -tui (pamja e tekstit e bazuar në terminal) ka shumë të ngjarë të mos mbështetet.

Nëse sa më sipër funksiononte në Windows, atëherë me siguri do të duhet të ndaleni (vetëm klienti). Në këtë pikë, disi do t'ju duhet të ekzekutoni klientin GDB ku është skedari juaj i ndërtuar ("core.out"), ose të shtoni të gjithë shtegun në atë skedar si një argument për klientin GDB.

Unë thjeshtova jetën time duke përdorur cygwin dhe duke krijuar lidhje nga drejtoria ime lokale $ HOME // bin ku ndodhen të dyja këto mjete.

Ok, ne kemi përpiluar dhe lidhur ashtu si më parë, dhe ne kemi skedarin main.elf gati për t'u ndezur.

Ne kemi st-util që funksionon në një dritare. Ne e rifillojmë klientin GDB, këtë herë bëjmë:

arm-none-eabi-gdb kryesore.vete

E lëmë të fillojë, presim kërkesën (gdb), bëjmë të njëjtën komandën tonë të lidhjes me serverin GDB (st-util), dhe ne jemi gati të ndezim ekzekutuesin. Veryshtë shumë antiklimatike:

(gdb) ngarkesë

Duke punuar me terminalet cygwin, ka një problem të njohur me komandat e tastierës që nuk dalin. Pra, në rastin tonë, dritarja që drejtonte serverin ishte plotësisht e heshtur. Ai që drejton klientin, ku kemi drejtuar ngarkesën, jep këtë:

Seksioni i ngarkimit.teksti, madhësia 0x1c lma 0x8000000 Adresa e fillimit 0x8000000, madhësia e ngarkesës 28 Shkalla e transferimit: 1 KB/sek, 28 bajt/shkrim.

Hapi 13: Ndezje me Linux - Më shumë shpërblim: D

Ndezje me Linux - Më shumë shpërblim: D
Ndezje me Linux - Më shumë shpërblim: D

Hapi 14: Le të zhytemi pak më thellë

Nëse keni arritur këtu, shkëlqyeshëm. Le të vazhdojmë.

Pse të mos shikoni brenda skedarit main.elf, të ekzekutueshëm? Drejtoni sa vijon:

krahu-asnje-eabi-objdump -d kryesor.vete

Ju duhet të shihni një dalje diçka si kjo:

main.elf: format skedari elf32-littlearm

Çmontimi i seksionit.teksti:

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 lëvizje r0, #0

08000010:

8000010: 3001 shton r0, #1 8000012: e7fd b.n 8000010 8000014: 20014000.fjalë 0x20014000 8000018: deadbeef.fjalë 0xdeadbeef

Cilat copa të vogla mund të marrim nga prodhimi i mësipërm?

Nëse ju kujtohet kur diskutuam dhe krijuam skedarin linker.script.ld, ne deklaruam se këto pajisje ARM kanë RAM duke filluar nga 0x20000000, dhe se memoria FLASH fillon në 0x08000000.

Kështu, ne mund të shohim se me të vërtetë programi është i tillë që të gjithë banojnë në kujtesën FLASH.

Pastaj, më lart, por një hap i mëvonshëm, kur po diskutonim për pjesën "Përshëndetje Botërore", kishte një deklaratë ku ngarkonim një vlerë të drejtpërdrejtë, konstante, të mirëfilltë ("0xDEADBEEF") në një regjistër bazë MCU ("R7").

Deklarata ishte:

LDR R7, = 0xDEADBEEF

Në kodin tonë, ai është i vetmi vend ku ne madje përmendim DEADBEEF. Ne asnje vend tjeter. E megjithatë, nëse shikoni udhëzimet e mësipërme të çmontuara/rindërtuara, etj., Ka më shumë që lidhen me DEADBEEF sesa menduam se bëmë.

Pra, përpiluesi/lidhësi në një farë mënyre vendosi të ndezë përgjithmonë vlerën e DEADBEEF në një adresë FLASH, në vendndodhjen 0x8000018. Dhe pastaj, përpiluesi ndryshoi udhëzimin tonë të mësipërm LDR të jetë:

LDR R7, [PC, #8]

Madje na krijoi një koment. Sa mirë. Dhe na thotë të marrim vlerën aktuale të kundërsulmit të programit (regjistri i PC), të shtojmë 0x8 në atë vlerë, dhe aty është djegur DEADBEEF, dhe ta marrim atë vlerë dhe ta mbushim në R7.

Pra, kjo gjithashtu do të thotë që numëruesi i programit (PC) po tregonte adresën 0x8000010, që është fillimi i main_loop, dhe se vlera DEADBEEF është në dy adresa pas përfundimit të main_loop.

Hapi 15: Së fundi, një vështrim i shkurtër mbi programin që po funksionon

Edhe nëse e lini GDB, thjesht futni përsëri komandën. Ju as nuk duhet t'i jepni ndonjë skedar; ne nuk po ndezim më, thjesht po e ekzekutojmë.

Pasi të keni lidhur përsëri klientin GDB me serverin GDB, në linjën e komandës (gdb):

(gdb) regjistrat e informacionit

Ju duhet të shihni diçka si kjo:

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 0xff800000000000000000000000000000000000

Por pastaj, në kërkesën (gdb), futni:

(gdb) vazhdoni

Dhe shumë shpejt goditi CTRL-C. Kjo duhet të ndalojë programin. Futni përsëri komandën "regjistrat e informacionit".

Këtë herë, duket ndryshe:

(gdb) regjistrat e informacionit

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 rff 0x00 00000 000000000000000000000000000000000000000000000000000000000000000000000000 16777216

Cfare ndodhi? Pikërisht atë që donim. DEADBEEF u ngarkua në R7, dhe R0 është rritur (jashtëzakonisht shpejt). Nëse e përsërisni, do të shihni përsëri R0 me një vlerë tjetër.

Hapi 16: Ne donim të krijonim një grup vetëm për lexim në Flash

Një mënyrë për të krijuar ekuivalentin e një grupi duke përdorur montimin dhe direktivat, është si më poshtë:

.type myarray, %object // emri ose etiketa 'myarray' është përcaktuar si një lloj objekti.

myarray: // ky është fillimi i deklarimit të 'myarray' // (nga çfarë do të përbëhet)..fjala 0x11111111 // anëtari i parë ose vlera e përmbajtur në 'myarray'..fjala 0x22222222 // vlera e dytë (adresat e afërta)..fjala 0x33333333 // dhe kështu me radhë..madhësia myarray,.-myarray // përpiluesi/montuesi tani e di se ku është fundi ose // kufiri i 'myarray'.

Tani që e kemi vendosur në kujtesën FLASH, mund ta përdorim në program. Më poshtë është një pjesë:

LDR R1, myarray // kjo ngarkon të dhënat e përfshira në vendndodhjen e parë të 'myarray'. ' // kjo nuk është ajo që duam.

LDR R1, = myarray // kjo ngarkon vetë vlerën e vendndodhjes (adresa e parë), // jo të dhënat.. // kjo është ajo që duam.

MOV R2, #0 // R2 do të mbajë një numërim për të siguruar që ne të mos largohemi

// fundi i grupit. LDR R3, = myarrsize // R3 do të jetë ekuivalenti i 'myarrsize'.

// R0 do të mbajë të dhënat tona

kryesore_loop:

LDR R0, [R1] // Ngarkoni të dhënat e treguara nga R1 ('myarray') në R0. CMP R2, R3 // A jemi në kufi të grupit? BEQ main_loop // Nëse jemi, kemi mbaruar, kështu që thjesht do të bëjmë lak përgjithmonë.

ADD R2, #1 // Përndryshe, ne mund të vazhdojmë të përsërisim përmes grupit.

SHTO R1, #4 // Shto 4 për të regjistruar R1, në mënyrë që të tregojë saktë tek tjetra

// adresë..

B main_loop // Lak mbrapa.

Video kalon nëpër të gjitha këto, dhe ka një defekt në të. Eshte mire; tregon se është i rëndësishëm kodi i funksionimit dhe debugimit. Ajo tregon një rast klasik të largimit nga fundi i një grupi.

Recommended: