Jump to content

My time with the LPC1114 dip28

Recommended Posts

I've been trying out the LPC1114 chip from NXP. It is an arm cortex-m0 chip with 32k of flash

and 4k of ram. Quantity 1 pricing is < $3. Did I mention this is available in dip-28 packaging,

very friendly to breadboards? Well it is.

I was going to post this on our sister site, however this chip is more like an msp430 than the cortex-m4 you find on the stellaris launchpad.


Others have posted tutorials to get you going.


http://www.meatandnetworking.com/tutorials/lpc1114fn28-with-open-source-tools/ - how to setup on a breadboad
http://www.embeddedrelated.com/showarticle/101.php?articleid=101- getting started with C++ and the lpc1114
http://www.blacksphere.co.nz/main/blackmagic - an open source SWD debugger that can run on an stm32f4 discovery board.
I'm rounding out my fabooh framework with chips other than the just the msp430.  This seemed like a good hobbyist

friendly chip to add.I'm not ready to release anything but just wanted to let people know I'm working with it so you

may see some code at some point.


In the meantime, I mostly wanted to share this Rei Vilo style breakout for the pins and get a dialog going with others who

might be interested in using this chip.  So if you have interest in this chip, speak up!


http://bit.ly/11GTwWb - LPC1114DIP pin break out.  Hover over the cells for a more detailed description of the pin functions.


Link to post
Share on other sites

A lot has changed recently with regard to arm toolchains. No longer do you have to build

one yourself. You can easily get a fully featured arm compiler binary for all 3 platforms.

(win32/linux/osx). Since last December you can find the linaro gcc available from here:


You want to grab the one that says arm-none-eabi-... for your OS. The 'none-eabi'

means it is a compiler for 'bare-metal' chips without any OS support. EABI

means the libraries conform to the standard ELF ABI for arm chips. They update

these files every quarter with new versions, new features and fixes. Make sure

you read the release notes to see what is new and any cautions.


Once you have a compiler, you can use it with Fredie Chopin's lpc1114_led_blink example

that has a fully featured makefile.


The lpc1114 is a cortex-m0 chip and has full support. They provide newlib libraries

that you can link against although if you are concerned about small code you might

want to avoid that stuff.



Link to post
Share on other sites

The lpc chips have a built in bootloader much like bsl on the msp430 chips.

I think there is a sanctioned flash loader. However, I'm just partial to

opensource and things that run on linux.


You'll find a lot of different versions of the lpc21isp code out there.

The first one I tried (from the meatandnetworking.com article) was just

plain broken. I'm using this version of lpc21isp I found on github.


It was missing support for our chip. So, I did have to patch it so it knows about

the 28 pin version of the lpc1114. I think g0rdon provide me those patches. Thanks

g0rdon! Basically the changes add the 28 pin dip chip id and provides the proper

smaller ram size (4k) to the device table. At startup, lpc21isp interrogates the

chip and then decides if it knows about the chip or not.


$ git diff lpcprog.c
diff --git a/lpcprog.c b/lpcprog.c
index ccf6c41..3fc5471 100644
--- a/lpcprog.c
+++ b/lpcprog.c
@@ -111,6 +111,8 @@ static LPC_DEVICE_TYPE LPCtypes[] =
    { 0x2532902B, "1113.../202",  24,  4,  6, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX
    { 0x0434102B, "1113.../301",  24,  8,  6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX
    { 0x2532102B, "1113.../302",  24,  8,  6, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX
+   { 0x0A40902B, "1114.../102",  32,  4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX
+   { 0x1A40902B, "1114.../102",  32,  4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX
    { 0x0444502B, "1114.../201",  32,  4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX
    { 0x2540902B, "1114.../202",  32,  4,  8, 1024, SectorTable_17xx, CHIP_VARIANT_LPC11XX
    { 0x0444102B, "1114.../301",  32,  8,  8, 4096, SectorTable_17xx, CHIP_VARIANT_LPC11XX

When I first started with electronics I had paid full price for a 3.3V FTDI breakout

board from SparkFun, ouch! However, it actually came in handy with this chip as it

supports the full set of modem signals. I use RX/TX/RTS/DTR. This allows me to use the

lpc21isp program to toggle the boot pin and reset for me. No hands loading.


TX-> Pin 15 (LPX RX)

RX-> Pin 16 (LPC TX)

DTR-> Pin 23 (RESET)

RTS-> Pin 24 (BOOTISP)/P0.1

GND-> Pin 22 (GND)


To load new code i just use make and use the control flags argument

to have it automatically reset the chip, erase it, and then reset the

chip when the code is loading.


$ make clean all 
lpc21isp -wipe -control -postreset lpc1114fn28_release/blink.hex /dev/ttyUSB0 115200 12000
Link to post
Share on other sites

OK, so now you have all the prerequistes to get going. Now I'd like to talk a bit about my stuff. First off, let me say I'm very new at ARM programming and this chip. However, I do have a vision of being able to write efficient C++ templated code that runs cross chip. I call this vision fabooh. http://fabooh.com It is very early in the stage of working and this ARM code is being added to make sure that the API is flexible enough to add multiple chip architectures.


I've checked in some very preliminary code that will provides a general framework for building example programs. The makefile take care of setting all the gcc options for the lpc1114. It is based on the Fredie Chopin and customized to fit into the fabooh directory structure. I'll merge in the msp430 version as I get further along. I didn't want to break the msp430 version as I experiment with the arm version.


If you git clone that, you can type make clean all from the top and build arm firmware for this lpc1114 chip. I'm assuming you have added the arm-none-eabi-gcc and the lpc21isp programs to your path.


$ cd fabooh/examples/basic/blink
$ make clean all install
Removing all generated output files from output directory: lpc1114fn28_release/
rm -f lpc1114fn28_release/blink.bin lpc1114fn28_release/blink.d lpc1114fn28_release/crt0.d lpc1114fn28_release/blink.dmp lpc1114fn28_release/blink.elf lpc1114fn28_release/blink.hex lpc1114fn28_release/blink.lss lpc1114fn28_release/blink.map lpc1114fn28_release/blink.o lpc1114fn28_release/crt0.o
Compiling file: ../../..//board/lpc1114fn28/crt0.c
arm-none-eabi-g++ -c -mcpu=cortex-m0 -mthumb -Os -ffunction-sections -fdata-sections -Wall -Wextra -std=gnu++98 -g -ggdb3 -fno-rtti -fno-exceptions -fverbose-asm  -DCORE_M0 -MD -MP -MF lpc1114fn28_release/crt0.d -I../../..//.  -I../../..//include/cortex-m0/core  -I../../..//board/lpc1114fn28  -I../../..//board/lpc1114fn28/chip_11xx  -I../../..//board/lpc1114fn28/lpc_ip  -I../../..//board/lpc1114fn28/chip_common ../../..//board/lpc1114fn28/crt0.c -o lpc1114fn28_release/crt0.o
Compiling file: blink.cpp
arm-none-eabi-g++ -c -mcpu=cortex-m0 -mthumb -Os -ffunction-sections -fdata-sections -Wall -Wextra -std=gnu++98 -g -ggdb3 -fno-rtti -fno-exceptions -fverbose-asm  -DCORE_M0 -MD -MP -MF lpc1114fn28_release/blink.d -I../../..//.  -I../../..//include/cortex-m0/core  -I../../..//board/lpc1114fn28  -I../../..//board/lpc1114fn28/chip_11xx  -I../../..//board/lpc1114fn28/lpc_ip  -I../../..//board/lpc1114fn28/chip_common blink.cpp -o lpc1114fn28_release/blink.o
Linking target: lpc1114fn28_release/blink.elf
arm-none-eabi-g++ -mcpu=cortex-m0 -mthumb -T../../..//board/lpc1114fn28/lpc1114.ld -g -Wl,-Map=lpc1114fn28_release/blink.map,--cref,--no-warn-mismatch -Wl,--gc-sections -nostartfiles  -L../../..//board/lpc1114fn28  lpc1114fn28_release/crt0.o lpc1114fn28_release/blink.o   -o lpc1114fn28_release/blink.elf
Creating extended listing: lpc1114fn28_release/blink.lss
arm-none-eabi-objdump -S lpc1114fn28_release/blink.elf > lpc1114fn28_release/blink.lss
Creating memory dump: lpc1114fn28_release/blink.dmp
arm-none-eabi-objdump -x --syms lpc1114fn28_release/blink.elf > lpc1114fn28_release/blink.dmp
Creating IHEX image: lpc1114fn28_release/blink.hex
arm-none-eabi-objcopy -O ihex lpc1114fn28_release/blink.elf lpc1114fn28_release/blink.hex
Creating binary image: lpc1114fn28_release/blink.bin
arm-none-eabi-objcopy -O binary lpc1114fn28_release/blink.elf lpc1114fn28_release/blink.bin
Size of modules:
arm-none-eabi-size -B -t --common  lpc1114fn28_release/crt0.o lpc1114fn28_release/blink.o  
   text	   data	    bss	    dec	    hex	filename
    340	      0	      0	    340	    154	lpc1114fn28_release/crt0.o
    224	      0	      4	    228	     e4	lpc1114fn28_release/blink.o
    564	      0	      4	    568	    238	(TOTALS)

lpc21isp -wipe -control -postreset lpc1114fn28_release/blink.hex /dev/ttyUSB0 115200 12000
Reset after flashing.
lpc21isp version 1.83
File lpc1114fn28_release/blink.hex:
Start Address = 0x000000C1
	converted to binary format...
	image size : 556
Image size : 556
Synchronizing (ESC to abort). OK
Read bootcode version: 1
Read part ID: LPC1114.../102, 32 kiB ROM / 4 kiB SRAM (0x1A40902B)
Read Unique ID:
Will start programming at Sector 1 if possible, and conclude with Sector 0 to ensure that checksum is written last.
Wiping Device. OK 
Sector 0: ..................
Download Finished... taking 0 seconds
Now launching the code
That is what it looks like to compile and load a blink program onto the lpc1114. If you poke around you can see a ctr0.c and lpc1114.ld script are provided that handle the power on reset and setting up the c runtime environment initialization. These work without using any of the compilers startup code. This should make it easier to use different toolchains. Note that the startup code also takes care of initializing the c++ global objects. This feature is often left off on sample code you find on the net that is only using straight 'C'. Yes, I'm coding in C++. That is a key feature of fabooh, it is a C++ peripheral template framework.



The code itself is really simple, in fact it looks very similar to the msp430 blink version

#include <fabooh.h>
#include <main.h>

void setup(void) {

void loop(void) {
  const uint32_t freq = 2;
  const uint32_t msec_delay = 1000 / freq / 2;

  while (1) {
I've setup RED_LED in the pins.h to map to pin 17 (P1.8) on the lpc1114. Just provide the chip with power some decoupling caps, a resistor for the led and you are done. See the meatandnetworking breadboard article for a schematic. Then poke around in the directory tree. It is pretty small and simple at this point. It needs a lot more fleshing out. However, the general overall structure is there and the various examples that are checked in should work. Try the serial examples. The print code was taken from the msp430 version and mostly worked without change. I'll be adding more examples as I go along. If you are inspired, you might want to fork fabooh and submit some of your code for inclusion.



Link to post
Share on other sites

One of the stumbling blocks for fans of open source development tools with the lpc1114 is the lack of a supported gdb server for cortex-m0 chips. You can buy an NXP development board. However, they are more expensive than their competitor's boards. In addition, they really expect you to use a commercial IDE. Openocd is a broken option as it doesn't really deal with the cortex-m0 chip unless you are using an STM32 chip.

To the rescue comes a newly minted gem, it is a tool called BlackMagic Probe (BMP). The developer offers an open source hardware and software solution that provides ARM Serial Wire Debug (SWD) as a gdb debug server.  It is unique in that you connect to it over a standard tty device. This greatly simplifies operating system support as most host systems support usb tty devices without much hassle.  Because it is open source, others have added support for off the shelf hardware many of you might already have.

Last year I got one of those STM32F4-Discovery boards. It is a great little dev board that has an on-board programmer along with USB connected to the target side of the board. You can build BMP to use this board. Just clone BMP from github.com.gsmcmullin/blackmagic and then build it with a special target:

make PROBE_HOST=f4discovery clean all

This will produce a blackmagic.bin that can be loaded on the target chip on the STM32F4-Discovery board and used as a gdb server. You will have to use openocd to load it into flash. The next time you power cycle the STM32F4-discovery board, it will appear as a new /dev/ttyACMX device.  Just wire up the pins from the discovery board to the SWD pins on the LPC1114 along with ground and you will end up with working gdb server than can be used to debug your cortex-m0. To start an lpc1114 debug session try this:

arm-none-eabi-gdb -b 115200 -ex 'target remote /dev/ttyACM0' blink.elf

bingo, bango, and you are on your way to writing and debugging code like a pro.

Things are really looking up for those seeking a decent open source development environment that supports the lpc1114fn28.

NXP has an interesting post here that discusses SWD:


Link to post
Share on other sites

So I spent some more time with BMP (BlackMagic Probe). I was able to use it to debug code loaded on the chip using lpc21isp. However, using gdb to load code wasn't working properly. I cranked up arm-none-eabi-gdb and did a little debugging on the BMP code. Turns out that the chip id code for the lpc1114/102 fn28 wasn't in the list of lpc11xx devices. When BMP probes the chip it wasn't finding it in the list and so it had no idea how much flash or ram it had.


This patch: http://dpaste.com/1076138/ has the small changes I made to have it detect our chip.


btw here is the final command line startup i use to debug.

$ arm-none-eabi-gdb -b 115200 -ex 'target extended-remote /dev/ttyACM0' -ex 'mon sw' -ex 'attach 1' lpc1114fn28_release/blink.elf
GNU gdb (GNU Tools for ARM Embedded Processors)
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "--host=i686-linux-gnu --target=arm-none-eabi".
For bug reporting instructions, please see:
Reading symbols from /home2/kimballr/lpc1114_ws/fabooh/examples/basic/blink/lpc1114fn28_release/blink.elf...done.
Remote debugging using /dev/ttyACM0
Target voltage: ABSENT!
Available Targets:
No. Att Driver
 1      LPC1114/102 (0x1A40902B)
Attached to Remote target
0x00000196 in delay_msec (msec=250) at ../../../include/cortex-m0/core/cpu_lpc11xx.h:110
110	    while (tickcount < t)
(gdb) load 
Loading section .text, size 0x234 lma 0x0
Start address 0xc1, load size 564
Transfer rate: 3 KB/sec, 564 bytes/write.
(gdb) run
The program being debugged has been started already.
Start it from the beginning? (y or n) y

Starting program: /home2/kimballr/lpc1114_ws/fabooh/examples/basic/blink/lpc1114fn28_release/blink.elf 
Program received signal SIGINT, Interrupt.
0x00000196 in delay_msec (msec=250) at ../../../include/cortex-m0/core/cpu_lpc11xx.h:110
110	    while (tickcount < t)
(gdb) p tickcount 
$1 = 14804
You get a (gdb) command prompt if all goes well. You just 'load' the code and then 'run'. BMP will automatically erase sectors on the lpc1114 as need to accommodate the new code with the load command. When you run it automatically resets the chip and starts the new code.


[EDIT: BMP has been updated with this change in the latest source, got to love OSS!]



Link to post
Share on other sites

A lot has changed recently with regard to arm toolchains. No longer do you have to build

one yourself. You can easily get a fully featured arm compiler binary for all 3 platforms.

(win32/linux/osx). Since last December you can find the linaro gcc available from here:


You want to grab the one that says arm-none-eabi-... for your OS. The 'none-eabi'

means it is a compiler for 'bare-metal' chips without any OS support. EABI

means the libraries conform to the standard ELF ABI for arm chips. They update

these files every quarter with new versions, new features and fixes. Make sure

you read the release notes to see what is new and any cautions.



I have also been using this toolchain on Linux, with all of my ARM boards, and have been pleased with it.  I used to build my own but got sick of dealing with dependencies.

Link to post
Share on other sites

Building your own toolchain and getting working ldscripts used to be the biggest stumbling block to using these low cost arm chips. I'm happy we are leaving that era behind us. I just read today that NXP acquired the company behind CodeRed. Some people are speculating that this will lower the cost and lock up the tool chain to just NXP chips.



I continue to forge ahead learning about the LPC1114 chip. I'm trying to understand the PLL clock system. The PLL allows you to use a lower speed XTAL to achieve a higher speed system clock. At reset the chip comes up using its interal 12MHz internal oscillator (IRC). If you do nothing that is what you get a 12MHz system clock. You can turn on the PLL subsystem and source it with the IRC. This allows you to run at 24MHZ, 36MHz and 48MHz. It is just a matter of setting the right registers.


NXP provides a really nice excel spreadsheet with macros that is wasted on me as I don't have excel. When I tried to import it into google spreadsheets, it didn't work. However, I found an old version someone else did and imported it into google spreadsheets. The spread sheet lets you enter an input clock and then play with the PSEL and MSEL variables to produce a new FCLKOUT. You can try out the spreadsheet here:

LPC1114 PLL Ratio Calculator


One nice things about these chips compared to the msp430 value line chips is that you can actually use an external crystal. I had a salvaged 12MHz xtal I found on an old ISA PC board. I plopped it on my breadboard and added a few capacitors and some twisty wire. After setting up the PLL subsystem I was able to dial it in to exactly 36.0000MHz .. not bad for a breadboard setup:




Links regarding "twisty wires"


gimmik capacitor

video gimmik capacitor



Link to post
Share on other sites

Now that I'm able to successfully manipulate the system clock using both the internal and external oscillators, I've been looking at the SSP peripheral. My goal was to learn enough about SPP to be able use it to drive 4 pixels of a WS2811 led strip at the full 800kHz clock rate. I've attached some code you can look at and I'll walk through it below.


 * spiws2811.cpp - send grb (Green,Red,Blue) data to 4 ws2811 pixels using lpc1114 SPI peripheral
 * note: assumes 48MHz to support 800kHz data stream, 24MHz or 12MHz use 400kHz
#include <fabooh.h>
#include <main.h>

const uint8_t frames[][12] = {
      0x05,0x05,0x05  /* white 20% */
      ,0x00,0x05,0x00 /* red 20% */
      ,0x05,0x00,0x00 /* green 20% */
      ,0x00,0x00,0x05 /* blue 20% */
      0x5f,0x5f,0x5f  /* white 37d% */
      ,0x00,0x5f,0x00 /* red 37% */
      ,0x5f,0x00,0x00 /* green 37% */
      ,0x00,0x00,0x5f /* blue 37% */
      0xff,0xff,0xff  /* white 100% */
      ,0x00,0xff,0x00 /* red 100% */
      ,0xff,0x00,0x00 /* green 100% */
      ,0x00,0x00,0xff /* blue 100% */
       0x00,0x00,0x00 /* turn them all off */

void setup (void) {
  LPC_SYSCON->PRESETCTRL    |= (1 << 0);            // clear SPI reset, SPI held in reset by default (3.5.2)
  LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 11 | 1 << 16); // enable clock to SPI0 block (3.5.14)

  // reset the ws2811
  // make MOSI a pull-down pin, then wait at least 50us
  LPC_IOCON->PIO0_9 = (LPC_IOCON->PIO0_9 & ~(0b11<<3) | (0b01 << 3));
  delay(2); // 1000ns

  // SPI configuration
  LPC_IOCON->PIO0_9 = (LPC_IOCON->PIO0_9 & ~(0x3)) | 0x01;  // enable MOSI function (7.4.23)

  // optional don't really need to output the clock, however, it is useful for debugging the SPI speed
#if 1
  LPC_IOCON->SCK_LOC = 0x02;  // Selects SCK0 function in pin location PIO0_6/SCK0
  LPC_IOCON->PIO0_6  = 0x02;  // SCK function (sec. 7.4.9)

  // 800kHz = F_CPU=48000000/SSP0CLKDIV=1/CPSR=2/(SCR=1)+1/BITS=15
  // 400kHz = F_CPU=24000000/SSP0CLKDIV=1/CPSR=2/(SCR=1)+1/BITS=15
  // 400kHz = F_CPU=12000000/SSP0CLKDIV=1/CPSR=2/(SCR=0)+1/BITS=15
  LPC_SYSCON->SSP0CLKDIV = 1; // enable SPI clk by writing non-zero clk divisor (3.5.15)
  LPC_SSP0->CPSR = 0x2;       // spi clock prescaler (14.6.5)
  static const unsigned SCR=(F_CPU == 12000000UL) ? 0 : 1;
  // 15 bit transfer, SPI frame format, CPOL=0 + CPHA=1, SCR=1 (14.6.1)
  LPC_SSP0->CR0 = 15-1 | (0b00 << 4) | (0b10 << 6) | (SCR << 8);
  LPC_SSP0->CR1 |= 0x01 << 1; // enable SPI (14.6.2)

  volatile unsigned int i = 0;

  unsigned bit_mask;
  const unsigned fcnt = 4;
  while (1) {
    unsigned cnt=fcnt*4;
    unsigned bits;
    uint8_t *pdata = &frames[i++][0];
    i = ( i < fcnt) ? i : 0;

    do {
      bit_mask = 1 << 7;
      do {
        if (*pdata & bit_mask ) {
          // ~600ns high / ~625ns low at 800kHz
          bits = 0b111111100000000; 
        else {
          // ~250ns high / ~1000ns low at 800kHz
          bits = 0b111000000000000;
        while ( !(LPC_SSP0->SR & (1<<1)) ); // wait until !TNF (Transmit Not Full) (14.6.4)
        LPC_SSP0->DR = bits; // push this pixel data into the SPI FIFO
        bit_mask >>= 1;
      } while(bit_mask);
    } while(--cnt);
    while ( !(LPC_SSP0->SR & (1<<4)) ); // wait until ! BSY (Busy) (14.6.4) meaning all bits transmitted


void loop() {}
I've set this up so that it works with a system clock of (12MHz,24MHz) and 48MHz. The fastest you can drive the SPI peripheral is at F_CPU/2. The most you are going to get out of it is 24MHz. As the ws2811 chips can run at either 800kHz or 400kHz we just need to divide the SPI clock to be succesful.


I'm not going to go in depth in how the ws2811 works, as you can already find lots of info on this site with the details. (Check out oPossums code). The key thing is we need to generate 2 different on off patterns. A '0' bit needs to be 250ns high/ 1000ns low and the '1' bit needs to be 600ns high / 625ns low. You send each bit to the DIN pin of the ws2811 8 bits at a time using MSB order. To set the width of the bits I found 15 bits of SPI data allows me to set the timing very close to what we need.


If we take the total width of the bits 1250 nanaseconds / 15 bits that turns out to be 83.3 nanoseconds per bit. So to send the '0' bit we need to send 0b111000000000000. or 3*83.3 (249.999ns) and 12*83.3333 (999.999ns). For the '1' bit we send 0b111111100000000, or 7*83.3 (583.333ns) and 8*83.3 (666.666ns). These seem to be close enough to work. A nice feature of the LPC1114 SPI peripheral is that it has an 8 frame FIFO. This allows you to send a continous stream of bits with no gaps.


It took me a while to get this working as I overlooked one important feature of the LPC1114 GPIO pins. Most of them have a pull-up pin set by default. Before I noticed this fasct, I had just used a 1k resistor on the P0_9 pin to gnd to pull it down. However, it wasn't going down all the way. Once, I changed the default from pull-up to pull-down, the code just worked.


I added lots of comments in the code above. Hopefully, that will explain most of what I did.


Note: the section reference in the code refer to the LPC1114 user manual # UM10398



Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Create New...