OpenOCD question

Dear all,

I am using OpenOCD to debug my self-made LPC22xx board. Everything works quite well except I have to reset my board every time I try to download my program.

The details are:

I want to downlaod my program into an external flash. I have to

Erase the flash ----- step 1

Reset my board ----- step 2

Download my program ------step 3

If I do not do step 2, step 3 will fail. Does anyone know the reason? Thanks!

The OpenOCD outputs the following message many times, and then the download operation fails.

Debug: embeddedice.c:156 embeddedice_read_re_w_check(): 1.

Regards,

Kevin

Here’s part of the logfile.

Debug: embeddedice.c:252 embeddedice_write_reg(): 5: 0xe3100902

Debug: embeddedice.c:252 embeddedice_write_reg(): 5: 0x1a000072

Debug: embeddedice.c:252 embeddedice_write_reg(): 5: 0xe3a00c11

Debug: embeddedice.c:252 embeddedice_write_reg(): 5: 0xe2800030

Debug: arm7_9_common.c:781 arm7_9_halt(): target->state: debug_running

Debug: embeddedice.c:252 embeddedice_write_reg(): 9: 0xffffffff

Debug: embeddedice.c:252 embeddedice_write_reg(): 11: 0xffffffff

Debug: embeddedice.c:252 embeddedice_write_reg(): 12: 0x00000100

Debug: embeddedice.c:252 embeddedice_write_reg(): 13: 0x000000f7

Debug: embeddedice.c:156 embeddedice_read_reg_w_check(): 1

Debug: arm7_9_common.c:619 arm7_9_poll(): DBGACK set, dbg_state->value: 0x9

Debug: embeddedice.c:252 embeddedice_write_reg(): 0: 0x00000005

Debug: embeddedice.c:252 embeddedice_write_reg(): 12: 0x00000000

Debug: arm7_9_common.c:919 arm7_9_debug_entry(): target entered debug from ARM state

Debug: arm7_9_common.c:951 arm7_9_debug_entry(): target entered debug state in Supervisor mode

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r0: 0x40002100

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r1: 0x70000000

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r2: 0x00001000

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r3: 0x002200a0

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r4: 0x0000f018

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r5: 0x002200aa

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r6: 0x0000aaaa

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r7: 0x00005554

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r8: 0x80000000

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r9: 0x00000000

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r10: 0x7d729f1b

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r11: 0x6e7c4aed

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r12: 0x00000009

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r13: 0x400000ac

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r14: 0x7ffff1ad

Debug: arm7_9_common.c:980 arm7_9_debug_entry(): r15: 0x40002104

Debug: arm7_9_common.c:986 arm7_9_debug_entry(): entered debug state at PC 0x40002104

Debug: target.c:442 target_call_event_callbacks(): target event 3

Debug: armv4_5.c:537 armv4_5_run_algorithm(): setting core_mode: 0x13

Debug: breakpoints.c:87 breakpoint_add(): added hardware breakpoint at 0x400000fc of length 0x00000004

Debug: arm7_9_common.c:1303 arm7_9_resume():

Debug: embeddedice.c:252 embeddedice_write_reg(): 8: 0x400000fc

Debug: embeddedice.c:252 embeddedice_write_reg(): 9: 0x00000003

Debug: embeddedice.c:252 embeddedice_write_reg(): 11: 0xffffffff

Debug: embeddedice.c:252 embeddedice_write_reg(): 13: 0x000000f7

Debug: embeddedice.c:252 embeddedice_write_reg(): 12: 0x00000100

Debug: arm7_9_common.c:1102 arm7_9_restore_context():

Debug: arm7_9_common.c:1118 arm7_9_restore_context(): examining User mode

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r0

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r1

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r2

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r3

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r4

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r5

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r6

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r7

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r8

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: r9

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: pc

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: cpsr

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 0 of mode User with value 0x40000100

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 1 of mode User with value 0x80000000

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 2 of mode User with value 0x00001000

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 3 of mode User with value 0x002200a0

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 4 of mode User with value 0x00000000

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 5 of mode User with value 0x002200aa

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 6 of mode User with value 0x0000aaaa

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 7 of mode User with value 0x00005554

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 8 of mode User with value 0x80000000

Debug: arm7_9_common.c:1181 arm7_9_restore_context(): writing register 9 of mode User with value 0x00000000

Debug: arm7_9_common.c:1118 arm7_9_restore_context(): examining FIQ mode

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: pc

Debug: arm7_9_common.c:1118 arm7_9_restore_context(): examining IRQ mode

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: pc

Debug: arm7_9_common.c:1118 arm7_9_restore_context(): examining Supervisor mode

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: pc

Debug: arm7_9_common.c:1118 arm7_9_restore_context(): examining Abort mode

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: pc

Debug: arm7_9_common.c:1118 arm7_9_restore_context(): examining Undefined mode

Debug: arm7_9_common.c:1132 arm7_9_restore_context(): examining dirty reg: pc

Debug: arm7_9_common.c:1214 arm7_9_restore_context(): writing cpsr with value 0x600000d3

Debug: arm7tdmi.c:475 arm7tdmi_write_xpsr(): xpsr: 600000d3, spsr: 0

Debug: arm7_9_common.c:1221 arm7_9_restore_context(): writing PC with value 0x400000ac

Debug: embeddedice.c:252 embeddedice_write_reg(): 0: 0x00000004

Debug: target.c:442 target_call_event_callbacks(): target event 4

Debug: arm7_9_common.c:1406 arm7_9_resume(): target resumed

Debug: embeddedice.c:156 embeddedice_read_reg_w_check(): 1

Debug: embeddedice.c:156 embeddedice_read_reg_w_check(): 1

Hello Kevin,

could you send a complete log file and your .cfg file to Dominic.Rath gmx.de? The log you’ve posted doesn’t contain the lines that show the flashing fail.

Best regards,

Dominic

It is known that the ARM7 core used by the LPC family does not allow JTAG control right out of reset. So what happens with interrupts or other hardware setups by some flash-stored program program once the JTAG based programming gets into control?

The effect described here may indicate, that there is some interference between the stored program’s hardware setup and the flash programming. If the programming is done after flash erase and a hardware reset, there no longer is any prior state which could interfere.

Maybe it helps to place a 1sec delay loop right after reset, to make sure the JTAG catches the processor before any harm is done.

At reset the processor takes off and runs, and some thousands of instructions later the jtag is able to get control. You have to keep the processor in a cage until you’re ready to let it out.

Here’s what I’m doing in crt.s based on a suggestion by Dominic.

/*

let the application stop processor advancement if they want

to get gdb started at a known location. after starting gdb

they need to tell gdb jump past_gdb_hook. if not debugging then

gdb_hook can just return. gdb_hook is a basic while( 1 ){}

*/

bl gdb_hook

.global past_gdb_hook

past_gdb_hook:

Then I define a go command in .gdbinit.

define go

echo (gdb) target remote :3333\n

target remote :3333

r16

display/i $pc

jump past_gdb_hook

end

I fire up gdb, set breakpoints if desired and then give it the go command.

If you’re not writing your own crt.s, then you’ll probably have to do something equivalent in main.

Hope this helps

Maybe it helps to place a 1sec delay loop right after reset, to make sure the JTAG catches the processor before any harm is done.

where should I place the delay loop? Since there is no code any more in the flash after it is erased.

By the way, I did not connect the reset pin of JTAG to the MCU’s reset pin, will this cause the problem?

Regards,

Kevin

If JTAG cannot reset the MCU, all hardware stays in the state left over from the program which ran before. Guess what happens if there still is a timer interrupt configured, but its handler is gone.

So while the debugger looses control over the MCU when applying reset (IMHO a design fault of the ARM7TDMI debug macrocell), not connecting to reset gets you into other problems, as you demonstrated.

The delay loop suggestion is a result of my own experience with JTAG based code-in-RAM debugging. Debugging got somewhat easier when any (unused but present) flash code did not touch any hardware, because due to the mentioned bug, after reset the debugger usually does not get in control over the MCU before at least part of the flash code code was run. If the startup code (crt.S or whatever it is called in your setup) contains a 1sec delay loop, the debugger can catch the MCU before any initialization has been done, so left over flash code does not hinder RAM based debugging. I’ve not yet done much flash based JTAG debugging, but I won’t be surprised if it helps in this setup too.

A.K.:
So while the debugger looses control over the MCU when applying reset (IMHO a design fault of the ARM7TDMI debug macrocell), not connecting to reset gets you into other problems, as you demonstrated.

It certainly is a serious design weakness, but the fault is NOT with ARM7TDMI EmbeddedICE macrocell. In the LPC family, it was purposely designed that way by Phillips to implement their code read protection “feature”. In Phillips ARM parts the nRESET and nTRST signals are internally connected so that when reseting ARM via nRESET, the JTAG TAP controller is ALSO reset. The TAP controller reset causes the debugger to lose control until the TAP controller can be reconfigured. Since the JTAG clock must be slower than the ARM clock, ARM can execute a very large number of instructions before the debugger regains control. A normal ARM system can be configured so the CPU can be reset without reseting the TAP controller, so it is possible to set a breakpoint at the reset vector and catch ARM before any code has executed. To see how it is really supposed to work, take a look at ARM AppNote 31.

– Dave

This is also true for ATMEL correct?

tcmichals:
This is also true for ATMEL correct?

If your question was to me in response to my description of the Phillips design "feature" concerning nTRST and nRESET, I do not know. I have only worked with cell phone ASICs containing ARM, and the more general purpose Phillips parts. The cell phone ASICs followed ARM's recommendations and could be debugged directly out of reset, while the Phillips parts can not.

– Dave