Wednesday, October 20, 2010

USB Bootloader for LPC1768-H Blue Board

The JTAG debugger has been working quite well. But it needs a parallel port which most laptops including my own lack. LPC17xx conveniently supports USB device interface which can be used for bootloading. USB is ubiquitous and using it will obviate the need for any extra programming hardware.

If you don't know what a bootloader is, then you should read this tutorial in sparkfun. The bootloader presented there is targeted to LPC2148 which is based on the ARM7TDMI core which differs quite a bit from the Cortex M3 on which the LPC1768 is based on. So, you need to read only enough to understand what a USB bootloader is.

NXP has provided a USB secondary bootloader as a sample program along with their app note on how to use mass storage device class. Here is the app note along with the code. You'll need Keil uVision 4 to compile the code. A free version which compiles upto 32 kB is available. This is sufficient since the bootloader itself occupies only 8 kB of flash. If you don't intend on modifying the code, look at the attachment below. A link to the HEX file which can be burnt is given.

The bootloader code will upon reset, check the status of a certain pin and decide whether to enter the bootloader or execute the user code. The default pin checked by the NXP USB bootloader is not mapped to a switch on the LPC1768-H Blue Board. A quick look at the schematic of the blueboard reveals that the only usable switch is connected to P2.10. This unfortunately is also the pin tested by the default UART bootloader present in all NXP LPC17xx chips. So, holding the switch and pressing reset till cause entry into the UART bootloader. Because, that is the only pin to which a switch is connected, we are forced to use that to signal the entry into a bootloader. A slight modification to the code given by NXP is thus necessary.

The idea is to capture the status of P2.10 not immediately after reset but after a gap a second or two. The modified bootloader will upon reset, turn on the test LED and wait for about 3 seconds. If during that period, the switch is pressed (P2.10 goes LOW), the bootloader is launched. If however, no key press is detected by the end of 3 secs( the test LED glows during this time), user code, if present is launched. It is important to see that, P2.10 should not be held LOW while resetting the CPU. Doing so will cause NXP's UART bootloader to launch on reset since it is that program which samples P2.10 first. The switch should be pressed only after the test LED glows indicating the secondary USB bootloader is sampling P2.10 and not NXP's UART bootloader.Subsequently, the bootloader will function as described in the app note. The only change is the entry method.

Here is the modified code.
And the HEX File.

Now, one small change is necessary in the linker file of the user programs ( that will be loaded by the bootloader onto the chip). The bootloader itself resides at 0x00000000 and uses 8 KB of space. So the user program should begin at 0x00002000. This should be explicitly stated in the linker file.

The code base that can be used to jump start the project with an editor like eclipse is here. Note that I've modified the flash start address in the linker file to 8 KB so that this code base can be used to generate bin files needed for bootloading.

You should modify the start flash address ( to 0x00002000 from 0x00000000 ) in the linker file of the user program if you are using some other code base.

EDIT :

I've added all these files in google code.

11 comments:

  1. This is awesome stuff!

    I just started out a while ago with an mbed, which is great, but utterly unusable as a true production example. I want to make something with the LPC1768 from scratch. So I also stumbled upon the Blueboard-LPC1768-H from NGX, but was worried about programming it. Me and JTAG + OpenOCD have kind of a not-so-smooth history, so this little nugget nudges me in the right direction I guess. Thanx a bunch!

    ReplyDelete
  2. I was worried about openOCD too given the difficulty people have had with it and reported in various forums. Thankfully, I never had to use it. To initially flash the bootloader to the board, i used H-JTAG which worked very easily. And H-JTAG compatible USB->JTAG or LPT->JTAG are easily available. I think even NGX has a few offerings. But after flashing the USB bootloader, I havent gone back to the JTAG.

    I'm trying to get the bootloader to reset the microcontroller after the flashing automatically. Currently, the board has to be hard-reset after flashing is complete.Though not an issue, its more convenient to have it reset itself after flashing.

    ReplyDelete
  3. I ordered the Blueboard-LPC1768-H. Soon as I have it, I'll look into the H-JTAG for programming the secondary bootloader. Then I'll get cracking with some of the tutorials you host on Google Code. I'll report back when I have some results...

    ReplyDelete
  4. OK,

    Got my Blueboard-LPC1768-H a couple of days ago but just started playing with it today. First tried Rowley Crossworks trial with NGX-ARM-USB-JTAG. Works alright, but I can't really get used to the whole debugging over JTAG thing. Took me 2 hours before I got something flashed into the board that would just run stand-alone, without the JTAG thingy connected.

    Now it was time for FlashMagic. Just for fun I downloaded the 32Kb limited uVision4 IDE from Keil to see what that is all about, and got your Blinky project compiled in it. But since I used built-in startup code from Keil, I guess the timing routine was way off and the LED blinked about once every 40 seconds or so. Good fun. But I have to mention a trend in trying to get these professional / commercial environments set up en running: man, it just eats scores of hours to get things going properly (it doesn't help that i'm a complete n00b). Anyways, time for some low-budget open-source fidgeting:

    I wanted the secondary bootloader to work. Programming via USB is the most convenient way of going about this stuff (PIC18F4550 FTW!). Found your recent post called 'Code Sourcery g++ Lite and Programmer's Notepad for LPC1768 development' and compiled Blinky from this post: 'Hello Word ( LED blinker ) on LPC1768 explained. GPIO tutorial' with Code Sourcery in Programmer's Notepad. Had some minor problems (detailed at the appropriate post) but eventually got the bootloader 'bootloaderV2.hex' programmed with Flash Magic and just drag-'n-dropped the freshly compiled Blinky from USB starter code (starter_code_14Jan2011_for_USBBootloader.rar) to my LPC1768 in windows explorer. Wonderful stuff, this whole mass storage class business.

    Anyways, it works like a charm! Thanx for all the detailed and for-n00bs-accessible tutorials in your posts. I'll keep checking in!

    ReplyDelete
  5. Keil probably uses libc which means, at boot, _start() is executed and control is subsequently passed to main() which means ResetHandler() in startup_lpc17xx.c is never executed.

    The PLL is setup in ResetHandler() and the CPU is clocked to 100MHz. Without that, the CPU runs at a MUCH lower frequency which is what caused the LED to blink once in 40 secs.

    Using JTAG for debugging on open source software has always been troublesome. Thats why I liked H-JTAG which allows easy flash burning without much setup. Once the USB bootloader is installed, LPC1768 development is very smooth.

    Actually, the NGX Blue Board has the USB bootloader pre-installed. But for some strange reason, the entry pin is set to P2.10 which has no switch/jumper connected to.

    I should write to NGX asking them to use some other entry mechanism like the one i'm using.

    ReplyDelete
  6. I get now where my 40 second interval came from... :). H-JTAG is indeed a great solution. As touched upon in another comment in your post 'Code Sourcery g++ Lite and Programmer's Notepad for LPC1768 development', I tried it on an older PC with a parallel port.

    First I built your non-buffered wiggler from the post: 'Hello World from LPC1768', and on this older PC with Win XP Pro x86 (32 bit) SP3 the program worked, and it recognized my STM32F103RBT6 perfectly.

    Safe for some reliability issues (my soldering skills I guess), I could program it, although it was painfully slow compared to STM's USART0 bootloader tool.

    But I completely agree that the secondary USB bootloader solution as posted here is the smoothest way of doing things. I also noticed in the manual that the Blueboard came pre-installed with this bootloader, but I already read in your post how you got it going, so I immediately switched to your modified version.

    First I thought that with one of the jumpers J9, J11 or J16 one could connect the ISP switch SW2 to USART0 bootloader or USB respectively. But I can't find anything on what those jumpers are actually for. From the schematic I infer that J11 and J16 control power supply lines, but I can't even find J9. So yeah, I think that from an explanatory / user's manual point of view, NGX still has some explaining to do, or update their entry mechanism somwehow, like you suggested...

    ReplyDelete
  7. The concern w.r.t entry mechanism is quite valid. The reason for not having a switch/button is the fact that when the board was initially designed, USB bootloader was not considered as a possible way of programming the board. It was only after the launch that this functionality has been provided. We have quite a few nos of PCBs in stock. The next revision will for sure have a cleaner USB bootloader entry mechanism.

    -Ashwin
    NGX Technologies Pvt Ltd

    ReplyDelete
  8. Wow...
    it worked so smooth. Thanks.
    The bootloader from the NGX site did not work for me, it did not launched the user code I paste in the storage device, but your code works.

    ReplyDelete
  9. can u please upload step by step procedure for dumping using CooCox IDE and JTAG

    ReplyDelete
  10. Thank you Sagar. This helped a lot. I spent few days struggling with NGX bootloader with GCC toolchain made .bin file. Finally your modified bootloader helped me. Thank you very much.

    ReplyDelete
  11. I am trying to use this bootloader (v2) with Linux. Even though it is working well on windows, it is not able to copy hex from Linux system. Either file is not copied or partially copied. Not able to run the program. Any idea?

    ReplyDelete