LPC1114FN28 with Open Source Tools

7 September 2012

I’ve been excited about the LPC1114FN28 for a while now (at least, as excited as one could be about a microcontroller).  The LPC1114FN28 is a microcontroller from NXP with an ARM Cortex-M0 core in a 28 pin DIP package. With 32k of flash and 4k of RAM, this chip isn’t the biggest or baddest on the block, but at $1.50 in small quantities, it has just about every other uC beat in the performance-per-dollar arena.  It’s got the basic peripherals, SPI, Serial, ADC, and I2C.  It’s programmable via SWD or serial bootloader. Though I don’t use a breadboard too often any more, it’s great to have an easy-to-prototype ARM chip in my box.  Unfortunately, these chips are notoriously difficult to work with, especially with open source tools.

A few posts ago, I talked about getting an open-source ARM toolchain up and running.  With the correct linker scripts, this toolchain will work very well for this chip.  NXP has also seen fit to include an internal RC oscillator on-board, so the breadboard setup for this chip is surprisingly simple.  Here’s what I used:

I’ve got an LED for power, an LED hooked up to PIO1_8 (pin 17), a reset switch, and a pin header configured to work with an FTDI cable or an FTDI friend hooked up to the serial lines.  Most important is the resistor between ground and PIO0_1 (pin 24).  The value of this pin is sampled at reset, and if it is tied to ground, the chip enters the serial bootloader. Otherwise, it executes the loaded program.  This process can’t be done in software, so you have to connect this resistor when you want to load code, and disconnect the resistor when you want to run your program.  You could also use a pin on the FTDI friend for this, but you’d have to modify the ISP software.

As I said, I’m using the toolchain I configured earlier.  I found some blinky test code for another chip in the LPC1114 family, and modified it to work with the LPC1114FN28.  The modified code can be found here: https://github.com/Zuph/lpc1114-blink

In order to get the code to work, I altered the linker script to reflect the amount of RAM on this particular chip, and changed the pin configuration for the LED pin.  I also had to change the clock source: this was the most difficult piece to chase down.  Unlike AVR chips, where the clock configuration is set by fuses, this ARM chip (and many others) force the user to configure clock sources manually. Originally, line 154 of main.c read:

LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_SEL_SYSOSC;

This configured the chip to use an external oscillator.  Changing this to:

LPC_SYSCON->SYSPLLCLKSEL = SYSPLLCLKSEL_SEL_IRC;

resolved the problems.  Output code is now being generated properly, but getting it on the chip is a different problem entirely!  Reading the manual for the series makes the bootloader look like a fairly simple piece of work!  Auto-baud synchronization makes interfacing simple, and the commands are reasonably easy to understand.  There are a few programs which purport compatibility with the the LPC111x family, including VSProg (from the Versaloon folks), and a likely-abandoned projected called lpc21isp.  Neither of these programs, however, support the LPC1114FN28/102 variant.  VSProg looked to be the most promising (given its general purpose nature), but modifying the config files proved fruitless in adding support for the FN28 (if you can get it working, please let me know!).  lps21isp, however, worked well once the parameters for the chip were programmed in.  I’ve uploaded the code for my variant here: https://github.com/Zuph/lpc21isp

I had to change lpcprog.c, adding the following on line 116:

{ 0x1A40902B, “1114FN…/102”, 32, 4, 8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX },

This adds the FN28 chip-id, along with the amount of RAM, flash, number of flash pages, and the maximum amount of data to transfer at once (the bootloader uses a two step process, writing code to RAM, then moving it to flash in order to reprogram the ship).  Once this is added, I was able to easily flash code to the chip, although I wasn’t able to do so at 9600 baud.  115200 baud works well.

In summary, wire up a breadboard as seen in the picture above, compile the blink code, flash it on to the chip using the lpc21isp program, remove the resistor on pin 24, reset the chip, and watch it blink!

Here are the exact commands I used:

brad@ThinkBrad:~/Dropbox/Dev/lpc1114_blink (master)$ make
Size of modules:
arm-none-eabi-size -B -t --common out/startup.o out/main.o out/vectors.o   
   text	   data	    bss	    dec	    hex	filename
    100	      0	      0	    100	     64	out/startup.o
    480	      0	      0	    480	    1e0	out/main.o
    200	      0	      0	    200	     c8	out/vectors.o
    780	      0	      0	    780	    30c	(TOTALS)

Size of target .elf file:
arm-none-eabi-size -B out/lpc1114_blink_led.elf
   text	   data	    bss	    dec	    hex	filename
    940	      0	   1024	   1964	    7ac	out/lpc1114_blink_led.elf

brad@ThinkBrad:~/Dropbox/Dev/lpc1114_blink (master)$ make
Size of modules:
arm-none-eabi-size -B -t --common out/startup.o out/main.o out/vectors.o   
   text	   data	    bss	    dec	    hex	filename
    100	      0	      0	    100	     64	out/startup.o
    480	      0	      0	    480	    1e0	out/main.o
    200	      0	      0	    200	     c8	out/vectors.o
    780	      0	      0	    780	    30c	(TOTALS)

Size of target .elf file:
arm-none-eabi-size -B out/lpc1114_blink_led.elf
   text	   data	    bss	    dec	    hex	filename
    940	      0	   1024	   1964	    7ac	out/lpc1114_blink_led.elf

brad@ThinkBrad:~/Dropbox/Dev/lpc1114_blink (master)$ ../lpc21isp/lpc21isp.out out/lpc1114_blink_led.hex /dev/ttyUSB0 115200 12000
lpc21isp version 1.83
File out/lpc1114_blink_led.hex:
	loaded...
Start Address = 0x000000C1
	converted to binary format...
	image size : 940
Image size : 940
Synchronizing (ESC to abort). OK
Read bootcode version: 1
7
Read part ID: LPC1114FN.../102, 32 kiB ROM / 4 kiB SRAM (0x1A40902B)
Will start programming at Sector 1 if possible, and conclude with Sector 0 to ensure that checksum is written last.
Erasing sector 0 first, to invalidate checksum. OK 
Sector 0: ..........................
Download Finished... taking 0 seconds
Now launching the brand new code
brad@ThinkBrad:~/Dropbox/Dev/lpc1114_blink (master)$

Possible caveats: The chip will only attempt to enter the bootloader once.  If autobaud has been attempted and failed, you’ll need to reset your chip to attempt it again.  Also, in the programming command, we give it the speed (in kHz) of the RC oscillator, since that’s the oscillator that the bootloader will be using.

Let me know if you have any questions.