LPC2103 with USBTINY, gnuarm and openocd stuck in Boot Block

Got my LPC board all setup, can jtag successfully, etc…etc… built the code that came with the lynch tutorial (some modifications) and flashed it using openocd, (flash write_image myimage.hex) and attempted to run. My code just seems to jump pretty quickly into the boot block 0x7fff… and sits there, looping. I’m pretty sure I’ve got my startup code correct, as well as the C… it’s lifted from the tutorial examples and is pretty straightforward. I’m not using an IDE, just the gnuarm tools under linux.

Is this a common thing? Is there something dumb I’m forgetting? What information is best to post to get this resolved (obviously there are a lot of logs and config files and such, and I don’t want to flood this place with useless data)

I’m super excited and haven’t lost hope yet!

Cheers!

-R

ryansturmer:
Got my LPC board all setup, can jtag successfully, etc…etc… built the code that came with the lynch tutorial (some modifications) and flashed it using openocd, (flash write_image myimage.hex) and attempted to run. My code just seems to jump pretty quickly into the boot block 0x7fff… and sits there, looping. I’m pretty sure I’ve got my startup code correct, as well as the C… it’s lifted from the tutorial examples and is pretty straightforward. I’m not using an IDE, just the gnuarm tools under linux.

Is this a common thing? Is there something dumb I’m forgetting? What information is best to post to get this resolved (obviously there are a lot of logs and config files and such, and I don’t want to flood this place with useless data)

I’m super excited and haven’t lost hope yet!

Cheers!

-R

If you are stuck in the bootloader it may be because you do not have the calc_checksum parameter in your OpenOCD “flash bank” config line. Without the proper checksum in the exception vector table, the boot loader will remain in control after reset. Also, if P0.14 is low at reset, your code will not be executed, but the ISP bootloader will reamin in control.

–Dave

Dave,

Thank you for the advice. I should have read the section in the manual about the bootloader, because it spells that p0.14 bit pretty plainly. I’ve tied that pin HIGH, so that shouldn’t be the issue anymore. calulate_checksum was specified by my config file, so I don’t suppose that’s the problem either.

What I’ve done is set up a simple LPC2103 circuit, and want to run the blinking LED example from the lynch tutorial. I’ve taken the C file, with some excess code culled out of it, and compiled it with the following startup code:

/* ***************************************************************************************************************

	crt.s						STARTUP  ASSEMBLY  CODE 
								-----------------------


	Module includes the interrupt vectors and start-up code.

  *************************************************************************************************************** */

/* Stack Sizes */
.set  UND_STACK_SIZE, 0x00000004		/* stack for "undefined instruction" interrupts is 4 bytes  */
.set  ABT_STACK_SIZE, 0x00000004		/* stack for "abort" interrupts is 4 bytes                  */
.set  FIQ_STACK_SIZE, 0x00000004		/* stack for "FIQ" interrupts  is 4 bytes         			*/
.set  IRQ_STACK_SIZE, 0X00000004		/* stack for "IRQ" normal interrupts is 4 bytes    			*/
.set  SVC_STACK_SIZE, 0x00000004		/* stack for "SVC" supervisor mode is 4 bytes  				*/



/* Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs (program status registers) */
.set  MODE_USR, 0x10            		/* Normal User Mode 										*/
.set  MODE_FIQ, 0x11            		/* FIQ Processing Fast Interrupts Mode 						*/
.set  MODE_IRQ, 0x12            		/* IRQ Processing Standard Interrupts Mode 					*/
.set  MODE_SVC, 0x13            		/* Supervisor Processing Software Interrupts Mode 			*/
.set  MODE_ABT, 0x17            		/* Abort Processing memory Faults Mode 						*/
.set  MODE_UND, 0x1B            		/* Undefined Processing Undefined Instructions Mode 		*/
.set  MODE_SYS, 0x1F            		/* System Running Priviledged Operating System Tasks  Mode	*/

.set  I_BIT, 0x80               		/* when I bit is set, IRQ is disabled (program status registers) */
.set  F_BIT, 0x40               		/* when F bit is set, FIQ is disabled (program status registers) */


.text
.arm

.global	Reset_Handler
.global _startup
.func   _startup

_startup:

# Exception Vectors

_vectors:       ldr     PC, Reset_Addr         
                ldr     PC, Undef_Addr
                ldr     PC, SWI_Addr
                ldr     PC, PAbt_Addr
                ldr     PC, DAbt_Addr
                nop							/* Reserved Vector (holds Philips ISP checksum) */
                ldr     PC, [PC,#-0xFF0]	/* see page 71 of "Insiders Guide to the Philips ARM7-Based Microcontrollers" by Trevor Martin  */
                ldr     PC, FIQ_Addr

Reset_Addr:     .word   Reset_Handler		/* defined in this module below  */
Undef_Addr:     .word   UNDEF_Routine		/* defined in main.c  */
SWI_Addr:       .word   SWI_Routine			/* defined in main.c  */
PAbt_Addr:      .word   UNDEF_Routine		/* defined in main.c  */
DAbt_Addr:      .word   UNDEF_Routine		/* defined in main.c  */
IRQ_Addr:       .word   IRQ_Routine			/* defined in main.c  */
FIQ_Addr:       .word   FIQ_Routine			/* defined in main.c  */
                .word   0					/* rounds the vectors and ISR addresses to 64 bytes total  */


# Reset Handler

Reset_Handler:  

				/* Setup a stack for each mode - note that this only sets up a usable stack
				for User mode.   Also each mode is setup with interrupts initially disabled. */
    			  
    			ldr   r0, =_stack_end
    			msr   CPSR_c, #MODE_UND|I_BIT|F_BIT 	/* Undefined Instruction Mode  */
    			mov   sp, r0
    			sub   r0, r0, #UND_STACK_SIZE
    			msr   CPSR_c, #MODE_ABT|I_BIT|F_BIT 	/* Abort Mode */
    			mov   sp, r0
    			sub   r0, r0, #ABT_STACK_SIZE
    			msr   CPSR_c, #MODE_FIQ|I_BIT|F_BIT 	/* FIQ Mode */
    			mov   sp, r0	
   				sub   r0, r0, #FIQ_STACK_SIZE
    			msr   CPSR_c, #MODE_IRQ|I_BIT|F_BIT 	/* IRQ Mode */
    			mov   sp, r0
    			sub   r0, r0, #IRQ_STACK_SIZE
    			msr   CPSR_c, #MODE_SVC|I_BIT|F_BIT 	/* Supervisor Mode */
    			mov   sp, r0
    			sub   r0, r0, #SVC_STACK_SIZE
    			msr   CPSR_c, #MODE_SYS|I_BIT|F_BIT 	/* User Mode */
    			mov   sp, r0

				/* copy .data section (Copy from ROM to RAM) */
                ldr     R1, =_etext
                ldr     R2, =_data
                ldr     R3, =_edata
1:        		cmp     R2, R3
                ldrlo   R0, [R1], #4
                strlo   R0, [R2], #4
                blo     1b

				/* Clear .bss section (Zero init)  */
                mov     R0, #0
                ldr     R1, =_bss_start
                ldr     R2, =_bss_end
2:				cmp     R1, R2
                strlo   R0, [R1], #4
                blo     2b

				/* Enter the C code  */
                b       main

.endfunc
.end

and linker script:

/* identify the Entry Point  */

ENTRY(_startup)



/* specify the LPC2106 memory areas  */

MEMORY 
{
	flash     			: ORIGIN = 0,          LENGTH = 128K	/* FLASH ROM                            	*/	
	ram_isp_low(A)		: ORIGIN = 0x40000120, LENGTH = 223		/* variables used by Philips ISP bootloader	*/		 
	ram   				: ORIGIN = 0x40000200, LENGTH = 64992	/* free RAM area							*/
	ram_isp_high(A)		: ORIGIN = 0x4000FFE0, LENGTH = 32		/* variables used by Philips ISP bootloader	*/
}



/* define a global symbol _stack_end  */

_stack_end = 0x4000FEDC;



/* now define the output sections  */

SECTIONS 
{
	. = 0;								/* set location counter to address zero  */
	
	startup : { *(.startup)} >flash		/* the startup code goes into FLASH */
	
	

	.text :								/* collect all sections that should go into FLASH after startup  */ 
	{
		*(.text)						/* all .text sections (code)  */
		*(.rodata)						/* all .rodata sections (constants, strings, etc.)  */
		*(.rodata*)						/* all .rodata* sections (constants, strings, etc.)  */
		*(.glue_7)						/* all .glue_7 sections  (no idea what these are) */
		*(.glue_7t)						/* all .glue_7t sections (no idea what these are) */
		_etext = .;						/* define a global symbol _etext just after the last code byte */
	} >flash							/* put all the above into FLASH */
	

	

	.data :								/* collect all initialized .data sections that go into RAM  */ 
	{
		_data = .;						/* create a global symbol marking the start of the .data section  */
		*(.data)						/* all .data sections  */
		_edata = .;						/* define a global symbol marking the end of the .data section  */
	} >ram AT >flash					/* put all the above into RAM (but load the LMA copy into FLASH) */

	.bss :								/* collect all uninitialized .bss sections that go into RAM  */
	{
		_bss_start = .;					/* define a global symbol marking the start of the .bss section */
		*(.bss)							/* all .bss sections  */
	} >ram								/* put all the above in RAM (it will be cleared in the startup code */

	. = ALIGN(4);						/* advance location counter to the next 32-bit boundary */
	_bss_end = . ;						/* define a global symbol marking the end of the .bss section */
}
	_end = .;							/* define a global symbol marking the end of application RAM */

The comments say 2106, because it’s the tutorial example, but checking most of the addresses against the 2101/2/3 user manual, the relevant ones seem to be the same. (Perhaps there’s an omission here on my part)

I make everything, and produce a hex file, which I then load into the target. Here’s my openOCD session:

ryansturmer@creampuffstarship:~/src/openocd/trunk$ openocd --file lpc2xxx_armusbocd.cfg
Info:    openocd.c:93 main(): Open On-Chip Debugger 1.0 (2008-01-05-01:03) svn:247
Info:    openocd.c:94 main(): $URL: svn://svn.berlios.de/openocd/trunk/src/openocd.c $
Info:    jtag.c:1291 jtag_examine_chain(): JTAG device found: 0x4f1f0f0f (Manufacturer: 0x787, Part: 0xf1f0, Version: 0x4)
Warning: arm7_9_common.c:742 arm7_9_assert_reset(): srst resets test logic, too
Info:    server.c:67 add_connection(): accepted 'telnet' connection from 0

And here’s what it looks like from the telnet client when I flash the system.

Open On-Chip Debugger
> poll
target state: halted
target halted in Thumb state due to debug request, current mode: Supervisor
cpsr: 0x400000f3 pc: 0x7fffe27e
> flash write_image /home/ryansturmer/projects/repos/lpc2000/examples/demo2106_blink_flash/main.hex 0 ihex
wrote 560 byte from file /home/ryansturmer/projects/repos/lpc2000/examples/demo2106_blink_flash/main.hex in 1s 183467us (0.462096 kb/s)
> reset run
> poll
target state: running
> halt
requesting target halt...
> Target 0 halted
target halted in Thumb state due to debug request, current mode: Supervisor
cpsr: 0x400000f3 pc: 0x7fffe27e

Again, I’m almost certain this is an obvious mistake due to my n00bery. Does anything jump out of the screen at anyone? I can post the C file and the header as well, but it’s pretty vanilla, and I don’t suspect it to be the problem.

Thanks for the help everyone, you guys have all been fantastic!

I am more of a hardware guy than a software, but your startup code looks OK for a simple startup to me, except that I personally would not go into user mode at startup like your code does. It is obvious from where OpenOCD stopped ARM that you are still in the bootloader. Also the fact that you are in Thumb mode is another good clue. Can you set the MEMMAP register to oX01 with OpenOCD to put the chip into user FLASH mode, and then look at your exception address block at 0X00000000 to see if the vectors there are what you expect? Maybe something is not right with your FLASH script?

–Dave

Is the “flash script” distinct from the script file I use to launch openocd with the --file argument? Or are they one and the same? I’m flashing the target from within open ocd, using the flash write_image command. Is that invoking some default script that I might need to modify? Or is it as simple as I think it is?

I set the mode to flash, and dumped the first couple words (at address 0x0) I’m not comfortable enough with this I guess to know if this is what I expect to see there or not. If they’re addresses, some of them appear to point into no-mans-land. Here’s my output:

> mww 0xe01fc040 0x01
> mdw 0 128
0x00000000: 20103018 20103010 44183010 45063010 44183010 00201884 44183130 45063010 
0x00000020: 00000000 00000010 00000005 00000000 02000010 00000010 00000000 00000000 
0x00000040: 20010030 20003040 40204000 20000004 42213046 20201000 20000004 22203010 
0x00000060: 20201000 20000000 40203010 24201000 42000000 20203010 40201000 20040000 
0x00000080: 21203010 20000000 00101030 20102030 20103004 20100000 30100000 30000000 
0x000000a0: 32303042 20200000 20101020 20102020 00010000 30000000 30303430 20000000 
0x000000c0: 40003810 00000000 40000200 40000010 40000010 00000030 41200000 09051000 
0x000000e0: 20003000 20051000 25043000 21023000 20202204 20002400 20203004 20003000 
0x00000100: 21003000 21023000 21003000 2120020c 22003000 22202000 41000000 20200000 
0x00000120: 20003000 40200000 20000000 20200000 41000010 20000000 200a0010 20003001 
0x00000140: 30003014 20102010 22003010 20023040 22013032 20400000 10453040 20203000 
0x00000160: a2013000 02000000 20002000 20203000 44020010 40000000 44102010 40000000 
0x00000180: 21003010 45022010 22203311 40027800 00030035 20100002 10393030 20243000 
0x000001a0: 42013002 23202000 20012000 20323144 00000004 20200000 20200000 40001000 
0x000001c0: 20000004 40003030 40000000 40000000 20010000 40000000 22200200 20000000 
0x000001e0: 20000000 21200000 20004000 2a000010 20200000 20000000 20001000 20403000

The checksum at least seems right (well, it’s not something ridiculous like 0x0 or 0xffffffff or anything)

Just for kicks, I jumped the target to address 0x0 to see if it would run after I put it in user flash mode. It seemed to!

> resume 0
Target 0 resumed
> poll
target state: running
> halt
requesting target halt...
> Target 0 halted
target halted in ARM state due to debug request, current mode: Abort
cpsr: 0x400000d7 pc: 0x00000118

Stepping has it move about in that lower part of flash, so perhaps it’s executing the code after all, though the fact that it’s in Abort (data abort?) mode has me concerned. My LED doesn’t actually blink. (Actually, I just have a scope attached to P0.7, and am watching it for activity.

I’m doing this through the telnet interface. I’d like to use GDB, because presumably, I can hook it up with my symbols and actually see where the program is if it’s in a reasonable place, but I can’t quite figure that out.

Any further thoughts are welcomed heartily.

-R

Okay!

Replying to my own thread here. Put stuff down, had a beer, came back, tried some more stuff.

You know what you have to do with flash memory? ERASE IT, turns out. Yeah, I know, astonishing. smacks forehead So everything is cool now! Almost. I have a different issue now, one that probably merits its own topic, so I’m going to create one.

Thanks guys!

-R