Taula de continguts:

Part 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Passos
Part 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Passos

Vídeo: Part 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Passos

Vídeo: Part 1 ARM Assembly TI RSLK Robotics Learning Curriculum Lab 7 STM32 Nucleo: 16 Passos
Vídeo: Getting Started Demo with CCSv6 and the MSP432 LaunchPad 2019 2024, Juliol
Anonim
Image
Image

El focus d’aquest Instructable és el microcontrolador STM32 Nucleo. La motivació d’això per poder crear un projecte de muntatge a partir d’ossos nus. Això ens ajudarà a aprofundir i entendre el projecte Launchpad MSP432 (el TI-RSLK) que ja ha estat el tema de diversos instructables.

No hi ha molta ajuda en línia per crear un projecte només de muntatge per al MSP432, mitjançant Code Composer Studio. Fins ara acabem de copiar / enganxar d'un projecte de muntatge preexistent. Aquest enfocament ens ha servit.

Ara bé, ara, per al laboratori 7, ens hem trobat amb un problema. O almenys un singlot temporal. El Lab 7 introdueix màquines d’estats finits i el primer que ens trobem és la necessitat de crear i utilitzar un conjunt de valors. Atès que el curs TI utilitza principalment programació C, això no és un problema. Però aquests instructables s’han centrat en el muntatge, no en C.

A més, atès que la matriu té valors de només lectura, seria bo posar-la a la memòria flash, no a la memòria RAM.

Sembla que hi ha molta més ajuda en línia per a projectes de muntatge que utilitzen la MCU STM32, per tant, comencem amb aquest manual instructiu, amb l’objectiu d’utilitzar allò que s’aprèn, per aplicar-lo després al MSP432 i al Code Composer Studio.

En el camí cap a aquest objectiu, també tindrem experiència amb un altre popular microcontrolador.

Pas 1: prova inicial del dispositiu

Prova inicial del dispositiu
Prova inicial del dispositiu
Prova inicial del dispositiu
Prova inicial del dispositiu
Prova inicial del dispositiu
Prova inicial del dispositiu

De nou, per què triar el STM32 Nucleo en particular?

Honestament? Com que buscava bons articles sobre projectes de muntatge de metall nu per a controladors ARM, em vaig trobar amb aquesta sèrie. I també perquè el STM32 sembla ser un MCU popular.

Vaig fer algunes investigacions (hi ha moltes versions per triar (vegeu la imatge superior), però al final es va convertir en el que puc obtenir, ja que anava a utilitzar Amazon (als Estats Units).

Es presenta en un paquet senzill però professional, amb algunes instruccions d’inici. Va ser una mica divertit veure que la demostració cremada al controlador era gairebé exactament el que hem fet anteriorment a Instructables: un LED parpelleja i canvia de velocitat segons premeu un botó.

Sembla que aquesta placa de desenvolupament és molt similar a la MSP432 ja que hi ha 2 LEDs i un polsador d’usuari. El MSP432 té 2 botons d'usuari.

Com podeu veure a les fotos, em va sorprendre una mica que la placa tingui un mini USB i no un micro USB. Va haver de quedar-me sense comprar un cordó.

Una altra bona prova és que quan el connecteu a l'ordinador (estic fent servir un quadre Linux), apareix al gestor de fitxers, com a sistema de fitxers, anomenat "NODE_F303RE". Obertura que revela dos fitxers, un HTML i un text.

Això és tot, però almenys també diu que la connectivitat sembla bastant fàcil.

Ara estem preparats per començar.

Intentaré no repetir cap bona informació de la sèrie d’articles IVONOMICON Bare Metal, sinó augmentar-la.

Pas 2: els elements essencials

El primer que necessitem és un compilador.

I llavors necessitem un depurador:

devchu @ chubox: ~ $ sudo apt-get install gdb-arm-none-eabiLlegint llistes de paquets … Fet Construint l'arbre de dependències Llegint informació d'estat … Fet S'instal·laran els nous paquets següents: gdb-arm-none-eabi 0 actualitzat, 1 recentment instal·lat, 0 per eliminar i 8 no actualitzats. Necessiteu obtenir 2, 722 kB d’arxius. Després d'aquesta operació, s'utilitzaran 7, 738 kB d'espai addicional al disc. Obteniu: 1 https://us.archive.ubuntu.com/ubuntu xenial / universe amd64 gdb-arm-none-eabi amd64 7.10-1ubuntu3 + 9 [2, 722 kB] Obtingut 2, 722 kB en 1s (1, 988 kB / s) Seleccionant el paquet no seleccionat prèviament gdb-arm-none-eabi. (S'està llegint la base de dades … 262428 fitxers i directoris instal·lats actualment.) Preparació per desempaquetar … / gdb-arm-none-eabi_7.10-1ubuntu3 + 9_amd64.deb … Desempaquetament de gdb-arm-none-eabi (7.10-1ubuntu3 + 9) … Processament activadors per a man-db (2.7.5-1) … Configuració de gdb-arm-none-eabi (7.10-1ubuntu3 + 9) …

Pas 3: Aspectes bàsics: Windows

El pas anterior suposava que estem utilitzant Linux. Què passa si fem servir Windows?

Podeu anar al lloc de desenvolupadors de braços i hi ha diverses opcions de baixada disponibles. Estic fent servir una màquina Windows 8.

Durant la instal·lació, vaig optar per instal·lar-lo a la unitat arrel "C: \" en lloc dels fitxers de programa només perquè també estic fent servir cygwin, i va ser més fàcil crear un enllaç des del meu contenidor local a una carpeta C: embolicar el camí als fitxers de programa (amb espais, etc.).

Per tant, el meu entorn i el meu camí cygwin, etc., és així:

C: / cygwin64 / home / bin / arm-none-eabi-gcc, on arm-none-eabi-gcc és un enllaç a C: / GNUToolsArmEmbedded / 7.2018.q2.update / bin / arm-none-eabi- gcc.

Llavors vaig crear una carpeta "dev" a sota de cygwin home, i aquí va ser on vaig col·locar el fitxer core. S i vaig executar l'ordre del compilador. (vegeu més avall les coses del compilador).

Vaig fer exactament el mateix per a gdb (arm-none-eabi-gdb).

Pas 4: quins són els elements essencials

Llavors, què és "gcc-arm-none-eabi"?

El compilador gnu (GCC) compilarà llenguatges de programació (com C) en codi natiu per a la màquina en què s’executa. Per exemple, si compiléssiu algun codi C mitjançant GCC a la vostra màquina Windows, es construiria per executar-la a la màquina Windows. L'executable generat (normalment) no s'executarà al microcontrolador ARM.

Per tant, per tal de construir programes que es descarregaran i es gravaran al microcontrolador ARM (en el nostre cas actual seria el STM32 Nucelo), hem de donar a GCC una altra cosa: la capacitat de "compilar de manera creuada". És a dir, la capacitat de generar un executable, no per al seu sistema (i processador) natius, sinó per al sistema objectiu (el microcontrolador ARM). Aquí és on entra en joc "gcc-arm-none-eabi".

Llavors, què és "gdb-arm-none-eabi"?

Un cop hàgim descarregat i gravat (intermitent) l'executable recentment generat al microcontrolador, probablement voldrem depurar-lo, pas a pas per línia del codi. GDB és el depurador de gnu, i també necessita una manera de fer la seva feina, però orientat a un sistema diferent.

Per tant, gdb-arm-none-eabi és per a GDB, el que és gcc-arm-none-eabi per a GCC.

Una altra instal·lació suggerida del paquet va ser "libnewlib-arm-none-eabi". Què és aquell?

Newlib és una biblioteca C i una biblioteca matemàtica destinada a l’ús en sistemes incrustats. És un conglomerat de diverses parts de la biblioteca, totes sota llicències de programari lliure que les fan fàcilment utilitzables en productes incrustats.

I, finalment, el paquet "libstdc ++ - arm-none-eabi". Això és bastant evident; és una biblioteca C ++ per al compilador creuat; per a microcontroladors ARM incrustats.

Pas 5: el fitxer Linker

El fitxer Linker
El fitxer Linker
El fitxer Linker
El fitxer Linker

Creem un script d'enllaçador.

Una part o bloc clau d’aquest fitxer seria l’ordre MEMORY.

--- de sourceware.org:

La configuració predeterminada de l'enllaçador permet assignar tota la memòria disponible. Podeu substituir-ho mitjançant l'ordre MEMORY. L'ordre MEMORY descriu la ubicació i la mida dels blocs de memòria a l'objectiu. Podeu utilitzar-lo per descriure quines regions de memòria pot utilitzar l'enllaçador i quines regions de memòria ha d'evitar. A continuació, podeu assignar seccions a regions de memòria concretes. L’enllaçador establirà les adreces de seccions en funció de les regions de memòria i avisarà sobre les regions que s’omplen massa. L'enllaçador no barrejarà seccions per ajustar-se a les regions disponibles. Un script d'enllaçador pot contenir molts usos de l'ordre MEMORY, però, tots els blocs de memòria definits es tracten com si estiguessin especificats dins d'una única ordre MEMORY. La sintaxi de MEMORY és:

MEMORYRIA

{nom [(attr)]: ORIGEN = origen, LONGITUD = len …}

L'exemple de l'article:

/ * Definiu el final de la memòria RAM i el límit de la memòria de pila * // * (4KB SRAM a la línia STM32F031x6, 4096 = 0x1000) * / / * (La RAM comença a l’adreça 0x20000000) _estack = 0x20001000;

MEMORYRIA

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

Per tant, hem d’esbrinar quina quantitat de FLASH (per al nostre programa i constants, etc.) i quanta RAM (per fer servir el programa; pila i pila, etc.) per a la nostra placa particular. Això es torna una mica interessant.

La bonica targeta que ve amb Nucleo diu que té memòria flash de 512 Kbytes i SRAM de 80 Kbytes. No obstant això, en connectar-lo a USB, es munta com un sistema de fitxers amb dos fitxers, i tant el gestor de fitxers com GParted indiquen que té més de 540 Kbytes d’espai. (RAM?).

PERUT, en intentar suprimir els dos fitxers mitjançant el gestor de fitxers, desconnectar i tornar a connectar el dispositiu, continua mostrant els dos fitxers. (i el gestor de fitxers sí que va reconèixer alguna cosa perquè hi ha una petita icona de "bloqueig" a cada fitxer.

Anem, doncs, amb les figures de la targeta. Ara prenem l’exemple anterior i el convertim al nostre tauler específic.

És possible que vulgueu utilitzar alguna cosa com aquest convertidor de memòria en línia, per anar del KB general al nombre específic de bytes.

Aleshores és possible que vulgueu utilitzar un convertidor de decimal a hexadecimal en línia.

/ * Definiu el final de la memòria RAM i el límit de la memòria de la pila * /

/ * (4KB SRAM a la línia STM32F031x6, 4096 = 0x1000) * // * l'exemple * /

/ * pas 1: (80KB SRAM al STM32F303RE, 81920 = 0x14000) * // * el nostre tauler * /

/ * pas 2, afegiu la mida hexadecimal a l'adreça inicial inicial (a continuació). * /

/ * (RAM comença a l'adreça 0x20000000) * /

_estack = 0x20001000; / * l'exemple * /

_estack = 0x20014000; / * la nostra junta * /

MEMORYRIA {

FLASH (rx): ORIGEN = 0x08000000, DURADA = 512K

RAM (rxw): ORIGEN = 0x20000000, LONGITUD = 80K

}

Anomenem el fitxer anterior "linker.script.ld".

Pas 6: la taula vectorial

La taula vectorial
La taula vectorial

Ara crearem un petit fitxer de muntatge (amb directrius) per fer una manipulació bàsica d’interrupcions. Seguirem l'exemple de l'article i crearem el fitxer anomenat "core. S".

Una vegada més, aquí teniu l'exemple de contingut del fitxer, però he fet un canvi per al tauler específic:

// Aquestes instruccions defineixen els atributs del nostre xip i

// el llenguatge assemblador que utilitzarem:.syntax unified / * Vegeu a continuació després d'aquesta àrea de codi * / /*.cpu cortex-m0 * / / * comenteu aquesta línia de l'exemple * /.cpu cortex-m4 / * afegiu en canvi el còrtex del nostre tauler. vegeu la imatge superior en aquest pas * / /*.fpu softvfp * / / * comenteu aquesta línia de l'exemple * /.fpu vfpv4 / * afegiu en canvi la del nostre tauler; té una FPU * /.thumb // Ubicacions de memòria global..global vtable.global reset_handler / * * La taula de vectors real. * Només s’inclouen la mida de la memòria RAM i el controlador de “restabliment” *, per simplicitat. * /.type vtable,% object vtable:.word _estack.word reset_handler.size vtable,.-vtable

Hmm.. No hi ha directiva ".align"

Tanmateix, això no és crític. Més informació (potser) més endavant.

.sintaxi unificada

.sintaxi [unificat | dividit]

Aquesta directiva estableix la sintaxi del conjunt d’instruccions tal com es descriu a la secció ARM-Instruction-Set

9.4.2.1 Sintaxi del conjunt d’instruccions Dues sintaxis lleugerament diferents són compatibles amb les instruccions ARM i THUMB. El valor predeterminat, dividit, utilitza l'estil antic on les instruccions ARM i THUMB tenien sintaxis pròpies i separades. La nova sintaxi unificada, que es pot seleccionar mitjançant la directiva.syntax.

.fpu vfpv4

El compilador GCC pot produir binaris amb diverses opcions pel que fa al punt flotant: suau - adequat per executar-se en CPU sense FPU - els càlculs es realitzen en programari mitjançant un compilador generat softfp - adequat per executar-se en CPU amb o sense FPU - utilitzarà una FPU si està present. Per al nostre cas específic (haureu de fer la vostra pròpia investigació), la FPU d'aquesta placa concreta s'ajusta a vfpv4. Potser haureu de jugar amb això. O fins i tot deixar-lo a softfp.

.thumb (contra.arm)

Aquests microcontroladors ARM tenen una combinació de conjunts d’instruccions. Un és ARM, un altre és THUMB. Una diferència són les instruccions de 16 bits contra les instruccions de 32 bits. Per tant, aquesta directiva indica al compilador que tracti les instruccions posteriors com THUMB o ARM.

Prendrem la resta del fitxer tal qual, ja que aquests Instructables encara no s’han endinsat en la programació de muntatges basats en interrupcions.

Pas 7: la versió de muntatge d'un programa "Hello World"

El següent també pot entrar al fitxer "core. S" creat prèviament. Això, de nou, és de l'exemple de l'article.

/ * * El controlador de restabliment. S'ha trucat en restablir. * /.type reset_handler,% function reset_handler: // Estableix el punter de la pila al final de la pila. // El valor "_stack" es defineix al nostre script d'enllaçador. LDR r0, = _stack MOV sp, r0

// Estableix alguns valors ficticis. Quan veiem aquests valors

// al nostre depurador, sabrem que el nostre programa // està carregat al xip i funciona. LDR r7, = 0xDEADBEEF MOVS r0, # 0 main_loop: // Afegeix 1 per registrar 'r0'. AFEGEIX r0, r0, # 1 // Torna enrere. B main_loop.size reset_handler,.-Reset_handler

Per tant, l’objectiu del programa anterior és carregar un patró reconeixible en un registre MCU bàsic (en aquest cas R7) i un valor incremental que comença a zero en un altre registre MCU bàsic (en aquest cas R0). Si passem pel codi d'execució, hauríem de veure l'increment de dades de R0.

Si heu seguit les instruccions relacionades amb el MSP432 i els cursos / laboratoris TI-RSLK, aleshores gairebé tot el programa anterior us hauria de ser familiar.

L'única cosa nova que puc veure és l'ús de "=" quan es carrega "DEADBEEF" per registrar R7. No ho havíem fet servir.

El fitxer "core. S" adjunt aquí conté ara la font completa.

Pas 8: compilació del codi

És hora de fer algunes coses sobre la línia d’ordres. Una cosa real, finalment.

Tot i això, no hi som prou. De nou hem de modificar l'ordre donat a l'article i modificar-lo a la nostra pròpia situació.

Aquí teniu l'exemple de codi:

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

Si anem al lloc gnu.org per a GCC, (en aquest cas la versió 7.3),

x

La -x és per especificar l'idioma. En cas contrari, si no hi ha -x, el compilador intentarà endevinar mitjançant l'extensió de fitxer. (en el nostre cas, *. S).

L'exemple anterior de l'article especifica assembler-with-cpp, però només podríem fer assembler.

c

La -c diu compila però no enllaça.

O0

El valor -O és establir el nivell d'optimització. L'ús de -O0 (oh-zero) diu "reduir el temps de compilació i fer que la depuració produeixi els resultats esperats. Aquest és el valor per defecte".

mcpu = escorça-m0

La -mcpu especifica el nom del processador de destinació. En el nostre cas, seria cortex-m4.

multitud

El botó -mthumb especifica la selecció entre el codi generador que executa els estats ARM i THUMB.

Muralla

El -Wall és, per descomptat, molt comú i conegut. Activa tots els indicadors d'advertència.

Finalment, al final de l’ordre tenim el fitxer d’entrada core. S i el fitxer de sortida core.o.

Aquí teniu la nova línia d’ordres resultant que s’adapta al nostre cas concret.

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

I això es va compilar.

Pas 9: enllaç del programa

Directament de l'exemple de l'article, tenim això:

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

La majoria de les anteriors les heu vist. A continuació es mostren les novetats.

specs = nosys.specs

Aquest és una mica complicat d’explicar.

Té a veure amb "semihosting" i "retargeting", i té a veure amb l'entrada / sortida. També té a veure amb les trucades del sistema i les biblioteques.

Normalment, els sistemes incrustats no proporcionen dispositius d’entrada / sortida estàndard. Això afectaria les trucades del sistema o de la biblioteca (exemple: printf ()).

Semihosting significa que el depurador (vegeu la imatge del pas 11 amb la part del depurador encerclada en vermell) té un canal especial i utilitza el protocol de semihosting, i podeu veure la sortida de printf () a la màquina amfitriona (a través del depurador).

Retargeting, en canvi, significa que aquestes mateixes trucades de sistema o biblioteca signifiquen una altra cosa. Fan una altra cosa, que té sentit per al sistema incrustat. En cert sentit, diguem per a printf (), hi ha una nova implementació, una implementació reorientada d’aquesta funció.

Dit tot això, el --specs = nosys.specs significa que no serem semihosting. Normalment, això vol dir que estem reorientant. Això ens porta a la següent bandera.

nostdlib

L'opció d'enllaçador -nostdlib s'utilitza per enllaçar un programa destinat a executar-se de forma autònoma. -nostdlib implica les opcions individuals -nodefaultlibs i -nostartfiles. A continuació, comentem les dues opcions per separat, però l’ús més típic és només nostdlib per a la compra única. Quan s’enllaça un programa allotjat, les biblioteques de sistemes estàndard, com ara libc, s’uneixen per defecte, donant accés al programa a totes les funcions estàndard (printf, strlen i amics). L'opció d'enllaçador -nodefaultlibs desactiva l'enllaç amb aquestes biblioteques per defecte; les úniques biblioteques enllaçades són exactament les que anomeneu explícitament a l'enllaçador mitjançant el senyalador -l.

lgcc

libgcc.a és una biblioteca estàndard que proporciona subrutines internes per superar les deficiències de determinades màquines. Per exemple, el processador ARM no inclou cap instrucció de divisió. La versió ARM de libgcc.a inclou una funció de divisió i el compilador emet trucades a aquesta funció quan sigui necessari.

T

Aquesta és només una manera d’indicar a l’enllaçador que utilitzi aquest fitxer com a script d’enllaç. En el nostre cas, el nom del fitxer és linker.script.ld.

o main.elf

Finalment, li indiquem a l’enllaçador quin serà el nom del fitxer d’imatge de sortida final que es gravarà / llançarà al nostre dispositiu.

Aquí teniu la nostra versió de la línia d’ordres completa, modificada per a la nostra situació específica:

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

Ens assegurem que el fitxer script i el fitxer core.o estiguin al mateix directori, on executarem la línia d’ordres anterior.

I enllaça sense problemes.

Una revisió

Després executem:

arm-none-eabi-nm main.elf

i aconseguim:

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

Té bona pinta. L'ordre arm-none-eabi-nm és una manera de llistar símbols dins dels fitxers objecte.

Pas 10: prova de connexió amb el STM32 Nucleo-64

Connexió de proves al STM32 Nucleo-64
Connexió de proves al STM32 Nucleo-64
Connexió de proves al STM32 Nucleo-64
Connexió de proves al STM32 Nucleo-64

La primera missió, si decidiu acceptar-la, és aconseguir que el vostre sistema vegi la vostra placa de desenvolupament.

Ús de Windows

Per a Windows, vaig decidir instal·lar TrueSTUDIO des d’Atollic (versió gratuïta). Va ser una instal·lació indolora i va instal·lar automàticament el controlador per poder utilitzar st-link per provar la connexió. Un cop vaig instal·lar TrueSTUDIO i el gestor de dispositius va veure el dispositiu, vaig descarregar les eines texan / stlink suggerides per l'article de Bare Metal que hem estat seguint. Vaig tornar a col·locar la carpeta directament a sota de "C: \" i vaig tornar a crear alguns enllaços des de la safata de casa local de cygwin a les ordres.

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

Com a prova inicial per veure si realment podem comunicar-nos amb el dispositiu, vaig executar:

st-info --probe

I vaig tornar:

S'han trobat 1 programadors stlink

Ara sabem que podem parlar / consultar el nostre tauler de desenvolupament.

Utilitzant Linux

Per a Linux, realment no necessiteu un controlador. Però, per a Debian, haureu de construir les primeres eines des del codi font.

git clone

Assegureu-vos que teniu instal·lat libusb-1.0-0-dev.

llista d'aptes | grep -E "* libusb. * dev *"

Hauríeu de veure:

libusb-1.0-0-dev / xenial, ara 2: 1.0.20-1 amd64 [instal·lat]

o alguna cosa així.

Per instal·lar-lo:

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

Tingueu en compte que l’anterior no és el mateix que:

sudo apt-get install libusb-dev

El programari libusb que falta correctament pot fer que cmake tingui problemes.

Error de CMake: les següents variables s’utilitzen en aquest projecte, però s’estableixen a NOTFOUND. Establiu-les o assegureu-vos que estiguin configurades i provades correctament als fitxers CMake: LIBUSB_INCLUDE_DIR (ADVANCED)

Canvieu al directori arrel del projecte (… bla / bla / stlink). Feu un "llançament".

Després d'aquestes compilacions, les eines haurien d'estar a ".. / build / Release".

A continuació, podeu executar "st-info --probe". Aquí teniu la sortida amb el nucli connectat, doncs no.

devchu @ chubox: ~ / Development / stlink $./build/Release/st-info --probeFound 1 stlink programmers serial: 303636414646353034393535363537 openocd: "\ x30 / x36 / x36 / x41 / x46 / x46 / x35 / x30 / x34 / x39 / x35 / x35 / x36 / x35 / x37 "flash: 524288 (mida de pàgina: 2048) sram: 65536 chipid: 0x0446 descr: dispositiu d'alta densitat F303 devchu @ chubox: ~ / Development / stlink $./build/Release/st- info --probe S'han trobat 0 programadors stlink devchu @ chubox: ~ / Development / stlink $

Pas 11: fem servir GDB amb Linux

Utilitzem GDB amb Linux
Utilitzem GDB amb Linux
Utilitzem GDB amb Linux
Utilitzem GDB amb Linux

Si heu provat tot això i heu arribat fins aquí - fantàstic! Excel · lent. Ara divertim-nos una mica.

Quan compreu aquestes plaques de desenvolupament ARM, ja siguin el MSP432 Launchpad de Texas Instruments o aquest que comentem ara, el Nucleo-F303 (STM32 Nucleo-64), normalment arriben ja amb un programa en execució, normalment algun programa parpellejant que també inclou prémer un interruptor per canviar la velocitat amb què parpellegen els LED.

Abans de ser tan ràpids en sobreescriure això, anem a veure què hi ha per veure i fer.

Amb Linux, obriu un terminal, canvieu de directori el projecte stlink git que acabem de construir i cerqueu l'eina st-util.

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

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

Executeu aquesta eina. Com que ja hem provat prèviament la nostra connexió amb st-info --probe, hauríem d'obtenir una sortida així:

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

st-util 1.4.0-50-g7fafee2 2018-10-20T18: 33: 23 INFO common.c: S'estan carregant els paràmetres del dispositiu…. 2018-10-20T18: 33: 23 INFO common.c: El dispositiu connectat és: dispositiu d'alta densitat F303, identificador 0x10036446 2018-10-20T18: 33: 23 INFO common.c: mida SRAM: 0x10000 bytes (64 KiB), Flash: 0x80000 bytes (512 KiB) en pàgines de 2048 bytes 2018-10-20T18: 33: 23 INFO gdb-server.c: L'identificador del xip és 00000446, l'identificador principal és 2ba01477. 2018-10-20T18: 33: 23 INFO gdb-server.c: escoltant a *: 4242 …

Aquest és el servidor GDB que s’executa ara i veu la nostra placa de desenvolupament i, el que és més important, està escoltant al port 4242 (el port per defecte).

Ara estem preparats per activar el client GDB.

A Linux, obriu un altre terminal, introduïu això:

arm-none-eabi-gdb -tui

Això és exactament el mateix que executar gdb estrictament en línia de comandes, però en lloc d'això produeix un terminal basat en text (suposo que utilitza curses).

Tenim el client GDB i el servidor GDB en funcionament. Tot i això, el client no està connectat al servidor. De moment no sap res del nostre nucli (o tauler que trieu). Ho hem de dir. Al terminal, la vostra sol·licitud hauria de ser ara "(gdb)". Introduïu:

objectiu d’ajuda

Us donarà una llista. Tingueu en compte que el que volem és objectiu Extended-Remote: utilitzeu un ordinador remot mitjançant una línia serial.

Però també li hem de donar la ubicació. Per tant, a l’indicatiu (gdb), introduïu:

(gdb) objectiu localhost remot estès: 4242

Haureu de tornar una resposta semblant a aquesta:

(gdb) objectiu localhost remot estès: 4242

Depuració remota mitjançant localhost: 4242 0x080028e4 a ?? ()

Mentrestant, al terminal que executa el gdbserver st-util, hem obtingut això:

2018-10-20T18: 42: 30 INFO gdb-server.c: S'han trobat registres de punts de ruptura de 6 hw

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

Pas 12: repetim, amb Windows i Flash el nostre programa

Repetim, amb Windows i Flash el nostre programa
Repetim, amb Windows i Flash el nostre programa
Repetim, amb Windows i Flash el nostre programa
Repetim, amb Windows i Flash el nostre programa
Repetim, amb Windows i Flash el nostre programa
Repetim, amb Windows i Flash el nostre programa

Els passos per executar st-util gdbserver i el client arm-none-eabi-gdb són essencialment els mateixos que vam fer durant el pas anterior. Obriu dos terminals (cygwin, DOS cmd o Windows Powershell), trobeu la ubicació del st-util, executeu-lo. A l’altre terminal, executeu el client arm-none-eabi-gdb. L'única diferència és que és probable que el mode -tui (visualització de text basada en terminal) no s'admeti.

Si l'anterior funcionava a Windows, probablement haureu d'aturar-vos (només el client). En aquest punt, d'alguna manera haureu d'executar el client GDB on es troba el fitxer de compilació ("core.out") o afegir tot el camí d'accés a aquest fitxer com a argument al client GDB.

Vaig simplificar la meva vida utilitzant cygwin i creant enllaços des del meu directori local $ HOME // bin fins on resideixen ambdues eines.

D'acord, hem compilat i enllaçat igual que abans, i ja tenim el fitxer main.elf llest per ser flash.

Tenim st-util funcionant en una finestra. Reiniciem el client GDB, aquesta vegada fem:

arm-none-eabi-gdb main.elf

Deixem que s’engegui, esperem l’indicatiu (gdb), fem la nostra mateixa ordre de connexió al servidor GDB (st-util) i estem preparats per fer flash l’executable. És molt anti-climàtic:

(gdb) càrrega

S’executa amb els terminals cygwin, hi ha un problema conegut, ja que alguna vegada les ordres de la consola no es publiquen. Per tant, en el nostre cas, la finestra que executa el servidor era completament silenciosa. El que executa el client, on hem executat la càrrega, emet aquest:

Secció de càrrega.text, mida 0x1c lma 0x8000000 Adreça inicial 0x8000000, mida de càrrega 28 Velocitat de transferència: 1 KB / seg, 28 bytes / escriptura.

Pas 13: Intermitent amb Linux: més recompensa: D

Intermitent amb Linux: més recompensa: D
Intermitent amb Linux: més recompensa: D

Pas 14: busseig una mica més profund

Si heu arribat fins aquí, excel·lent. Posem-nos en marxa.

Per què no busqueu l'interior del fitxer main.elf, l'executable? Executeu el següent:

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

Hauríeu de veure una sortida així:

main.elf: format de fitxer elf32-littlearm

Desmuntatge de la secció.text:

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 moviments r0, # 0

08000010:

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

Quines petites llavors podem obtenir de la sortida anterior?

Si recordeu quan discutíem i creavem el fitxer linker.script.ld, afirmàvem que aquests dispositius ARM tenen memòria RAM a partir de 0x20000000 i que la memòria FLASH comença a 0x08000000.

Per tant, podem veure que, de fet, el programa és tal que resideix a la memòria FLASH.

A continuació, més amunt, però un pas posterior, quan discutíem la porció "Hello World", hi havia una sentència on carregàvem un valor literal immediat i constant ("0xDEADBEEF") en un registre bàsic de la MCU ("R7").

La declaració era:

LDR R7, = 0xDEADBEEF

Al nostre codi, aquest és l’únic lloc on fins i tot esmentem DEADBEEF. No on més. Tot i això, si mireu les instruccions desmuntades / reconstruïdes anteriors, etc., hi ha més coses relacionades amb DEADBEEF del que pensàvem que vam fer.

Per tant, el compilador / enllaçador d’alguna manera va decidir destellar permanentment el valor de DEADBEEF en una adreça FLASH, a la ubicació 0x8000018. I després, el compilador va canviar la nostra instrucció LDR anterior per ser:

LDR R7, [PC, # 8]

Fins i tot ens va generar un comentari. Que bé. I ens diu que prenem el valor actual del comptador del programa (el registre de PC), afegim 0x8 a aquest valor, i és aquí on s’ha cremat DEADBEEF, obtenim aquest valor i ompliu-lo a R7.

Això també significa que el comptador de programes (PC) apuntava a l'adreça 0x8000010, que és l'inici del main_loop, i que el valor DEADBEEF es troba a dues adreces després del final del main_loop.

Pas 15: Finalment, una breu mirada al programa en execució

Fins i tot si sortiu de GDB, torneu a introduir l'ordre. Ni tan sols li heu de donar cap fitxer; ja no parpellegem, només l’executem.

Un cop hàgiu tornat a connectar el client GDB al servidor GDB, a l'indicador d'ordres (gdb):

(gdb) registres d'informació

Hauríeu de veure alguna cosa així:

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 0xffffffffff 429496720000

Però després, a l’indicatiu (gdb), introduïu:

(gdb) continua

I molt ràpidament va tocar CTRL-C. Això hauria d’aturar el programa. Torneu a introduir l'ordre "registres d'informació".

Aquesta vegada, sembla diferent:

(gdb) registres d'informació

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 r12 0x0 0000000 00000 16777216

Què va passar? Exactament el que volíem. DEADBEEF s'ha carregat a R7 i R0 ha estat (extremadament ràpid) incrementant-se. Si repetiu, veureu R0 de nou amb un altre valor.

Pas 16: volíem crear una matriu de només lectura en Flash

Una manera de crear l’equivalent a una matriu mitjançant assemblees i directives és la següent:

.type myarray,% object // el nom o etiqueta 'myarray' es defineix com un tipus d'objecte.

myarray: // aquest és l'inici de la declaració de 'myarray' // (en què consistirà)..word 0x11111111 // el primer membre o valor contingut a 'myarray'..word 0x22222222 // el segon valor (adreces contigües)..word 0x33333333 // i així successivament..size myarray,.-myarray // el compilador / assemblador ara sap on és el final o // límit de 'myarray'.

Ara que l’hem configurat a la memòria FLASH, el podem utilitzar al programa. A continuació es mostra una porció:

LDR R1, myarray // això carrega les dades contingudes a la primera ubicació de "myarray". " // això no és el que volem.

LDR R1, = myarray // carrega el valor de la ubicació (la primera adreça), // no les dades.. // Això és el que volem.

MOV R2, # 0 // R2 farà un recompte per assegurar-nos que no marxem

// final de la matriu. LDR R3, = myarrsize // R3 serà l'equivalent a "myarrsize".

// R0 mantindrà les nostres dades

main_loop:

LDR R0, [R1] // Carrega les dades apuntades per R1 ('myarray') a R0. CMP R2, R3 // Estem al límit de la matriu? BEQ main_loop // Si ho fem, ja hem acabat, així que farem un bucle per sempre.

AFEGEIX R2, # 1 // En cas contrari, podem continuar iterant a través de la matriu.

AFEGEIX R1, # 4 // Afegiu 4 per registrar R1, de manera que apunti correctament al següent

// adreça..

B main_loop // Bucle enrere.

El vídeo repassa tot això i hi ha un error. És bo; mostra que és important executar i depurar el codi. Mostra un cas clàssic de sortir del final d’una matriu.

Recomanat: