utilizar tutorial test para opciones español depurador gdb gnu jtag openocd

tutorial - gdb windows



¿Cómo usar el GDB(Gnu Debugger) y OpenOCD para la depuración del microcontrolador-desde el terminal? (5)

A primera vista, la distribución en gnutoolchains.com debería ser lo suficientemente buena. Hay una serie de scripts de compilación para elaborar tu propia versión. Tengo el mío para incluir el ARM7TDMI. Funciona bien en Linux y FreeBSD pero MinGW falló la última vez que lo probé :-(

Con respecto a OpenOCD, recomendaría iniciarlo en el mismo directorio que su instancia de GDB, para que la descarga binaria parezca transparente si la invoca desde GDB (la forma más fácil). También tiene la opción de crear un script que inicie OpenOCD y cargar el código, pero luego tendrá que reiniciarlo después de cada compilación.

La manera estándar (de bajo costo) de programar los microcontroladores ARM es usar Eclipse con una compleja cadena de herramientas conectada a él. Eclipse tiene definitivamente sus méritos, pero me gustaría sentirme independiente de este IDE. Me gustaría descubrir qué sucede tras bambalinas cuando compilo (compile - link - flash) mi software, y cuando ejecuto una sesión de depuración. Para obtener una comprensión más profunda, sería maravilloso ejecutar todo el procedimiento desde la línea de comandos.

Nota: estoy usando Windows 10 de 64 bits. Pero la mayoría de las cosas que se explican aquí también se aplican a los sistemas Linux. Por favor, abra todos los terminales de comando con derechos de administrador. Esto puede ahorrar muchos problemas.

1. Construyendo el software

La primera ''misión'' se cumple. Ahora puedo compilar y vincular mi software en un .bin binario y una imagen .elf través de la línea de comandos. La clave del éxito fue descubrir dónde Eclipse coloca sus make-files para un proyecto específico. Una vez que sepa dónde están, todo lo que tiene que hacer es abrir un terminal de comando y escribir el comando GNU make .

¡Ya no necesitas Eclipse para eso! Especialmente si puede leer (y entender) el makefile y adaptarlo a sus necesidades cuando avance su proyecto.

Tenga en cuenta que encontré las herramientas GNU (compilador, vinculador, make utility, GDB, ...) en la siguiente carpeta, después de instalar SW4STM32 (System Workbench para STM32):

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

Luego hice una nueva carpeta en mi disco duro y copié todas estas herramientas GNU en ella:

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

Y agrego estas entradas a la "variable de ruta de entorno":

- C:/Apps/AC6GCC/bin - C:/Apps/AC6GCC/lib/gcc/arm-none-eabi/5.2.1

¡Huray, ahora tengo todas las herramientas GNU en funcionamiento en mi sistema! Puse el siguiente archivo build.bat en la misma carpeta que el makefile :

@echo off echo. echo."--------------------------------" echo."- BUILD -" echo."--------------------------------" echo. make -j8 -f makefile all echo.

Ejecutar este archivo de bat debería hacer el trabajo! Si todo va bien, obtienes un archivo binario .bin y uno .elf como resultado de la compilación.

2. Flasheo y depuración del firmware.

El siguiente paso natural es actualizar el firmware del chip e iniciar una sesión de depuración. En Eclipse es solo un ''clic en un botón'', al menos si Eclipse está configurado correctamente para su microcontrolador. Pero, ¿qué pasa detrás de las escenas? He leído (parte de) la tesis de maestría de Dominic Rath, el desarrollador de OpenOCD. Puedes encontrarlo aquí: http://openocd.net/ . Esto es lo que aprendí:

  • Eclipse inicia el software OpenOCD cuando hace clic en el ícono ''depurar''. Eclipse también proporciona algunos archivos de configuración para OpenOCD, de modo que OpenOCD sabe cómo conectarse a su microcontrolador. ''Cómo conectarse'' no es una cosa trivial. OpenOCD necesita encontrar el controlador USB adecuado para conectarse al adaptador JTAG (por ejemplo, STLink). Tanto el adaptador JTAG como su controlador USB suelen ser suministrados por el fabricante de su chip (por ejemplo, STMicroelectronics). Eclipse también entrega un archivo de configuración a OpenOCD que describe las especificaciones del microcontrolador. Una vez que OpenOCD conoce todas estas cosas, puede establecer una conexión JTAG confiable con el dispositivo de destino.

  • OpenOCD inicia dos servidores. El primero es un servidor Telnet en el puerto TCP 4444. Da acceso a la CLI (interfaz de línea de comandos) de OpenOCD. Un cliente Telnet puede conectarse y enviar comandos a OpenOCD. Esos comandos pueden ser un simple ''detener'', ''ejecutar'', ''establecer punto de interrupción'', ...

  • Dichos comandos podrían ser suficientes para depurar su microcontrolador, pero muchas personas ya estaban familiarizadas con el Gnu Debugger (GDB). Esta es la razón por la que OpenOCD también inicia un servidor GDB en el puerto TCP 3333. ¡Un cliente GDB puede conectarse a ese puerto y comenzar a depurar el microcontrolador!

  • El Gnu Debugger es un software de línea de comandos. Muchas personas prefieren una interfaz visual. Eso es exactamente lo que hace Eclipse. Eclipse inicia un cliente GDB que se conecta a OpenOCD, pero eso está oculto para el usuario. Eclipse proporciona una interfaz gráfica que interactúa con el cliente GDB detrás de escena.

He hecho una figura para explicar todas estas cosas:

>> Puesta en marcha de OpenOCD

Logré iniciar OpenOCD desde la línea de comandos. Te explico como

  1. Primero asegúrese de que su programador STLink-V2 JTAG esté correctamente instalado. Puede probar la instalación con la "herramienta de utilidad STLink" de STMicroelectronics. Tiene una interfaz gráfica de usuario agradable y simplemente hace clic en el botón Conectar.
  2. A continuación, descargue el ejecutable del software OpenOCD desde este sitio web: http://gnutoolchains.com/arm-eabi/openocd/ . Instálelo y colóquelo en una carpeta de su disco duro, como "C: / Apps /".
  3. Abra un terminal de comando e inicie OpenOCD. Deberá darle a OpenOCD algunos archivos de configuración, de manera que sepa dónde buscar su microcontrolador. Por lo general, debe proporcionar un archivo de configuración que describa al programador JTAG y un archivo de configuración que defina su microcontrolador. Pase esos archivos a OpenOCD con el argumento -f en la línea de comando. También deberá dar acceso a OpenOCD a la carpeta de scripts , pasándolo con el argumento -s . Así es como inicio OpenOCD en mi computadora con la línea de comando:

    > "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 inició OpenOCD correctamente (con los argumentos correctos), se iniciará con el siguiente mensaje:

    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. Observe que su ventana de terminal ahora está bloqueada. Ya no puede escribir comandos. Pero eso es normal. OpenOCD se ejecuta en segundo plano y bloquea el terminal. Ahora tiene dos opciones para interactuar con OpenOCD: inicia una sesión de Telnet en otro terminal e inicia sesión en el puerto TCP localhost:4444 , por lo que puede dar comandos a OpenOCD y recibir comentarios. O inicia una sesión de cliente GDB y conéctela al puerto TCP localhost:3333 .

>> Iniciar una sesión de Telnet para interactuar con OpenOCD

Así es como inicia una sesión de Telnet para interactuar con el programa OpenOCD en ejecución:

> dism /online /Enable-Feature /FeatureName:TelnetClient > telnet 127.0.0.1 4444

Si funciona bien, recibirá el siguiente mensaje en su terminal:

Open On-Chip Debugger > ..

¡Y ya está listo para enviar comandos a OpenOCD! Pero ahora voy a cambiar a la sesión de GDB, ya que es la forma más conveniente de interactuar con OpenOCD.

>> Iniciar una sesión de cliente GDB para interactuar con OpenOCD

Abre otra ventana de terminal y escribe el siguiente comando:

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

Este comando simplemente inicia el cliente GDB de arm-none-eabi-gdb.exe . Si todo va bien, GDB comienza con el siguiente mensaje:

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)..

Ahora conecte este cliente GDB al servidor GDB dentro de OpenOCD:

(gdb) target remote localhost:3333

Ahora estás conectado a OpenOCD! Es bueno saberlo: si desea usar un comando OpenOCD nativo (como lo haría en una sesión de Telnet), preceda el comando con el monitor palabras clave. De esta manera, el servidor GDB dentro de OpenOCD no manejará el comando por sí mismo, sino que lo pasará al deamon nativo de OpenOCD.

Entonces, ahora es el momento de restablecer el chip, borrarlo y detenerlo:

(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

El chip ya está listo para recibir algunas instrucciones de nosotros. Primero le diremos al chip que sus secciones de flash 0 a 7 (que son todas las secciones de flash en mi chip de 1Mb) no deben estar protegidas:

(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

A continuación paro el chip de nuevo. Sólo para estar seguro..

(gdb) monitor halt

Finalmente le .elf archivo binario .elf a 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.

Ahora es el momento de la verdad. Le pido a GDB que cargue este binario en el chip. Dedos cruzados:

(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

Lamentablemente no tuvo éxito. Recibo el siguiente mensaje en OpenOCD:

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

EDIT: problema de hardware solucionado.

Aparentemente era un problema de hardware. Nunca pensé que mi chip estaría defectuoso, ya que cargar el binario en el chip con la herramienta STLink Utility funcionó sin problemas. Solo OpenOCD se quejaba y daba errores. Así que naturalmente culpé a OpenOCD, y no al chip en sí. Ver mi respuesta a continuación para más detalles.

EDITAR: ¡Una forma elegante y alternativa de flashear el chip - usando makefile!

A medida que se solucionó el problema, ahora me centraré en una forma alternativa de ejecutar el flash y la depuración del chip. ¡Creo que esto es realmente interesante para la comunidad!

Es posible que haya notado que usé los comandos de Windows cmd para ejecutar todos los pasos necesarios. Esto puede ser automatizado en un archivo por lotes. Pero hay una forma más elegante: automatizar todo en un archivo make! Sr./Mss. ¿Othane ha sugerido el siguiente makefile para su Cortex-M? chip. Supongo que el procedimiento para un chip Cortex-M7 es muy similar:

################################################# # 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)

Estimado Sr./Mss. Othane, ¿podría explicar cómo usar este makefile para los siguientes pasos?

  • Construye el binario desde el código fuente
  • Flashear el chip

Sé algunos conceptos básicos sobre los makefiles, pero tu makefile es realmente muy profundo. Parece que utilizas bastantes características de la utilidad make de GNU. Por favor, danos una explicación más y te concederé el bono ;-)

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


Ahora simplemente invoca "gdb" y conéctalo al "servidor remoto" (localhost si el servidor y gdb se ejecutan en la misma máquina). Configure GDB de modo que sepa la ubicación del código fuente y la ubicación del archivo ELF. Hay un montón de sitios web que pasan por el uso básico de GDB ...

Parece que hay un GDB para Windows ( http://www.equation.com/servlet/equation.cmd?fa=gdb )

Los siguientes comandos en GDB deberían ayudarte a comenzar:

destino remoto localhost: 3333

directorio / ruta / a / proyecto

archivo de símbolos /path/to/project.elf


Aparentemente era un problema de hardware. Nunca pensé que mi chip estaría defectuoso, ya que cargar el binario en el chip con la herramienta STLink Utility funcionó sin problemas. Solo OpenOCD se quejaba y daba errores. Así que naturalmente culpé a OpenOCD, y no al chip en sí.

Hoy intenté el mismo procedimiento con un nuevo chip en el tablero, ¡y ahora funciona!

Obtengo la siguiente salida en GDB al emitir el comando de load :

(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 Start address 0x8003450, load size 15388 Transfer rate: 21 KB/sec, 2564 bytes/write. (gdb)

Gracias a todos los que hicieron todo lo posible por ayudarme :-)


Como lo recuerdo, también tuve algunos problemas con el comando de carga directa, así que cambié a "flash write_image borre my_project.hex 0 ihex" ... obviamente estaba usando archivos hexadecimales, pero parece que los archivos elf deberían funcionar, vea http://openocd.org/doc/html/Flash-Commands.html ... lo bueno de este comando es que también borra solo las secciones de flash que se están escribiendo, lo que es realmente útil y no necesita borrado

Antes de ejecutar el comando anterior, deberá ejecutar "stm32f1x unlock 0" para asegurarse de que el chip esté desbloqueado y que pueda conectarse al flash ... Consulte la hoja de datos sobre esto

También para comenzar, el comando "stm32f1x mass_erase 0" borrará el chip por completo y rápidamente, por lo que es bueno asegurarse de que comiences en un estado conocido

Sé que algunos de estos comandos dicen que son para los f1, pero confía en mí, trabajan para la serie f4

Por cierto, este archivo contiene la mayoría de los comandos que utilizo para actualizar mi f4, por lo que podría ser una buena referencia https://github.com/othane/mos/blob/master/hal/stm32f373/stm32f373.mk

Espero que eso te despegue


Este es un poco breve y no es un gran estilo de , pero le señalaría mi código donde lo he configurado para mi biblioteca "mos" para STM32F4 y STM32F1 ( https://github.com/othane/mos ). Este es un gran tema para responder, así que creo que un ejemplo podría ser mejor.

En resumen, mi proyecto es un árbol de Makefiles, ya que tiene su código para compilar el principal de su interés aquí se encuentra aquí https://github.com/othane/mos/blob/master/hal/stm32f373/stm32f373.mk ... básicamente necesitas openocd y luego tengo una serie de comandos para permitir borrar el chip, o destellar y depurar el nuevo código, etc. simplemente escribiendo make .erase o make .flash o make .debug

Finalmente, si observa mis pruebas de unidad (estos son básicamente programas de ejemplo) encontrará el Makefile para compilarlo + un archivo gdbinit como este https://github.com/othane/mos/blob/master/utest/gpio/debug_gpio_utest.gdbinit ... entonces simplemente haces "make && make .flash && make .debug" en un terminal, y llamas a tus compiladores cruzados gdb así "arm-none-eabi-gdb -x ./debug_gpio_utest.gdbinit" en otro ... esto iniciará gdb después de actualizar el código y puede usar los comandos normales de ruptura y lista de gdb, etc. para interactuar con el código (observe cómo definí un comando de reinicio en el archivo .gdbinit, consulte la ayuda para el mon comando ... básicamente, le permitirá enviar comandos a través de gdb directamente a openocd y es realmente útil)

Lo siento, la respuesta es bastante breve y con muchos enlaces, pero espero que se ponga en marcha.