EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

Getting my LPC2148 to boot by itself ! (JTAG Flashing, Openocd, hard reset)

Started by armdeveloper February 2, 2007
I've got an Olimex LC2148 board. It and my code run fine when I use
lpc2k_pgm to program and run it. No problems.

However, my code doesn't run when I program it with the JTAG pod.

Question #1: does openocd or the gnu linker calculate the signature for
memory location 0x14 automatically ? My openocd config file has this in
it:
flash bank lpc2000 0x0 0x7D000 0 0 lpc2000_v2 0 12000 calc_checksum
Does calc_checksum calculate the value for 0x14 ?

Question#2:
"The Insiders Guide to the Philips ARM7 Based Microcontrollers" by
Trevor Martin discusses the fact that the LPC2000 processors come out of
reset in boot mode. Apparently, one needs to write 0x02 to MEMMAP so
the processor will boot from FLASH. (I'm referring to page 52, Section
3.6.2)

I dug around in the code for lpc2k_gpm and I found this:
/* ARM code to run user code */
begin:
adr r0, const
ldr r1, [r0] /* r1 points to MEMMAP register */
mov r0, #1
str r0, [r1] /* remap interrupt vectors to flash */
mov pc, #0 /* and then jump to the user's code */
const:
.int 0xE01FC040 /* MEMMAP register */

How do I program both this code and the vector table to start at 0x00 ?

Thanks

An Engineer's Guide to the LPC2100 Series

Pardon me, to get user flash mode, one should write 0x01 to MEMMAP.

So where do I place the code to do that when the processor comes out of
reset in boot mode ?

Thanks

On Fri, 2007-02-02 at 15:26 -0700, armdeveloper wrote:
> I've got an Olimex LC2148 board. It and my code run fine when I use
> lpc2k_pgm to program and run it. No problems.
>
> However, my code doesn't run when I program it with the JTAG pod.
>
> Question #1: does openocd or the gnu linker calculate the signature for
> memory location 0x14 automatically ? My openocd config file has this in
> it:
> flash bank lpc2000 0x0 0x7D000 0 0 lpc2000_v2 0 12000 calc_checksum
> Does calc_checksum calculate the value for 0x14 ?
>
> Question#2:
> "The Insiders Guide to the Philips ARM7 Based Microcontrollers" by
> Trevor Martin discusses the fact that the LPC2000 processors come out of
> reset in boot mode. Apparently, one needs to write 0x02 to MEMMAP so
> the processor will boot from FLASH. (I'm referring to page 52, Section
> 3.6.2)
>
> I dug around in the code for lpc2k_gpm and I found this:
> /* ARM code to run user code */
> begin:
> adr r0, const
> ldr r1, [r0] /* r1 points to MEMMAP register */
> mov r0, #1
> str r0, [r1] /* remap interrupt vectors to flash */
> mov pc, #0 /* and then jump to the user's code */
> const:
> .int 0xE01FC040 /* MEMMAP register */
>
> How do I program both this code and the vector table to start at 0x00 ?
>
> Thanks
On Fri, 2007-02-02 at 15:38 -0700, armdeveloper wrote:
> Pardon me, to get user flash mode, one should write 0x01 to MEMMAP.
>
> So where do I place the code to do that when the processor comes out of
> reset in boot mode ?
>
> Thanks
lpc2k_pgm seems to load the program to change MEMMAP program to RAM.
But that can't be because the RAM will get wiped every time the
processor powers down.

Do I have something wrong with my openocd configuration ? Should it be
doing this for me automatically ?
case BOOT_SOFT:
switch(event) {
case BEGIN:
printf("Booting (soft jump)...\r\n");
printf("loading jump code\r\n");
// would be nice if we could simply jump to the user's code, but
// Philips didn't think of that. The interrupt vector table stays
// mapped to the bootloader, to jumping to zero only runs the
// bootloader again. Intead, we need to download a tiny ARM
// program that reconfigures the hardware and then jumps to zero.
//snprintf(buf, sizeof(buf), "G %d A\r\n", 0);
snprintf(buf, sizeof(buf), "W %d %d\r\n", chip->ram_addr,
BOOTPROG_SIZE * 4);
xmit_cmd(buf, 4);
return;
case RESPONSE:
if (num_lines(parsed_response_buf) < 1) return;
if (strcmp(parsed_response_buf, "0\r\n") == 0) {
current_addr = 0;
num_to_xmit = BOOTPROG_SIZE * 4;
copy_boot_code_to_memory();
linecount = 0;
cksum = 0;
state = BOOT_XMIT_DATA;
event = BEGIN;
} else {
download_cancel("can't xmit to ram"); return;
}
break;
case TIMEOUT:
download_cancel("No response"); return;
}
break;
--- In l..., armdeveloper wrote:
>
> On Fri, 2007-02-02 at 15:38 -0700, armdeveloper wrote:
> > Pardon me, to get user flash mode, one should write 0x01 to MEMMAP.
> >
> > So where do I place the code to do that when the processor comes
out of
> > reset in boot mode ?
> >
> > Thanks

You're making more of this than there is... When the chip powers up,
it looks at P0.14 to see if you want to continue into ISP mode for
downloading. If not, it looks at the checksum in the 6th vector
location. If the checksum is correct, the chip branches to the user
program. If not, it enters ISP mode. All of this is discussed in the
User Manual. But the checksum must be correct!

The Philips (NXP) downloader (lpc21isp) calculates the checksum
automatically. Others, like Rowley Crossworks precalculate the
checksum and put it in the startup.s file. They can do this because
the vectors are constant, each vector doing an indirect branch from a
table in a known location.

If your makefile is set to build the code for flash, you shouldn't
have any problem getting it to start in flash. There is no big hurry
to change MAM, I do it with a function call early in main() but that
is hundreds of instructions from startup.

You should review James Lynch's tutorial. While he is using a
different toolset, the concepts of how and where a program runs are
covered quite well:
http://www.olimex.com/dev/pdf/ARM%20Cross%20Development%20with%20Eclipse%20version%203.pdf

The document covers both the 2106 and 2148. It is probably the best
tutorial around. I know I found it very useful when I first started
with the 2106.

FWIW, he also discusses running programs out of RAM. Interesting, but
not something that I have wanted to do.

Richard
--- In l..., armdeveloper wrote:
> Pardon me, to get user flash mode, one should write 0x01 to MEMMAP.
>
> So where do I place the code to do that when the processor comes out of
> reset in boot mode ?
>
> Thanks
>

The LPC2148 will come of reset in boot mode and run the LPC
bootloader. When the bootloader is finished doing it's thing, it will
switch your vectors into the map itself, and jump to your reset
vector. When your code starts to run, MEMMAP will already be set to
one. You can then remap the vectors to RAM if your code needs to be
able to modify the vectors in normal operation. The main point is,
that coming out of reset the Phillips bootloader is always going to
run before your code runs. That is part of how Phillips implements
it's Code Read Protection.

-- Dave
On Sat, 2007-02-03 at 00:15 +0000, derbaier wrote:
> --- In l..., armdeveloper wrote:
> >
> >
> > Pardon me, to get user flash mode, one should write 0x01 to MEMMAP.
> >
> > So where do I place the code to do that when the processor comes out
> of
> > reset in boot mode ?
> >
> > Thanks
> >
> >
> > The LPC2148 will come of reset in boot mode and run the LPC
> bootloader. When the bootloader is finished doing it's thing, it will
> switch your vectors into the map itself, and jump to your reset
> vector. When your code starts to run, MEMMAP will already be set to
> one. You can then remap the vectors to RAM if your code needs to be
> able to modify the vectors in normal operation. The main point is,
> that coming out of reset the Phillips bootloader is always going to
> run before your code runs. That is part of how Phillips implements
> it's Code Read Protection.

Are you sure about that ?

http://www.hitex.co.uk/arm/lpc2000book/

On page 50, section 3.6.2 says this:

"Every time the LPC2000 comes out of reset its memory map will be in
boot mode, so the instruction on the reset vector will cause it to jump
into the bootloader code entry point at 0x7FFFFFFF. This can be the
bane of new users if they load their code into FLASH with a JTAG., reset
and single step the first instruction only to find that the program
counter is at some wild high address. If this happens, you need to
program the MEMMAP register to 0x00000002, to force the chip into FLASH
mode and return the user vector table."

So this doesn't sound like anything happens automatically.

So how do I program MEMMAP ?

>
--- In l..., armdeveloper wrote:
>
> On Sat, 2007-02-03 at 00:15 +0000, derbaier wrote:
> > --- In l..., armdeveloper
wrote:
> > >
> > >
> > > Pardon me, to get user flash mode, one should write 0x01 to
MEMMAP.
> > >
> > > So where do I place the code to do that when the processor
comes out
> > of
> > > reset in boot mode ?
> > >
> > > Thanks
> > >
> > >
> > >
> >
> > The LPC2148 will come of reset in boot mode and run the LPC
> > bootloader. When the bootloader is finished doing it's thing, it
will
> > switch your vectors into the map itself, and jump to your reset
> > vector. When your code starts to run, MEMMAP will already be set
to
> > one. You can then remap the vectors to RAM if your code needs to
be
> > able to modify the vectors in normal operation. The main point is,
> > that coming out of reset the Phillips bootloader is always going
to
> > run before your code runs. That is part of how Phillips implements
> > it's Code Read Protection.
>
> Are you sure about that ?
>
> http://www.hitex.co.uk/arm/lpc2000book/
>
> On page 50, section 3.6.2 says this:
>
> "Every time the LPC2000 comes out of reset its memory map will be in
> boot mode, so the instruction on the reset vector will cause it to
jump
> into the bootloader code entry point at 0x7FFFFFFF. This can be the
> bane of new users if they load their code into FLASH with a JTAG.,
reset
> and single step the first instruction only to find that the program
> counter is at some wild high address. If this happens, you need to
> program the MEMMAP register to 0x00000002, to force the chip into
FLASH
> mode and return the user vector table."
>
> So this doesn't sound like anything happens automatically.
>
> So how do I program MEMMAP ?
>
>
The description above is correct. The LPC book quote is referring to
the difficulty of setting a breakpoint at the very start of a
program, as (in normal operation) the first thing that runs is the
boot loader. It's only when it's done it's stuff the application
runs. Unless you want to single step through the bootloader, there
has to be a better way of debugging teh startup code. The better way
is to use the debugger to set MEMMAP so that the bootloader is
effectively bypassed when reset by the debugger. It's really only
relevent when debugging though.

Although it takes a while to understand and get used to, it's a
fairly flexible setup as ARMs go.

Brendan.
On Sat, 2007-02-03 at 01:25 +0000, Brendan Murphy wrote:

>
> The description above is correct. The LPC book quote is referring to
> the difficulty of setting a breakpoint at the very start of a
> program, as (in normal operation) the first thing that runs is the
> boot loader. It's only when it's done it's stuff the application
> runs. Unless you want to single step through the bootloader, there
> has to be a better way of debugging teh startup code. The better way
> is to use the debugger to set MEMMAP so that the bootloader is
> effectively bypassed when reset by the debugger. It's really only
> relevent when debugging though.
>
> Although it takes a while to understand and get used to, it's a
> fairly flexible setup as ARMs go.
>
> Brendan.
>
Thanks for taking the time to explain that, late on a Friday no less.
>
I just programmed the flash on my 2148 with lpc2k_pgm and with my JTAG
using openocd.

I then used openocd to read the first 64 bytes of memory for each using
dump_binary from telnet. I compared the files and they are binary
equals. I take this to mean that lpc2k and the JTAG programmer
calculated the same value for 0x14.

Yet the lpc2K loaded file will run from reset and the JTAG won't.
Also, the lpc2k WILL boot with "Reboot" but will not boot with
"Bootloader"

So the device is being programmed the same by the lpc2K and the JTAG
(openocd). The security code appears to be the same for the lpc2K and
JTAG programming.

It runs with an lpc2K Program/Reboot. After that is done, it will run
with a hardware reset.

It won't run with
- JTAG program/reset
- lpc2K Bootloader
- hardware reset

WHY ?
--- In l..., armdeveloper wrote:
>
> On Sat, 2007-02-03 at 00:15 +0000, derbaier wrote:
> > --- In l..., armdeveloper wrote:
> > >
> > >
> > > Pardon me, to get user flash mode, one should write 0x01 to MEMMAP.
> > >
> > > So where do I place the code to do that when the processor comes out
> > of
> > > reset in boot mode ?
> > >
> > > Thanks
> > >
> > >
> > >
> >
> > The LPC2148 will come of reset in boot mode and run the LPC
> > bootloader. When the bootloader is finished doing it's thing, it will
> > switch your vectors into the map itself, and jump to your reset
> > vector. When your code starts to run, MEMMAP will already be set to
> > one. You can then remap the vectors to RAM if your code needs to be
> > able to modify the vectors in normal operation. The main point is,
> > that coming out of reset the Phillips bootloader is always going to
> > run before your code runs. That is part of how Phillips implements
> > it's Code Read Protection.
>
> Are you sure about that ?
>
> http://www.hitex.co.uk/arm/lpc2000book/
>
> On page 50, section 3.6.2 says this:
>
> "Every time the LPC2000 comes out of reset its memory map will be in
> boot mode, so the instruction on the reset vector will cause it to jump
> into the bootloader code entry point at 0x7FFFFFFF. This can be the
> bane of new users if they load their code into FLASH with a JTAG., reset
> and single step the first instruction only to find that the program
> counter is at some wild high address. If this happens, you need to
> program the MEMMAP register to 0x00000002, to force the chip into FLASH
> mode and return the user vector table."
>
> So this doesn't sound like anything happens automatically.
>
> So how do I program MEMMAP ?
>
>
I can assure you that your program WILL start from flash without
changing MEMMAP. In fact, upon review of a couple of my projects, I
don't change MEMMAP at all even on programs using interrupts.

But I do see an example where I commented out setting MEMMAP just
after setting up MAMCR and MAMTIM by just MEMMAP = 0x01;

You know, section 21.4 and more specifically section 21.4.2 of the
User Manual covers all this.

On reset the bootloader maps its' own vectors to force startup of the
bootloader code. During the process, the bootloader disables the
overlaying and does the checksum on the user's vectors and, if
correct, branches to 0x00000000 and, at that point, the user's vectors
are in place.

AFAIK, nothing needs to be done to MEMMAP to get your program to run
out of flash. You can set it to 0x01 if you wish but it doesn't seem
to be required. Or maybe the bootloader does it for you; I can't say
that I have ever read the contents of MEMMAP to see what it contains.

In any event, it just doesn't matter. I just write the code, stuff it
in flash and it runs.

Richard

The 2024 Embedded Online Conference