Comment utiliser le GDB (Gnu Debugger) et OpenOCD pour microcontrôleur de débogage - depuis le terminal?

La norme (à faible coût) façon de programmer les microcontrôleurs ARM est à l'aide d'Eclipse avec un complexe de la chaîne d'branché sur elle. Eclipse a certainement ses mérites, mais j'aimerais me sentir indépendante de cette IDE. J'aimerais découvrir ce qui se passe derrière les coulisses quand je build (compilation - lien - flash) mon logiciel, et quand je lance une session de débogage. Pour obtenir une telle compréhension plus profonde, ce serait merveilleux pour exécuter l'ensemble de la procédure depuis la ligne de commande.

Note: je suis sous 64 bits de Windows 10. Mais la plupart des choses expliqué ici s'applique également sur les systèmes Linux. S'il vous plaît ouvrir toutes les bornes de commande avec les droits admin. Cela peut vous faire économiser beaucoup de problèmes.

1. La construction du logiciel

La première mission est accomplie. Je suis maintenant en mesure de compiler et lier mon logiciel dans un fichier binaire .bin et un .elf l'image par le biais de la ligne de commande. La clé du succès est de trouver où Eclipse met son faire-fichiers pour un projet spécifique. Une fois que vous savez où ils sont, tout ce que vous avez à faire est d'ouvrir une fenêtre de terminal et tapez la GNU make commande.

Comment utiliser le GDB (Gnu Debugger) et OpenOCD pour microcontrôleur de débogage - depuis le terminal?

Vous n'avez pas besoin de l'Éclipse de plus pour que! Surtout si vous pouvez lire (et comprendre) le makefile et de l'adapter à vos besoins lors de votre projet avance.

Noter que j'ai trouvé les outils GNU (compilateur, éditeur de liens, faire de l'utilitaire, GDB, ...) dans le dossier suivant, après l'installation de SW4STM32 (System Workbench for STM32):

C:\Ac6\SystemWorkbench\plugins\fr.ac6.mcu.externaltools.arm-none.win32_1.7.0.201602121829\tools\compiler\

Ensuite, j'ai fait un nouveau dossier sur mon disque dur et copié tous ces outils GNU en elle:

C:\Apps\AC6GCC
           |-> arm-none-eabi
           |-> bin
           '-> lib

Et j'ai ajouter ces entrées à la "variable d'Environnement Path":

 - C:\Apps\AC6GCC\bin
 - C:\Apps\AC6GCC\lib\gcc\arm-none-eabi.2.1

Huray, maintenant j'ai tous les outils GNU et en cours d'exécution sur mon système! J'ai mis la suivante build.bat fichier dans le même dossier que le makefile:

@echo off
echo.
echo."--------------------------------"
echo."-           BUILD              -"
echo."--------------------------------"
echo.

make -j8 -f makefile all

echo.

L'exécution de cette chauve-souris-fichier devrait faire l'affaire! Si tout se passe bien, vous obtenez l'un des .bin et un .elf fichier binaire comme le résultat de la compilation.

2. De clignoter et le débogage du firmware

Naturelles étape suivante est de flasher le firmware de la puce et de commencer une session de débogage. Dans Eclipse, il suffit d'un "clic sur un bouton" - au moins si l'Éclipse est correctement configuré pour votre microcontrôleur. Mais ce qui se passe derrière les coulisses?
J'ai lu (en partie) la Thèse de Maîtrise de Dominic Rath - le développeur de OpenOCD. Vous pouvez le trouver ici: http://openocd.net/ . C'est ce que j'ai appris:

  • Eclipse lance le OpenOCD logiciel lorsque vous cliquez sur le 'debug' icône. Eclipse fournit également des fichiers de configuration pour OpenOCD - tels que OpenOCD sait comment se connecter à votre microcontrôleur. "Comment se connecter" n'est pas une chose banale. OpenOCD besoins pour trouver le bon pilote USB pour se connecter à l'adaptateur JTAG (par exemple STLink). À la fois l'adaptateur JTAG et son pilote USB sont généralement fournis par votre fabricant de la puce (par exemple STMicroelectronics). Eclipse remet également un fichier de configuration pour OpenOCD qui décrit les spécifications du microcontrôleur. Une fois OpenOCD sait à propos de toutes ces choses, il peut raliser un JTAG connexion à l'appareil cible.

  • OpenOCD commence deux serveurs. Le premier est un serveur Telnet sur le port TCP 4444. Elle donne accès à la OpenOCD CLI (Interface de Ligne de Commande). Un client Telnet peuvent se connecter et envoyer des commandes à OpenOCD. Ces commandes peuvent être un simple "stop", "exécuter", "réglage du point d'arrêt', ...

  • Ces commandes peuvent être suffisantes pour le débogage de votre microcontrôleur, mais beaucoup de gens étaient déjà familiarisés avec le Débogueur Gnu (GDB). C'est pourquoi OpenOCD commence aussi un GDB serveur sur TCP port 3333. Un GDB client peut se connecter à ce port, et démarrer le débogage du microcontrôleur!

  • Le Débogueur Gnu est une ligne de commande du logiciel. Beaucoup de gens préfèrent une interface visuelle. C'est exactement ce que Eclipse n'. Eclipse lance un GDB client qui se connecte à OpenOCD - mais c'est tout caché à l'utilisateur. Eclipse fournit une interface graphique qui interagit avec le GDB client derrière les coulisses.

J'ai fait un chiffre d'expliquer toutes ces choses:

Comment utiliser le GDB (Gnu Debugger) et OpenOCD pour microcontrôleur de débogage - depuis le terminal?

>> Démarrage OpenOCD

J'ai réussi à démarrer OpenOCD à partir de la ligne de commande. Je vais vous expliquer comment.

  1. Assurez-vous d'abord que votre STLink-V2 JTAG programmeur est correctement installé. Vous pouvez tester l'installation avec le "STLink outil Utilitaire" de STMicroelectronics. Il a une belle interface graphique, et il vous suffit de cliquez sur le bouton connecter.
    Comment utiliser le GDB (Gnu Debugger) et OpenOCD pour microcontrôleur de débogage - depuis le terminal?
  2. La suite, téléchargez le OpenOCD logiciel exécutable à partir de ce site web: http://gnutoolchains.com/arm-eabi/openocd/ . De l'installer et de le mettre dans un dossier sur votre disque dur, comme "C:\Apps\".
  3. Ouvrir un terminal de commande, et de commencer à OpenOCD. Vous aurez besoin de donner OpenOCD quelques fichiers de configuration, telle qu'elle sait où regarder pour votre microcontrôleur. Généralement, vous avez besoin de donner un fichier de configuration qui décrit le JTAG programmeur, et un fichier de configuration qui définit votre microcontrôleur. Transmettre ces fichiers à OpenOCD avec le -f argument dans la ligne de commande. Vous devrez également fournir OpenOCD l'accès à la scripts dossier, en le passant avec la -s argument. C'est de cette façon je commence OpenOCD sur mon ordinateur avec la ligne de commande:

    > "C:\Apps\OpenOCD-0.9.0-Win32\bin\openocd" -f "C:\Apps\OpenOCD-0.9.0-Win32\share\openocd\scripts\interface\stlink-v2.cfg" -f "C:\Apps\OpenOCD-0.9.0-Win32\share\openocd\scripts\target\stm32f7x.cfg" -s "C:\Apps\OpenOCD-0.9.0-Win32\share\openocd\scripts"
    
  4. Si vous avez commencé à OpenOCD correctement (avec les bons arguments), il va de démarrage avec le message suivant:

    Open On-Chip Debugger 0.9.0 (2015-08-15-12:41)
    Licensed under GNU GPL v2
    For bug reports, read
            http://openocd.org/doc/doxygen/bugs.html
    Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
    Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
    adapter speed: 2000 kHz
    adapter_nsrst_delay: 100
    srst_only separate srst_nogate srst_open_drain connect_deassert_srst
    Info : Unable to match requested speed 2000 kHz, using 1800 kHz
    Info : Unable to match requested speed 2000 kHz, using 1800 kHz
    Info : clock speed 1800 kHz
    Info : STLINK v2 JTAG v24 API v2 SWIM v4 VID 0x0483 PID 0x3748
    Info : using stlink api v2
    Info : Target voltage: 3.231496
    Info : stm32f7x.cpu: hardware has 8 breakpoints, 4 watchpoints
    Info : accepting 'gdb' connection on tcp/3333
    Info : flash size probed value 1024
    
  5. Remarquez que votre fenêtre de terminal est maintenant bloqué. Vous ne pouvez plus vous tapez des commandes. Mais c'est normal. OpenOCD est en cours d'exécution en arrière-plan, et il bloque le terminal. Maintenant, vous avez deux options pour interagir avec OpenOCD: vous démarrez une session Telnet dans un autre terminal, et que vous vous connectez sur le port TCP localhost:4444, de sorte que vous pouvez donner des ordres à OpenOCD et recevoir de la rétroaction. Ou vous démarrez un GDB client de session, et le connecter au port TCP localhost:3333.

>> le Démarrage d'une session Telnet pour interagir avec OpenOCD

C'est la façon dont vous démarrez une session Telnet pour interagir avec le fonctionnement OpenOCD programme:

> dism /online /Enable-Feature /FeatureName:TelnetClient

> telnet 127.0.0.1 4444

Si elle fonctionne bien, vous obtiendrez le message suivant sur votre terminal:

Open On-Chip Debugger
> ..

Et vous êtes prêt à envoyer commmands à OpenOCD! Mais je vais passer maintenant à la session GDB, car c'est le moyen le plus pratique pour interagir avec OpenOCD.

>> le Démarrage d'une GDB de session d'un client d'interagir avec OpenOCD

Encore ouvert une autre fenêtre de terminal et tapez la commande suivante:

> "C:\Apps\AC6GCC\bin\arm-none-eabi-gdb.exe"

Cette commande démarre simplement le arm-none-eabi-gdb.exe GDB client. Si tout va bien, GDB démarre avec le message suivant:

    GNU gdb (GNU Tools for ARM Embedded Processors) 7.10.1.20151217-cvs
    Copyright (C) 2015 Free Software Foundation, Inc.
    License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
    This is free software: you are free to change and redistribute it.
    There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
    and "show warranty" for details.
    This GDB was configured as "--host=i686-w64-mingw32 --target=arm-none-eabi".
    Type "show configuration" for configuration details.
    For bug reporting instructions, please see:
    <http://www.gnu.org/software/gdb/bugs/>.
    Find the GDB manual and other documentation resources online at:
    <http://www.gnu.org/software/gdb/documentation/>.
    For help, type "help".
    Type "apropos word" to search for commands related to "word".
    (gdb)..

Maintenant, connectez cette GDB client vers le serveur GDB à l'intérieur de OpenOCD:

    (gdb) target remote localhost:3333

Vous êtes maintenant connecté à OpenOCD! Bon à savoir: si vous souhaitez utiliser un natif OpenOCD de commande (tout comme vous le feriez dans une session Telnet), il suffit de faire précéder la commande avec le mot-clé monitor. De cette façon, le GDB serveur à l'intérieur de OpenOCD ne sera pas traiter la commande lui-même, mais de la transmettre à la maternelle OpenOCD démon.

Donc, maintenant, il est temps de réinitialiser la puce, de les effacer et de les arrêter:

    (gdb) monitor reset halt
       target state: halted
       target halted due to debug-request, current mode: Thread
       xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
    (gdb) monitor halt

    (gdb) monitor flash erase_address 0x08000000 0x00100000
       erased address 0x08000000 (length 1048576) in 8.899024s (115.069 KiB/s)
    (gdb) monitor reset halt
       target state: halted
       target halted due to debug-request, current mode: Thread
       xPSR: 0x01000000 pc: 0xfffffffe msp: 0xfffffffc
    (gdb) monitor halt

La puce est maintenant prêt à obtenir quelques instructions que nous. Nous allons d'abord dire la puce que son flash sections 0 à 7 (c'est tout le flash sections dans mon 1 mo de chip) ne doivent pas être protégés:

    (gdb) monitor flash protect 0 0 7 off

    (gdb) monitor flash info 0
       #0 : stm32f7x at 0x08000000, size 0x00100000, buswidth 0, chipwidth 0
            #  0: 0x00000000 (0x8000 32kB) not protected
            #  1: 0x00008000 (0x8000 32kB) not protected
            #  2: 0x00010000 (0x8000 32kB) not protected
            #  3: 0x00018000 (0x8000 32kB) not protected
            #  4: 0x00020000 (0x20000 128kB) not protected
            #  5: 0x00040000 (0x40000 256kB) not protected
            #  6: 0x00080000 (0x40000 256kB) not protected
            #  7: 0x000c0000 (0x40000 256kB) not protected

Ensuite, j'ai arrêter la puce à nouveau. Juste pour être sûr..

    (gdb) monitor halt

Enfin j'ai la main sur le binaire .elf fichier GDB:

    (gdb) file C:\\..\\myProgram.elf
       A program is being debugged already.
       Are you sure you want to change the file? (y or n) y
       Reading symbols from C:\..\myProgram.elf ...done.

C'est maintenant le moment de vérité. Je demande GDB pour charger ce fichier binaire dans la puce. Je croise les doigts:

    (gdb) load
       Loading section .isr_vector, size 0x1c8 lma 0x8000000
       Loading section .text, size 0x39e0 lma 0x80001c8
       Loading section .rodata, size 0x34 lma 0x8003ba8
       Loading section .init_array, size 0x4 lma 0x8003bdc
       Loading section .fini_array, size 0x4 lma 0x8003be0
       Loading section .data, size 0x38 lma 0x8003be4
       Error finishing flash operation

Malheureusement, il n'a pas réussi. Je reçois le message suivant dans OpenOCD:

    Error: error waiting for target flash write algorithm
    Error: error writing to flash at address 0x08000000 at offset 0x00000000

EDIT : problème Matériel fixe.

Apparemment c'était un problème matériel. Je n'avais jamais pensé que ma puce serait défaut, depuis le chargement de la binaire sur la puce avec le STLink Utilitaire outil a fonctionné sans problème. Seulement OpenOCD a été se plaindre et en donnant des erreurs. C'est donc naturellement que j'ai blâmé OpenOCD - et non la puce elle-même. Voir ma réponse ci-dessous pour plus de détails.


EDIT : Alternative élégante façon de flasher la puce à l'aide d'un makefile!

Que la question suis fixé, je vais maintenant l'accent sur une autre façon d'exécuter le flash et le débogage de la puce. Je crois que c'est vraiment intéressant pour la communauté!

Vous avez peut-être remarqué que j'ai utilisé Windows cmd commandes à exécuter toutes les étapes nécessaires. Cela peut être automatisé dans un fichier de commandes. Mais il y a une façon plus élégante: pour tout automatiser dans un makefile!
M./Mss. Othane a suggéré le makefile suivant pour son Cortex-M? la puce. Je suppose que la procédure pour un Cortex-M7 puce est très similaire:

            #################################################
            #        MAKEFILE FOR BUILDING THE BINARY       #
            #        AND EVEN FLASHING THE CHIP!            #
            # Author: Othane                                #
            #################################################

    # setup compiler and flags for stm32f373 build 
    SELF_DIR := $(dir $(lastword $(MAKEFILE_LIST))) 


    CROSS_COMPILE ?= arm-none-eabi- 
    export CC = $(CROSS_COMPILE)gcc 
    export AS = $(CROSS_COMPILE)gcc -x assembler-with-cpp 
    export AR = $(CROSS_COMPILE)ar 
    export LD = $(CROSS_COMPILE)ld 
    export OD   = $(CROSS_COMPILE)objdump 
    export BIN  = $(CROSS_COMPILE)objcopy -O ihex 
    export SIZE = $(CROSS_COMPILE)size 
    export GDB = $(CROSS_COMPILE)gdb 


    MCU = cortex-m4 
    FPU = -mfloat-abi=hard -mfpu=fpv4-sp-d16 -D__FPU_USED=1 -D__FPU_PRESENT=1 -DARM_MATH_CM4 
    DEFS = -DUSE_STDPERIPH_DRIVER -DSTM32F37X -DRUN_FROM_FLASH=1 -DHSE_VALUE=8000000 
    OPT ?= -O0  
    MCFLAGS = -mthumb -mcpu=$(MCU) $(FPU) 


    export ASFLAGS  = $(MCFLAGS) $(OPT) -g -gdwarf-2 $(ADEFS) 
    CPFLAGS += $(MCFLAGS) $(OPT) -gdwarf-2 -Wall -Wno-attributes -fverbose-asm  
    CPFLAGS += -ffunction-sections -fdata-sections $(DEFS) 
    export CPFLAGS 
    export CFLAGS += $(CPFLAGS) 


    export LDFLAGS  = $(MCFLAGS) -nostartfiles -Wl,--cref,--gc-sections,--no-warn-mismatch $(LIBDIR) 


    HINCDIR += ./STM32F37x_DSP_StdPeriph_Lib_V1.0.0/Libraries/CMSIS/Include/\ 
        ./STM32F37x_DSP_StdPeriph_Lib_V1.0.0/Libraries/CMSIS/Device/ST/STM32F37x/Include/\ 
        ./STM32F37x_DSP_StdPeriph_Lib_V1.0.0/Libraries/STM32F37x_StdPeriph_Driver/inc/\ 
        ./
    export INCDIR = $(patsubst %,$(SELF_DIR)%,$(HINCDIR)) 




    # openocd variables and targets 
    OPENOCD_PATH ?= /usr/local/share/openocd/
    export OPENOCD_BIN = openocd 
    export OPENOCD_INTERFACE = $(OPENOCD_PATH)/scripts/interface/stlink-v2.cfg 
    export OPENOCD_TARGET = $(OPENOCD_PATH)/scripts/target/stm32f3x_stlink.cfg 


    OPENOCD_FLASH_CMDS = '' 
    OPENOCD_FLASH_CMDS += -c 'reset halt' 
    OPENOCD_FLASH_CMDS += -c 'sleep 10'  
    OPENOCD_FLASH_CMDS += -c 'stm32f1x unlock 0' 
    OPENOCD_FLASH_CMDS += -c 'flash write_image erase $(PRJ_FULL) 0 ihex' 
    OPENOCD_FLASH_CMDS += -c shutdown 
    export OPENOCD_FLASH_CMDS 


    OPENOCD_ERASE_CMDS = '' 
    OPENOCD_ERASE_CMDS += -c 'reset halt' 
    OPENOCD_ERASE_CMDS += -c 'sleep 10'  
    OPENOCD_ERASE_CMDS += -c 'sleep 10'  
    OPENOCD_ERASE_CMDS += -c 'stm32f1x mass_erase 0' 
    OPENOCD_ERASE_CMDS += -c shutdown 
    export OPENOCD_ERASE_CMDS 


    OPENOCD_RUN_CMDS = '' 
    OPENOCD_RUN_CMDS += -c 'reset halt' 
    OPENOCD_RUN_CMDS += -c 'sleep 10' 
    OPENOCD_RUN_CMDS += -c 'reset run' 
    OPENOCD_RUN_CMDS += -c 'sleep 10'  
    OPENOCD_RUN_CMDS += -c shutdown 
    export OPENOCD_RUN_CMDS 


    OPENOCD_DEBUG_CMDS = '' 
    OPENOCD_DEBUG_CMDS += -c 'halt' 
    OPENOCD_DEBUG_CMDS += -c 'sleep 10' 


    .flash: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_FLASH_CMDS) 


    .erase: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_ERASE_CMDS) 


    .run: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_RUN_CMDS) 


    .debug: 
        $(OPENOCD_BIN) -f $(OPENOCD_INTERFACE) -f $(OPENOCD_TARGET) -c init $(OPENOCD_DEBUG_CMDS) 

Cher Monsieur/Mss. Othane, pourriez-vous expliquer comment utiliser ce makefile pour les étapes suivantes:

  • Compiler le binaire à partir du code source
  • Flash de la puce

Je sais que quelques notions de base sur les fichiers makefile, mais votre makefile est vraiment très profond. Vous semblez utiliser certaines fonctionnalités de l'utilitaire make de GNU. Veuillez nous donner plus d'explication, et je vais vous accorder le bonus 😉

------------------------------

  • Le makefile montré est vraiment pas trop ... en fait j'ai 1 de ces fichiers par l'architecture, il exporte un tas de variable comme CC CFLAGS et à la baisse des makefiles qui comprennent cela, ils peuvent ensuite compiler le code de façon générique à l'aide de ces drapeaux ... En termes de programmation, nous ajoutons une certains .effacer, .flash, etc ... commandes de sorte à faire un effacement complet du programme, etc vous pouvez l'exécuter: faire .effacer && faire .flash && faire .debug ... alors vous pouvez vous connecter à l'aide de gdb, ou en faire .exécution de l'exécuter sans débogage
  • Waw, merci beaucoup pour votre aide. Pourrais-je demander à un de plus favorable? Pas seulement pour moi, mais pour tous ceux qui pourraient bénéficier de votre merveilleuse réponse. Pourriez-vous copier ces fichiers makefile qui s'appliquent à la Cortex-M7/M4 (donc le "parent" et "l'enfant" makefiles) dans votre réponse? Et les commandes à utiliser, trop? Ce serait vraiment génial! La communauté vous en remercie 🙂 (Une référence à github est bon, mais il est préférable d'avoir tout visible sur StackOverflow. Ce qui le rend plus accessible, et les gens peuvent laisser des commentaires, poser des questions, ...)
  • Salut @othane , j'ai déjà reçu le bonus pour vous. Vous le méritez vraiment! Veuillez considérer l'idée de mettre votre makefiles ici sur StackOverflow. Je serais vraiment très heureux 🙂
  • Cheers mate .. désolé, j'ai raté ce message, je ne pense pas que c'est un bon endroit pour publier des fichiers mais... Ils doivent tous être disponible sur GitHub qui me semble plus approprié que celui de débordement de pile
InformationsquelleAutor K.Mulier | 2016-06-25