Arduino Uno with a 32-bit ARM Cortex-M0 in 28 pin DIL package

Somebody has already tried LPC1114FN28/102 DIP28 on a breadboard with a "blink a led" test code. See: http://www.meatandnetworking.com/tutorials/lpc1114fn28-with-open-source-tools/ for all details. The test just says that this ARM is relatively easy to use by hobbyists. However, it does not prove anything about the performance of LPC1114FN28/102 as compared with an Atmega328p, for example. If it is not 10 times faster, likely AVR funs will not abandon so easily their favorite microcontroller for it.

If it is not 10 times faster, likely AVR funs will not abandon so easily their favorite microcontroller for it.

It wouldn't be even remotely close to being 10x faster.

You use those chips not for speed, or costs, but for lower software costs, a non-factor for the hobbyist markets.

nxp just announced a CM0 chip in 8pdip.

It wouldn't be even remotely close to being 10x faster.

how do you figure? It could easily be 10x faster for SOME purposes. Say: 32bit integer math. A 32bit add on AVR takes at least 4 instructions at 16MHz, or 250ns. a 32bit add on an LPC1114 takes 1 instruction at 50MHz, or 20ns. More than 10x faster. Of course, your program will never be all 32bit math, but...

That kind of comparison makes sense if all you do with your mcu is to add 32-bit numbers. Even in that comparison, what if you wanted to process char or short?

More importantly, for those of us using those chips for a variety of different tasks, you would be hard-pressed to show the cmx chips are 10x faster than a comparable avr (or any other 8-bit mcu).

There is a comparison between ARM Cortex M0 and other controllers including AVR. see: http://ics.nxp.com/literature/presentations/microcontrollers/pdf/cortex.m0.code.density.pdf especially pages 41, 42, 43.

Oh, I'll accept "not 10x faster", but I think "not remotely close to 10x faster" is too harsh. I see "almost always faster, and 12x faster for some pretty common operations. " I think I could come up with non-contrived code that would be significantly more than 12x faster (say by using an array of 32bit constants in flash.)

Of course I'm also in the group that believes an AVR is "fast enough" almost all of the time.

The peripherals are much slower than the mcu: it takes the same time to do 400khz i2c on a 72Mhz CM3 as it does on a 1Mhz avr. Or it takes the same amount of time to wait for a person to press a button, etc.

So the raw speed comparison on a mcu really isn't that meaningful.

I would venture a guess that the CMx chips are no more faster than an avr than their system clocks suggest.

Obviously, that conclusion changes if you are using those chips for some 32-bit intensive tasks (fft for example, or dsp on the cm4s).

Also the ADC for LPC1114FN28/102 is at least 5 times faster than the one on Atmega328p, (for the ARM I am not seeing the maximum conversion time at full resolution which is needed for a more precise comparison).

ARM
The LPC1110/11/12/13/14/15 contain one ADC. It is a single 10-bit successive
approximation ADC with eight channels.

• Measurement range 0 V to VDD.
• 10-bit conversion time >= 2.44 us (up to 400 kSamples/s).

AVR
ATmega48PA/88PA/168PA/328P
Analog-to-Digital Converter
• 10-bit Resolution
• 13 - 260 ?s Conversion Time
• Up to 76.9 kSPS (Up to 15 kSPS at Maximum Resolution)

The voltage range of the Arm is 'Single power supply (1.8 V to 3.6 V)."

A 328 can run up "– 0 - 4MHz@1.8 - 5.5V, 0 - 10MHz@2.7 - 5.5.V, 0 - 20MHz @ 4.5 - 5.5V"

I wonder if the fact an ADC could be required to charge up to the higher VDD on the 328, if that is responsible for some of the time difference?

I wonder if the fact an ADC could be required to charge up to the higher VDD on the 328, if that is responsible for some of the time difference?

I haven't looked into the ARMs directly, but the ADC sampling time is usually related to the size of the sampling cap on the front-end of the ADC, as well as the the value of the external source resistance.

Slower ADCs usually have a sampling cap in the 20-120 pF range, while for the fast ones it's more like 4 pF. Also, the faster ones will say something like "source impedance must be 500 ohms max for maximum sampling rate", while the slower ADCs will say something like 10K max. So, max sampling rate mainly comes down to RC charging.

Thank you for the explanation!

Mouser had 3907 chips LPC1114FN28/102 DIP on 15 Nov. 2012. Now, 4 days later they have 3899 in stock. This microcontroller does not seem to have many clients.

It's an interesting chip, but the wide package and "only" 32k of flash make it less than compelling. A PIC32MX150F128 in narrow 28-dip with 128k of flash is more interesting, even if it's $2 more.

Sigh. It's really clear that NXP is serious about trying to displace 8bit CPUs. I wish they were more obviously "on target" with their attempts. 16pin micoBGAs, 28pin wide DIPs, ... nice tries, but not quite what I was hoping for. I can't quite tell whether they're clueless, or whether it really IS that hard to figure out what is really wanted in this nebulous "hobbyist/small manufacturer/mindshare" market space.

whether it really IS that hard to figure out what is really wanted in this nebulous "hobbyist/small manufacturer/mindshare" market space.

It is quite possible that nxp has studied the market and come to the conclusion that this super-duper red-hot "hobbyist" niche is not where they can make sufficient profit to float their boat. Instead, they want to focus instead on this much larger non-sexy industrial applications market for this chip.

Just try to a get a board with through-hole-parts made today and you will understand.

This microcontroller does not seem to have many clients.

It is probably true that large customer orders don't show up on their web inventory.

I have not studied it too much but the LPC Xpresso IDE, designed for ARMs produced by NXP, seems quite easy to work with.

The IDE hides the internal registers and you work mainly with easy to understand functions that set timers, IO ports, etc.. However, there may be traps, complications. LPC Xpresso IDE does not have a simulator, for instance, like Keil. You need the real hardware to test your code.

LPC Xpresso code example:

/****************************************************************************
 *   $Id:: PWM16_32test.c 3635 2010-06-02 00:31:46Z usb00423                $
 *   Project: NXP LPC11xx 16-bit/32-bit PWM example
 *
 *   Description:
 *     This file contains PWM test modules, main entry, to test PWM APIs.
 *
 ****************************************************************************
 * Software that is described herein is for illustrative purposes only
 * which provides customers with programming information regarding the
 * products. This software is supplied "AS IS" without any warranties.
 * NXP Semiconductors assumes no responsibility or liability for the
 * use of the software, conveys no license or title under any patent,
 * copyright, or mask work right to the product. NXP Semiconductors
 * reserves the right to make changes in the software without
 * notification. NXP Semiconductors also make no representation or
 * warranty that such application will be suitable for the specified
 * use without further testing or modification.
****************************************************************************/

#include "driver_config.h"
#include "target_config.h"

#include "timer32.h"
#include "timer16.h"
#include "gpio.h"

extern volatile uint32_t timer32_0_counter;

volatile uint32_t period = 1000;  //48Khz PWM frequency

/* Main Program */

int main (void) {
    /* Initialize 32-bits timer 0 */
    init_timer32(0, TIME_INTERVAL);
    enable_timer32(0);

    /* Initialize the PWM in timer32_1 enabling match0 output */
    init_timer32PWM(1, period, MATCH0);
    setMatch_timer32PWM (1, 0, period/4);
    enable_timer32(1);

    /* Initialize the PWM in timer16_1 enabling match1 output */
    init_timer16PWM(1, period, MATCH1, 0);
    setMatch_timer16PWM (1, 1, period/8);
    enable_timer16(1);

    /* Enable AHB clock to the GPIO domain. */
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<6);

    /* Set port 2_0 to output */
    GPIOSetDir( 2, 0, 1 );

    while (1)                                /* Loop forever */
    {
        /* I/O configuration and LED setting pending. */
        if ( (timer32_0_counter > 0) && (timer32_0_counter <= 50) )
        {
            GPIOSetValue( 2, 0, 0 );
        }
        if ( (timer32_0_counter > 50) && (timer32_0_counter <= 100) )
        {
            GPIOSetValue( 2, 0, 1 );
        }
        else 
            while ( timer32_0_counter < 100 ); //wait for 
       timer32_0_counter = 0;
    }
}

A nice feature I like is that LPC Xpresso displays explanations about a function, ex. init_timer32 (the meaning of parameters, etc.) if you glide the mouse cursor over its name.

The IDE hides the internal registers

The ide does not hide anything: you can always code the mcu by writing to the registers.

However, in this case, they use a set of libraries from nxp to operate the peripherals. That's not unusual: ST has a set of its own libraries.

dhenry: The ide does not hide anything: you can always code the mcu by writing to the registers. However, in this case, they use a set of libraries from nxp to operate the peripherals. That's not unusual: ST has a set of its own libraries.

Without those libraries working with ARM peripherals is really not practical.

If indeed one have to write all these lines of code to initialize a timer I imagine that not many people would dare to attack ARMs.

/******************************************************************************
** Function name:       init_timer
**
** Descriptions:        Initialize timer, set timer interval, reset timer,
**                      install timer interrupt handler
**
** parameters:          timer number and timer interval
** Returned value:      None
** 
******************************************************************************/
void init_timer32(uint8_t timer_num, uint32_t TimerInterval) 
{
  if ( timer_num == 0 )
  {
    /* Some of the I/O pins need to be carefully planned if
    you use below module because JTAG and TIMER CAP/MAT pins are muxed. */
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<9);
    LPC_IOCON->PIO1_5 &= ~0x07;   /*  Timer0_32 I/O config */
    LPC_IOCON->PIO1_5 |= 0x02;    /* Timer0_32 CAP0 */
    LPC_IOCON->PIO1_6 &= ~0x07;
    LPC_IOCON->PIO1_6 |= 0x02;    /* Timer0_32 MAT0 */
    LPC_IOCON->PIO1_7 &= ~0x07;
    LPC_IOCON->PIO1_7 |= 0x02;    /* Timer0_32 MAT1 */
    LPC_IOCON->PIO0_1 &= ~0x07;   
    LPC_IOCON->PIO0_1 |= 0x02;    /* Timer0_32 MAT2 */
#ifdef __JTAG_DISABLED
    LPC_IOCON->JTAG_TDI_PIO0_11 &= ~0x07; 
    LPC_IOCON->JTAG_TDI_PIO0_11 |= 0x03;  /* Timer0_32 MAT3 */
#endif
#if CONFIG_TIMER32_DEFAULT_TIMER32_0_IRQHANDLER==1
    timer32_0_counter = 0;
    timer32_0_capture = 0;
#endif //TIMER32_0_DEFAULT_HANDLER
    LPC_TMR32B0->MR0 = TimerInterval;
#if TIMER_MATCH
    LPC_TMR32B0->EMR &= ~(0xFF<<4);
    LPC_TMR32B0->EMR |= ((0x3<<4)|(0x3<<6)|(0x3<<8)|(0x3<<10)); /* MR0/1/2/3 Toggle */
#else
    /* Capture 0 on rising edge, interrupt enable. */
    LPC_TMR32B0->CCR = (0x1<<0)|(0x1<<2);
#endif
    LPC_TMR32B0->MCR = 3;         /* Interrupt and Reset on MR0 */

#if CONFIG_TIMER32_DEFAULT_TIMER32_0_IRQHANDLER==1
    /* Enable the TIMER0 Interrupt */
    NVIC_EnableIRQ(TIMER_32_0_IRQn);
#endif
  }
  else if ( timer_num == 1 )
  {
    /* Some of the I/O pins need to be clearfully planned if
    you use below module because JTAG and TIMER CAP/MAT pins are muxed. */
    LPC_SYSCON->SYSAHBCLKCTRL |= (1<<10);
#ifdef __JTAG_DISABLED
    LPC_IOCON->JTAG_TMS_PIO1_0  &= ~0x07;    /*  Timer1_32 I/O config */
    LPC_IOCON->JTAG_TMS_PIO1_0  |= 0x03; /* Timer1_32 CAP0 */
    LPC_IOCON->JTAG_TDO_PIO1_1  &= ~0x07;    
    LPC_IOCON->JTAG_TDO_PIO1_1  |= 0x03; /* Timer1_32 MAT0 */
    LPC_IOCON->JTAG_nTRST_PIO1_2 &= ~0x07;
    LPC_IOCON->JTAG_nTRST_PIO1_2 |= 0x03; /* Timer1_32 MAT1 */
    LPC_IOCON->ARM_SWDIO_PIO1_3  &= ~0x07;
    LPC_IOCON->ARM_SWDIO_PIO1_3  |= 0x03;    /* Timer1_32 MAT2 */
#endif
    LPC_IOCON->PIO1_4 &= ~0x07;
    LPC_IOCON->PIO1_4 |= 0x02;        /* Timer0_32 MAT3 */

#if CONFIG_TIMER32_DEFAULT_TIMER32_1_IRQHANDLER==1
    timer32_1_counter = 0;
    timer32_1_capture = 0;
#endif //TIMER32_1_DEFAULT_HANDLER

    LPC_TMR32B1->MR0 = TimerInterval;
#if TIMER_MATCH
    LPC_TMR32B1->EMR &= ~(0xFF<<4);
    LPC_TMR32B1->EMR |= ((0x3<<4)|(0x3<<6)|(0x3<<8)|(0x3<<10)); /* MR0/1/2 Toggle */
#else
    /* Capture 0 on rising edge, interrupt enable. */
    LPC_TMR32B1->CCR = (0x1<<0)|(0x1<<2);
#endif
    LPC_TMR32B1->MCR = 3;         /* Interrupt and Reset on MR0 */

#if CONFIG_TIMER32_DEFAULT_TIMER32_1_IRQHANDLER==1
    /* Enable the TIMER1 Interrupt */
    NVIC_EnableIRQ(TIMER_32_1_IRQn);
#endif
  }
  return;
}

Maybe not all the code above is necessary for a particular application. I do not know.

There is another problem, sometimes you have to change the parameters of a timer on the run as fast as possible between two events that are 10-20 clock cycles apart. It seems like functions as "init_timer32" need more than 20 clk. ticks. Is there workarounds?

the LPC Xpresso IDE, designed for ARMs produced by NXP, seems quite easy to work with.

The LPC Xpresso IDE is fantastic to work with :)

When I first downloaded it I had a simple test program running in minutes. It's not as turnkey as Arduino but close.

Here's a version of blink that runs on the LPC1227

#include "LARD.h"

/*
  Blink
  Turns on an LED on for one second, then off for one second, repeatedly.

  This example code is in the public domain.
 */

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 7;    // different pin on the LPC Xpresso board

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     
}

// the loop routine runs over and over again forever:
void loop(void) {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second
}

Look familiar? :)


Rob