Debugging con Wiggler, !OpenOCD y Toolchain GNUARM:
Tabla de Contenidos
Hardware:
Esquema de la interconexión de los dispositivos:
<table align="center" border="0"><tbody><tr><td><img src=%ATTACHURL%/EsquemaDebug.png /> </td></tr></tbody></table>
JTAG:
JTAG, the Joint Test Access Group, se fundó en 1985 para crear estándares de prueba de PCB y circuitos integrados. La ùltima versiòn de este propòsito fue aprobada por IEEE como IEEE Std. 1149.1-2001 [IEEE1149], IEEE Standard Test Access Port and Boundary-Scan Architecture.
Usualmente, el tèrmino JTAG refiere al antes mesionado IEEE standard, antes que a el grupo que creò este. Como consecuencia, JTAG debería hacer referencia a IEEE Std. 1149.1.
Usos
Según lo dicho anteriormente JTAG ha sido adoptado con otros propósitos. Los usos comunes incluyen:
- Boundary-Scan testing. Esto es para lo que JTAG fue originalmente creado. Los patrones de prueba son serialmente corridos en el dispositivo para ser testeados, mientras los resultados son mandados de vuelta al equipamiento de testeo maestro. Las conexiones entre ICs o el correcto funcionamiento de un IC por si mismo puede ser testeado usando boundary-scan testing.
- In-System Programming (ISP). In-System programmable devices incluye (Flash-)EEPROMs, dispositivos de lógica programable (CPLDs, FPGAs) y microcontroladores con memoria integrada no volátil. La programación In-System permite a estos dispositivos ser reconfigurados in-field, tanto como facilmente testeados y debbugeados durante la fase de desarrollo.
- Debugging. Los tradicionales emuladores In-Circuit han venido despopularizándose con los modernos microcontroladores embebidos, el nuevo diseño System-On-Chip incluye facilidades de debug entre todos los dispositivos. JTAG esta siendo usado para acceder al circuito integrado de debug en el microcontrolador, dejando otras interfases de comunicación libres para uso general. Este es el método actualemente utilizado para debug en microcontroladores ARM.
Un sitema típico para cualquier propósito incluyendo JTAG consiste en un sistema host (generalmente una PC), uan interface de hardware, y un sistema target.
Interfaces de hardware JTAG
El hardware depende de la tarea que vayamos a realizar, y demás recursos disponibles como por ejemplo recursos.
El más simple dispositivo que está siendo usado en la actualidad son un poco màs que cambiadores de nivel para el puerto paralelo de la PC. El Macraigor Wiggler, o clones de este dispositivo comercialmente disponible, y varios cables paralelos disponibles desde algunos distribuidores PLD (como Xilinx Parallel Cable III, Altera ByteBlaster MV, Lattice ispDOWNLOAD cable) son miembros de este tipo de interface. El host PC serializa todo dato que debe ser transmitido a través de JTAG cambiando bits individuales del puerto paralelo. Un solo acceso al puerto toma al menos 1uS, limitando la frecuencia máxima a 500kHz, pero en la practica los resultados serás mucho más bajos.
- Dsipositivos más avanzados implementan la serialización en hardware, resultando en una performance drasticamente incrementada. El Macraigor Raven es una interface para el puerto paralelo de la PC que está disponible para correr hasta 8MHz, aunque la velocidad efectiva sea un poco menor. FTDI's FT2232c son dispositivos con USB 1.1 Fullspeed (hasta 11MBit) que operan a con frecuencias TCK de hasta 6MHz.
Referencias
IEEE Std. 1149.1-2001
Wiggler clone:
El Wiggler clone es un programador/debbuger utilizado para la programación de microcontroladores ARM. Utiliza la interfase JTAG de los mismos y el puerto paralelo de nuestra PC.
El puerto paralelo debe estar configurado en EPP en la configuración de la BIOS.
Circuito:
<img width="600" alt="wiggler_schema.png" src="/pub/CIII/LabElectronica/DebugWigglerOpenOCDGNUARM/wiggler_schema.png" height="450" />
Placa y distribución de los componentes:
Jtag_Wiggler_placa.pdf: Placa Wiggler JTAG.
Jtag_Wiggler_distrib.pdf: Distribución de los Componentes en la placa.
Software
!OpenOCD:
- El Open On-Chip Debugger (!OpenOCD) permite la interacción con el usuario a travéz de una interface telnet (por defecto: port 4444) y con un GDB server (por defecto: port 3333). El intérprete de línea de comandos esta disponible para ambas interfaces. Nosotros lo utilizamos para que haga el vínculo entre la Wiggler y nuestro arm-elf-gdb o arm-elf-insight.
Está disponible en los mirrors Debian. Para más información al respecto la página oficial del proyecto es:
<a target="top" href="http://openfacts.berlios.de/index-en.phtml?title=Open''On-Chip_Debugger">http://openfacts.berlios.de/index-en.phtml?title=Open_On-Chip_Debugger</a>
Como se ha detectado un bug para los micros LPC en las versiones de !OpenOCD que se encuentran en los repositorios Debian se hace una pequeña reseña de como compilar el proyecto desde sus fuentes. Bajamos el ultimo repositorio desde la SVN como usuario con: *$ svn checkout svn://svn.berlios.de/openocd/trunk* luego usamos *$ ./bootstrap* ahora usamos configure con los flags necesarios: *$ ./configure --prefix /home/usuario/ --enable-parport --enable-parport_ppdev* lo cual va a depender de el jtag que tengamos. ahora solo resta realizar make *$ make* y luego agregar al .bashrc de nuestro usuario el proyecto: PATH=~/trunk/src/:${PATH} Hay que reiniciar el modo gráfico para que el bash comienze a funcionar, además se desintaló el openocd de Debian antes de realizar todo.
Espera por Muestra o ajusta el nivel de debug a Ejecuta comando desde <file>
$ load_image <file> ['bin'||'ihex'||'elf'] Load image <file> to target memory at dump_image <file> <size> Dump <size> bytes of target memory starting at to a (binary) <file>. load_binary <file> [DEPRECATED] Load binary <file> to target memory at dump_binary <file> <size> [DEPRECATED] Dump <size> bytes of target memory starting at to a (binary) <file>.:
Muestra información acerca de los bancos flash <num> Chequea el estado de borrado de los sectores en banco flash <num>. Esta es la única operación que actualiza la información de estado de borrado mostrada por 'flash info'. Esto significa que se tiene que ejecutar un comando 'erase_check' despues de borrar o programar el dispositivo para tener información actualizada. Chequea el estado de protección de los sectores en un banco flash <num>. Borra sectores en el banco<num>, empezando en el sector <first> hasta e incluyendo <last>. La numeración de los sectores empieza de 0. Dependiendo del tipo de flash, el borrado puede requerir protección para ser deshabilitado primero (e.g. Intel Advanced Bootblock flash using the CFI driver). Escribe el binario<file> al banco flash <num>, espezando en <offset> bytes desde el comienzo del banco. Este comando fue reemplazado por el nuevo comando 'flash write_binary' usando la misma sintaxis. Escribe el binario<file> al banco flash <num>, espezando en <offset> bytes desde el comienzo del banco. Escribe la imágen <file> al/los actual/es banco/s flash del target. Una relocación[offset] puede ser especificada y el archivo[type] puede ser especificado explicitamente como 'bin' (binary), 'ihex' (Intel hex), 'elf' (ELF file) o 's19' (Motorola s19). Habilita ('on') o deshabilita ('off') la protección a sectores flash <first> hasta <last> del banco flash <num>.
Estos comandos son específicos para ARM7 y ARM9, como !ARM7TDMI, ARM720t, ARM920t o !ARM926EJ-S. Habilita el uso del canal de comunicación de debug (DCC) para escribir grandes cantidades de memoria (>128 byte). Las descargas DCC ofrecen un incremento grande de la velocidad, pero pueden ser potencialmente inseguras, especialmente con dispositivos corriendo a baja velocidad. Este comando fue introducido con
Para el correcto funcionamiento del !OpenOCD con nuestra interfaz Wiggler debemos tener los permisos como usuario para acceder al mismo. Para agregar el usuario a dialout como root tipeamos: Además damos los permisos pertinentes de la siguiente forma:
Aqui vemos que debe mostrarnos openocd al correrlo. Lo hacemos desde la carpeta donde esta nuestro archivo de configuración (en mi caso en donde a la vez se encuentra mi proyecto). La opción debug nos muestra toda la información de lo que va haciendo el programa y file linkea nuestro archivo de configuración con !OpenOCD. Y ya tenemos nuestro Wiggler conectado, en este caso en el puerto 3333 del localhost.
Una vez que se tiene conectado !OpenOCD desde la consola, procedemos a ejecutar arm-elf-insight en otra consola entrando: Target Settings configuramos: Compilando !OpenOCD desde la SVN:
Comandos generales:
Daemon
n milisegundos de retornar la ejecución. Util en conexiones con archivos script(comandos 'script' y configuraciones 'target_script'). Manejador de estado del Target:
Comandos de acceso a memoria:
Comandos para la memoria Flash:
Comandos específicos ARM7/9
OpenOCD rev. 60. Uso de !OpenOCD:
Archivo de configuración para ARM7 LPC2114 y Wiggler:
#daemon configuration
telnet_port 4444
gdb_port 3333
# tell gdb our flash memory map
# and enable flash programming
gdb_memory_map enable
gdb_flash_program enable
#interface
interface parport
parport_port /dev/parport0
parport_cable wiggler
jtag_speed 3
#use combined on interfaces or targets that can't set TRST/SRST separately
reset_config trst_and_srst srst_pulls_trst
#jtag scan chain
#format L IRC IRCM IDCODE (Length, IR Capture, IR Capture Mask, IDCODE)
jtag_device 4 0x1 0xf 0xe
#target configuration
target create target0 arm7tdmi -endian little -chain-position 0 -variant arm7tdmi-s_r4
working_area 0 0x40000000 0x4000 nobackup
#[new_target_name] configure -work-area-virt 0 -work-area-phys 0x40000000 -work-area-size 0x4000 -work-area-backup false
#flash bank lpc2000 <base> <size> 0 0 <target#> <variant>
flash bank lpc2000 0x0 0x20000 0 0 0 lpc2000_v2 14765 calc_checksum
# For more information about the configuration files, take a look at:
# http://openfacts.berlios.de/index-en.phtml?title=Open+On-Chip+Debugger
#init
#reset halt
Consideraciones puerto paralelo y usuarios:
# gpasswd -a suusuario dialout
$ su
# rmmod lp
# modprobe ppdev
# chmod 666 /dev/parport0
# exit
$
Conectando el Wiggler con !OpenOCD:
usuario@dominio:~/Desktop/Debug$ openocd --file wiggler.cfg --debug 0
Open On-Chip Debugger 1.0 (2008-11-21-19:57) svn:1181
BUGS? Read http://svn.berlios.de/svnroot/repos/openocd/trunk/BUGS
$URL: svn://svn.berlios.de/openocd/trunk/src/openocd.c $
Debug: 1. 0 configuration.c:88 find_file(): found wiggler.cfg
Debug: 1. 0 command.c:91 script_command(): script_command - telnet_port
Debug: 1. 0 command.c:108 script_command(): script_command - telnet_port, argv[0]=ocd_telnet_port
Debug: 1. 0 command.c:108 script_command(): script_command - telnet_port, argv[1]=4444
Debug: 11 0 command.c:91 script_command(): script_command - gdb_port
Debug: 12 0 command.c:108 script_command(): script_command - gdb_port, argv[0]=ocd_gdb_port
Debug: 13 0 command.c:108 script_command(): script_command - gdb_port, argv[1]=3333
Debug: 15 0 command.c:91 script_command(): script_command - gdb_memory_map
Debug: 16 0 command.c:108 script_command(): script_command - gdb_memory_map, argv[0]=ocd_gdb_memory_map
Debug: 17 0 command.c:108 script_command(): script_command - gdb_memory_map, argv[1]=enable
Debug: 19 0 command.c:91 script_command(): script_command - gdb_flash_program
Debug: 20 0 command.c:108 script_command(): script_command - gdb_flash_program, argv[0]=ocd_gdb_flash_program
Debug: 21 0 command.c:108 script_command(): script_command - gdb_flash_program, argv[1]=enable
Debug: 23 0 command.c:91 script_command(): script_command - interface
Debug: 24 0 command.c:108 script_command(): script_command - interface, argv[0]=ocd_interface
Debug: 25 0 command.c:108 script_command(): script_command - interface, argv[1]=parport
Debug: 27 1 command.c:91 script_command(): script_command - parport_port
Debug: 28 1 command.c:108 script_command(): script_command - parport_port, argv[0]=ocd_parport_port
Debug: 29 1 command.c:108 script_command(): script_command - parport_port, argv[1]=/dev/parport0
Debug: 31 1 command.c:91 script_command(): script_command - parport_cable
Debug: 32 1 command.c:108 script_command(): script_command - parport_cable, argv[0]=ocd_parport_cable
Debug: 33 1 command.c:108 script_command(): script_command - parport_cable, argv[1]=wiggler
Debug: 35 1 command.c:91 script_command(): script_command - jtag_speed
Debug: 36 1 command.c:108 script_command(): script_command - jtag_speed, argv[0]=ocd_jtag_speed
Debug: 37 1 command.c:108 script_command(): script_command - jtag_speed, argv[1]=3
Debug: 38 1 jtag.c:1965 handle_jtag_speed_command(): handle jtag speed
User: 39 1 command.c:372 command_print(): jtag_speed: 3
Debug: 41 1 command.c:91 script_command(): script_command - reset_config
Debug: 42 1 command.c:108 script_command(): script_command - reset_config, argv[0]=ocd_reset_config
Debug: 43 1 command.c:108 script_command(): script_command - reset_config, argv[1]=trst_and_srst
Debug: 44 1 command.c:108 script_command(): script_command - reset_config, argv[2]=srst_pulls_trst
Debug: 46 1 command.c:91 script_command(): script_command - jtag_device
Debug: 47 1 command.c:108 script_command(): script_command - jtag_device, argv[0]=ocd_jtag_device
Debug: 48 1 command.c:108 script_command(): script_command - jtag_device, argv[1]=4
Debug: 49 1 command.c:108 script_command(): script_command - jtag_device, argv[2]=0x1
Debug: 50 1 command.c:108 script_command(): script_command - jtag_device, argv[3]=0xf
Debug: 51 1 command.c:108 script_command(): script_command - jtag_device, argv[4]=0xe
Debug: 52 1 target.c:3993 jim_target(): Target command params:
Debug: 53 1 target.c:3994 jim_target(): target create target0 arm7tdmi -endian little -chain-position 0 -variant arm7tdmi-s_r4
Debug: 55 1 command.c:91 script_command(): script_command - working_area
Debug: 56 1 command.c:108 script_command(): script_command - working_area, argv[0]=ocd_working_area
Debug: 57 1 command.c:108 script_command(): script_command - working_area, argv[1]=0
Debug: 58 1 command.c:108 script_command(): script_command - working_area, argv[2]=0x40000000
Debug: 59 1 command.c:108 script_command(): script_command - working_area, argv[3]=0x4000
Debug: 60 1 command.c:108 script_command(): script_command - working_area, argv[4]=nobackup
Debug: 62 2 command.c:91 script_command(): script_command - bank
Debug: 63 2 command.c:108 script_command(): script_command - bank, argv[0]=ocd_flash_bank
Debug: 64 2 command.c:108 script_command(): script_command - bank, argv[1]=lpc2000
Debug: 65 2 command.c:108 script_command(): script_command - bank, argv[2]=0x0
Debug: 66 2 command.c:108 script_command(): script_command - bank, argv[3]=0x20000
Debug: 67 2 command.c:108 script_command(): script_command - bank, argv[4]=0
Debug: 68 2 command.c:108 script_command(): script_command - bank, argv[5]=0
Debug: 69 2 command.c:108 script_command(): script_command - bank, argv[6]=0
Debug: 70 2 command.c:108 script_command(): script_command - bank, argv[7]=lpc2000_v2
Debug: 71 2 command.c:108 script_command(): script_command - bank, argv[8]=14765
Debug: 72 2 command.c:108 script_command(): script_command - bank, argv[9]=calc_checksum
Debug: 74 2 command.c:91 script_command(): script_command - init
Debug: 75 2 command.c:108 script_command(): script_command - init, argv[0]=ocd_init
Debug: 76 2 openocd.c:143 handle_init_command(): target init complete
Debug: 77 2 parport.c:353 parport_init(): opening /dev/parport0...
Debug: 78 2 parport.c:365 parport_init(): ...open
Debug: 79 41 parport.c:237 parport_reset(): trst: 0, srst: 0
Debug: 80 41 openocd.c:150 handle_init_command(): jtag interface init complete
Debug: 81 41 jtag.c:1625 jtag_init_inner(): Init JTAG chain
Debug: 82 41 jtag.c:327 jtag_call_event_callbacks(): jtag event: JTAG controller reset (TLR or TRST)
Debug: 83 41 jtag.c:1305 jtag_reset_callback(): -
Debug: 84 41 jtag.c:327 jtag_call_event_callbacks(): jtag event: JTAG controller reset (TLR or TRST)
Debug: 85 41 jtag.c:1305 jtag_reset_callback(): -
Info: 86 52 jtag.c:1414 jtag_examine_chain(): JTAG device found: 0x4f1f0f0f (Manufacturer: 0x787, Part: 0xf1f0, Version: 0x4)
Debug: 87 52 jtag.c:327 jtag_call_event_callbacks(): jtag event: JTAG controller reset (TLR or TRST)
Debug: 88 52 jtag.c:1305 jtag_reset_callback(): -
Debug: 89 52 openocd.c:156 handle_init_command(): jtag init complete
Debug: 90 56 embeddedice.c:401 embeddedice_write_reg(): 0: 0x00000005
Debug: 91 60 embeddedice.c:401 embeddedice_write_reg(): 12: 0x00000000
Debug: 92 60 embeddedice.c:401 embeddedice_write_reg(): 20: 0x00000000
Debug: 93 62 openocd.c:159 handle_init_command(): jtag examine complete
Debug: 94 62 openocd.c:165 handle_init_command(): flash init complete
Debug: 95 62 openocd.c:169 handle_init_command(): mflash init complete
Debug: 96 62 openocd.c:173 handle_init_command(): NAND init complete
Debug: 97 62 openocd.c:177 handle_init_command(): pld init complete
Debug: 98 63 gdb_server.c:2205 gdb_init(): gdb service for target arm7tdmi at port 3333
Warning: 99 63 tcl_server.c:178 tcl_init(): no tcl port specified, using default port 6666
Warning: 100 110 arm7_9_common.c:744 arm7_9_poll(): DBGACK set while target was in unknown state. Reset or initialize target.
Debug: 101 110 embeddedice.c:401 embeddedice_write_reg(): 0: 0x00000005
Debug: 102 110 embeddedice.c:401 embeddedice_write_reg(): 12: 0x00000000
Debug: 103 113 arm7_9_common.c:1164 arm7_9_debug_entry(): target entered debug from ARM state
Debug: 104 148 arm7_9_common.c:1196 arm7_9_debug_entry(): target entered debug state in System mode
Debug: 105 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r0: 0x2000001f
Debug: 106 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r1: 0xe3a03000
Debug: 107 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r2: 0x00aa0000
Debug: 108 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r3: 0xe0028014
Debug: 109 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r4: 0xe002c000
Debug: 110 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r5: 0x7ffffe3c
Debug: 111 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r6: 0x4000012c
Debug: 112 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r7: 0x00000000
Debug: 113 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r8: 0xffffffff
Debug: 114 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r9: 0xffffffff
Debug: 115 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r10: 0xffffffff
Debug: 116 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r11: 0x40003ef4
Debug: 117 151 arm7_9_common.c:1227 arm7_9_debug_entry(): r12: 0x40003ef8
Debug: 118 152 arm7_9_common.c:1227 arm7_9_debug_entry(): r13: 0x40003ee4
Debug: 119 152 arm7_9_common.c:1227 arm7_9_debug_entry(): r14: 0x4000022c
Debug: 120 152 arm7_9_common.c:1227 arm7_9_debug_entry(): r15: 0x4000039c
Debug: 121 152 arm7_9_common.c:1233 arm7_9_debug_entry(): entered debug state at PC 0x4000039c
Debug: 122 152 target.c:717 target_call_event_callbacks(): target event 4 (early-halted)
Debug: 123 152 target.c:3125 target_handle_event(): event: 4 early-halted - no action
Debug: 124 152 target.c:717 target_call_event_callbacks(): target event 5 (halted)
Debug: 125 152 target.c:3125 target_handle_event(): event: 5 halted - no action
User: 126 152 target.c:973 target_arch_state(): target state: halted
User: 127 152 armv4_5.c:317 armv4_5_arch_state(): target halted in ARM state due to breakpoint, current mode: System
cpsr: 0x2000001f pc: 0x4000039c
Uso básico con programa alojado en RAM usando arm-elf-insight:
usuario@dominio:~/Desktop/Debug$ arm-elf-insight
<img width="741" alt="Targetselection.png" src="/pub/CIII/LabElectronica/DebugWigglerOpenOCDGNUARM/Targetselection.png" height="430" />
<img width="492" alt="abrirprograma.png" src="/pub/CIII/LabElectronica/DebugWigglerOpenOCDGNUARM/abrirprograma.png" height="285" />
Le ponemos que "no" a cada una de las sugerencias:
<img width="564" alt="no.png" src="/pub/CIII/LabElectronica/DebugWigglerOpenOCDGNUARM/no.png" height="122" />
<img width="267" alt="ok.png" src="/pub/CIII/LabElectronica/DebugWigglerOpenOCDGNUARM/ok.png" height="129" />
Download y nos tiene que dar el mensaje de que la descarga fue exitosa en la parte inferior de la pantalla. Desde alli procedemos a operar el Debugger teniendo las siguientes opciones:
<img width="423" alt="menu.png" src="/pub/CIII/LabElectronica/DebugWigglerOpenOCDGNUARM/menu.png" height="99" />
De izquierda a derecha:
El linker script que usamos debe alojar todos los sectores de nuestro programa en la memoria RAM, de modo de que la aplicación se aloje alli. Esto se logra modificando el linker script, cambiando ROM o FLASH por RAM como sector destinado.
En nuestra placa de desarrollo se debe conectar el puente que se encuentra dispuesto a tal fin. El mismo conecta Los pines RTCK con el TCK de la interface JTAG. El circuito sincroniza por TCK al ARM cores internal clock, generando la entrada DBGTCKEN requerida por el ARM core y provee un clock de realimentación (RTCK) que habilita el debugger a usar velocidades de clock adaptables.
Blink-Led en C corriendo en RAM:
Se plantea como próximas actividades: Realizar las mismas experiencias con un dispositivo de interfaz USB (Se sugiere oocd-link) Hay mas información en: http://www.hs-augsburg.de/~hhoegl/proj/usbjtag/usbjtag.html y en http://www.joernonline.de/ Información adicional http://wiki.sikken.nl/index.php?title=ArmDebug#Insight Consideraciones linker script:
Consideraciones placa de desarrollo ARM:
Ejemplos:
Estado Actual del Proyecto: