Debugging a custom LPC2388 board (I tried to be thorough!)

Hello hello!

So I know coming to this segment of the forum with a fresh topic and a nightmarish topic like “custom board” is bad form, but I could use some help just verifying a few things to make sure I didn’t do this completely wrong.

Things about my setup:

  1. I’m working on a linux box, on a custom LPC2388 board of my own design, I can give plenty of details if needed, just ask and ye shall get snippets of the schematic! [Here is a quick picture of what currently assembled if you want to get an idea of what I’m working on.

  2. I compiled arm-elf-gcc and the related tools (ld, ar, as, newlib) using the instructions and script [here, though I modified them to use binutils-2.20.1, gcc-4.4.0, and newlib-1.18.0 instead of the versions listed.

  3. I compiled Openocd-0.4.0 using the following: “/configure --enable-ft2232_libftdi” I had libftdi installed and this compiled and installed fine. I had originally tried “./configure --build=i686-pc-linux-gnu --host=arm-elf --enable-ft2232_libftdi” but this had an error with the fact that there was no usleep defined for the arm platform. I guess since I’m depending on the embeddedICE I don’t need to compile the host side?

  4. I’m using the Olimex arm-usb-ocd, and the default configuration for this included with the openocd distribution for it

  5. For the openocd configuration for the lpc2388 I have a slightly modified version of the lpc2378 file included with the openocd distribution. The modified lines essentially expand the “working space” to use all 64kB of ram (as opposed to the lpc2378’s 32kB of ram) and changed the chip name to “lpc2388”. Everything else looked right, and I couldn’t find something to replace the “_CPUTAPID 0x4f1f0f0f” but openocd appears to detect it anyway.

  6. I compiled the following program which I believe should be correct:

#include <stdio.h>
#include "lpc23xx.h"

// This makes sure that the code protect bits are set to a *known* safe value
// This turns off code protect and allows the JTAG to continue functioning
// DO NOT REMOVE THIS CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
const unsigned crp __attribute__((section(".ARM.__at_0x1FC"))) = 0x00000000;
// DO NOT REMOVE THIS CODE!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

int main(int argc, char *argv[]) {
    IODIR0= 0x00000000;
    IODIR1= (0x01 << 20);

    IOSET1= 0xFFFFFFFF;

    while(1) {
    }

    return 0;
}

The Problem:

So I start up openocd and get the following:

Open On-Chip Debugger 0.4.0 (2010-05-28-21:00)
Licensed under GNU GPL v2
For bug reports, read
	http://openocd.berlios.de/doc/doxygen/bugs.html
jtag_nsrst_delay: 200
jtag_ntrst_delay: 200
trst_and_srst srst_pulls_trst srst_gates_jtag trst_push_pull srst_open_drain
500 kHz
Info : clock speed 500 kHz
Info : JTAG tap: lpc2388.cpu tap/device found: 0x4f1f0f0f (mfg: 0x787, part: 0xf1f0, ver: 0x4)
Info : Embedded ICE version 7
Error: EmbeddedICE v7 handling might be broken
Info : lpc2388.cpu: hardware has 2 breakpoint/watchpoint units

Which looks correct to me, except the “Error: EmbeddedICE v7 handling might be broken” Should I be concerned about that?

I then connect using telnet, run “soft_reset_halt” and upload my code using “flash write_image main.elf” and try to run the code by telling it to continue from address 0. It seems to get into the bootloader or something, gets stuck in THUMB mode, and never exits. I’ve also gone ahead and tried to unplug my jtag programmer and disable the debugging to see if the code runs properly after that, but the LED never lights up like I keep hoping it will.

This is my first ARM project, so I’m not too sure how to proceed from here, I think I’ve figured out a lot of it on my own, but I’m not sure if I’ve done any of it properly. Any help would be greatly appreciated! Thank you for taking the time to read all of this!

----EDIT----

Of course just after I made this post I read the errata: Apparently if you leave VBAT (for the RTC module) floating the device cannot start up (or at least in Rev B, which is what I’m using). I’ll go ahead and do a greenwire fix and see if I’m still having issues. If I’m not I’ll go ahead and delete this post! Sorry to clog up the forum!

----EDIT 2----

It still isn’t working! Please someone: HEEEELLLLPPP!!](Nutaksas Research: Installing Gnuarm ARM Toolchain on Ubuntu 9.04)](http://www.scuzzstuff.org/scuzzbox/scuzzbox_part1_assembled.jpg)

Sorry to bump my own thread, but I still need some help. This post is now the #1 result of google for “newlib lpc2388” so I’m even more at a loss than before! Here is a more simple series of questions:

  1. When compiling newlib how should I specify the path to install? The script used “–prefix=/usr/local/arm” but now all of the references are to some absurd thing like “…/…/…/…/…/newlib-1.18” which doesn’t appear to be working.

  2. How go I specify to gcc where newlib is? Will this just be taken care of if I compile newlib and then recompile gcc?

  3. How should I specify the “main” function in my c files? I originally had “int main(int argc, char *argv)” but that’s of course absurd as I don’t have any arguments! Would “int main(void)” be correct?

  4. Do I need a different crt0.s for the lpc2388?

  5. I got the lpc23xx.h file from Keil [here. Is there an NXP location where I should be downloading this support material (as the file says “Copyright(C) 2006, NXP Semiconductor” I think it’s the correct file but I’d like to be sure)?

Hoping a linux using lpc2xxx developer can help me out with these questions!

Thanks for reading this! And thanks in advanced for any help! Exclamation points!](http://www.keil.com/dd/docs/arm/philips/lpc23xx.h)

So since I haven’t received any complaints from the moderator or in response to my comments, I’ll post one more time in order to help future searchers and with the hope that someone might be able to help me a little bit faster then me trying to figure things out completely on my own :mrgreen:

My Question:

I’ve been trying to figure out why my code doesn’t properly startup with the chip. I’ve been reading through [this tutorial from caltech, but I’m a little bit confused on one main point. Should I be compiling on a regular basis with the arguments “-nostartfiles -Ttext=0” and build my own startup script? There is a “crt0.S” supplied with newlib, which seems to perform many of the important functions like setting up the stack and pushing arguments and calling main, but it does not provide things like the interrupt vectors. This is completely bizarre mostly because it uses software interrupts in crt0.S, which fail spectacularly!

If I am meant to be doing everything that newlib is currently doing in crt0.S, is there a list somewhere of the functions I should call? Should I set up the heap myself? Should I call some sort of heap-setting-up function? Should I ignore everything and watch as “malloc()” fails spectacularly and my program goes down in a blaze of glory?

Thanks for any help!

note: everything below here is me answering my own questions for future searchers

In response to my previous post:

  1. First, a clarification “doesn’t seem to be working” was when I was single stepping through and trying to debug. It compiled fine! The way to have the sources pass through the debugger appears to be to specify the whole path when running configure. So I modified the script to run ```
    pwd/…/newlib-1.18/configure

2) You don't have to specify where newlib is. The "--with-newlib" line seems to automatically find it after you install.

3) I still haven't quite figured this out. The file "crt0.s" supplied with newlib appears to push both an int and a character array onto the stack, which would seem to indicate that the standard "int main(int argc, char *argv[])" is the correct choice, even though you don't have anything passed to you. This is probably useful for having the startup files pass something like a firmware version or something, but you would probably hardcode that anyway so it seems rather pointless. The "int main()" part is important because you can apparently supply an "atexit" function to do something before the chip automatically restarts (like have an infinite loop). So the int part can be passed there.

4) This is still baffling to me!](http://www.ovro.caltech.edu/~dwh/ucos/project_AR1803.pdf)