The blog has been pretty quiet lately, but development on the LPC11U24/LPC11U37/LPC1347 Code Base is still very active. There are some known bugs and a lot of gaps to fill in, but things are coming together wirh USB support including multiple classes, a growing driver library, and plenty of boring plumbing code to get the essentials out of the way so you don't have to.

Working on a project yourself with the LPC11U24/LPC11U37/LPC1347? We'd be glad to have some more people kick the tires in on the code base, since more eyeballs is almost always a good thing.

Some of the current 'outstanding' issues are:

- The sensor abstraction layer is a move in the right direction, making it easy to switch similar sensors in an out and get sensible SI units out, but the API still need some thought, and there's a need for a lot of helper code for common sensor types. For example, some helper functions for pressure sensors were recently added to calculate altitude (etc.), but similar code needs to be added for gyroscopes, accelerometers, magnetometers, color sensors, etc., to make it easier for people to perform useful tasks with the raw sensor data. This API and abstraction layer is something sorely missing from most embedded projects I've seen, and if you have anything to contribute here it's bound to have a lot of benefit to a wide variety of people since any code added here is very easily ported to other platforms and projects.

I finally found a few minutes to test the latest PCBs for the LPC11U37/LPC1347 and I'm pretty happy with both the test HW and the code base itself. I think it's a significant improvement over any of the previous code bases posted here, and I think it should be a good starting point for projects moving forward.

Overall, I'm extremely happy with the flexibility offered by the (essentially) pin and register compatible LPC11U24, LPC11U37 and LPC1347. This trio leaves a lot of room to maneuver optimizing for flash size, performance, price or package size with almost no extra SW development effort. Making a code base that makes that as painless as possible took a bit of effort, but at least it's a one time expenditure.

I don't want to post many details until the code base is ready to go live, but I think it's all come together pretty well so far, and I hope it will be a decent starting point for a lot of people. It'll definitely make things easier here to get prototypes off the ground in days or weeks rather than weeks or months.

I was surprised by the interest in the RF board I posted about earlier, so I figured I'd post a small update on the progress. I've been dividing my time between the 1347 and 11U37, trying to spend equal amounts of time with both to make sure that the codebase easily works with either chip out of the box.

Initial Opinions

While the migration from the 1114 and 1343 has been generally pretty smooth, I did have to pull out the UM to understand the new (and more flexible) GPIO blocks, the 12-bit ADC (1347 only), get the EEPROM working, etc., but nothing too dramatic so far. SSP, I2C, etc., are the same as always since they're basically just licensed IP blocks from ARM.

Overall, I'm exceptionally happy with both chips and the 1347 is everything I wish the 1343 would have been ... though I'd be happier if the distributor pricing was a bit lower.

There were some hiccups creating a common LPC11U37 + LPC1347 codebase because of a few regrettable naming differences in the CMSIS libraries from NXP. The UART IRQ handler is defined as "USART_IRQHandler" for the 1347, for example, but "UART_IRQHandler" for the 11U37, so to have a single codebase for either chip I end up with horribly ugly cludges like this:

Similar situation for "FLEX_INT0_IRQHandler" (11U37) versus "PIN_INT0_IRQHandler" (LPC1347), and in a number of other places, but these are relatively easy to locate and fix. The worst so far was with GPIO, though, where some of the register names in the core header file were different, as seen below (used to set up a GPIO interrupt):

LPC_SYSCON->PINTSEL (LPC11U37) is probably the better name because it better represents what this register is doing (GPIO Pin Interrupt Select), but curiously the LPC1347 user manual also lists this value as PINTSEL (not PINSEL), so it's likely just an unfortunate typo that people are stuck with now since they can't really change it. It's also a rather misleading name if you've ever done any ARM7 development with the older LPC2000 series since 'PINSEL' performed a very different and common function. But hey ... such is life, and at least they give you something to start with these days, and mistakes happen. It just struck me as unfortunate that for chips that are almost identical on a peripheral level, and that can be dropped in with 99% SW and HW compatability that the major obstacle would be something as trivial as inconsistent naming across families.

Low Power

The power numbers were higher in the sleep modes than I expected, and I'm still working on this and certain it's my fault. I trust the numbers in the datasheet, and I'm pretty confident in my HW after two revisions for power, but I just need to find the secret sauce in the firmware. This also took quite a while with the 1114. I'm currently at 30µA in power down running at 2.2V which is identical to what I got on some similar LPC1114 wireless boards ... but I should be able to go much lower than that (ideally under 10µA total). There were a lot of gotchas trying to isolate those microamps, though, including on less than obvious one.

The 1347 and 11U37 families now include a (welcome) QFP64 package option with more IO pins (great for large LCDs, etc.). Inside, though, all of these chips almost certainly use the same die, and they just selectively bond out the required pins for the package -- QFN33, QFP48, QFP64, etc. The 'gotcha' was that on a QFN33 or QFN48 package, those extra GPIO pins still exist on the die, and if you go into a low power/sleep mode without taking them into consideration you'll be drawing several hundred µA more than you should be due to the pullups and default pin state. You need to explicitly setup the unbonded pins to output and GND as well, and put the pullups in an appropriate state AND be sure to disable the analog mode on unbonded pins with an ADC option. I didn't think of that at first, but it got me from 400µA to around 30µA, using code similar to the following (I explicitly set every pin on startup now):

I caught that thanks to Embedded Artist's excellent Oryx board (thanks for the inadvertent heads-up Anders!).

CodeBase Improvements

Since I'm starting a new code base I took the opportunity to try to improve on previous efforts, and I think the current version has a better organisation, and I've improved some things I really didn't like in the previous 1343 and 1114 libraries.

I've improved the CLI a bit (better organisation, etc.)

I added a very preliminary mechanism to localise/translate text so that you can support multiple languages in one application (though this really needs more attention and testing), which is a must outside the US but not something I see done a lot in open source embedded projects

I've start working on a global error handling mechanism, though at the moment it's just shared error codes and better error handling and checking in I2C

I also added a board-specific init sequence and file in addition to the shared systemInit() function so that board specific code can be better seperated, though this still needs some thought.

Overall, I'm happier with this that the 1343 code base, but it still needs some thought and effort and isn't ready for the real world yet. The biggest change is that I've decided not to swim against the current and just use CMSIS from the start. When I start with the 1343 and 1114 codebase CMSIS was brand new, and nothing existed for these chips anyway, so I just did what I always did and pulled out the UM and started making my own flat header file. I still prefer this approach, but I just don't have the time to dedicate to doing this well these days -- there are weeks and weeks of effort in that approach -- so I'm using the default NXP peripheral drivers and CMSIS 3 code, making changes where appropriate so that the code works with both the 11U37 and 1347 just changing a single define in projectconfig.h. This isn't an ideal solution for me, and I may go back and rewrite all those peripheral drivers myself ... but for now this lets me get started quickly and developping the HW, etc.

When Will it be Available?

Not sure, and no promises. I don't want to publish it before it's in reasonably good shape and I'm happy with the basic organisation, and since this is just an unpaid weekend project I can't work on it much during the week ... but hopefully in a month or so I'll publish an initial version along with the HW files for a first wireless board and maybe put together a simple MCU-only board for people no interested in RF but who want to use the codebase.

The ToDo list is still pretty big. I haven't touched USB yet, the antenna on the current boards desperately needs to be properly measured and either revised or tuned, and I have to add in ADC support and a few key peripherals I haven't gotten to yet like the timers. I think the worst is done, though, and things are coming together nicely ... just never enough hours in the week to really wrap it up.

I'll definitely be moving to the 1347 and 11U37 combination in the future, though, and they're great little chips that should be much more flexible than the earlier 1343 and 1114. I'll probably move away from the 1343 entirely, but will maintain the 1114 code since it's still ridiculously cheap, there's a DIP version of it, and the new 1115 with 64KB flash breathes some extra life into it.

I've been looking for an excuse to do something with the LPC1347 for a while, and I ended up recycling a lot of previous work, combining a number of lessons learned into a single four-layer board that should let me test a number of power supply and project scenarios. I kept the board fairly basic, just a microSD card for datalogging, USB, and SWD connector, and reset/ISP buttons. There's on on-board user-selectable 3.3V/2.2V linear regulator (TPS780), but it can be bypassed and you can power the board from another source for flexible power input and current control. It's designed to fit in these inexpensive weather-proof cases with a transparent top for a small solar cell, but should be easy to adapt to another enclosure.

I kept the RF section completely seperate as well so that I can change to another chip if required. The current board uses an AT86RF212 (868/915MHz 802.15.4), and I can drop in an AT86RF230/231 (2.4GHz) with a simple adjustment to the transmission line width for impedance matching ... but I also whipped up a schematic for the nRF8001 for Bluetooth LE that I might test down the road. The way the board is now I can make seperate 2-layer add-on PCBs for various power and sensor inputs, sticking to one common footprint and header to evaluate things more quickly.

One benefit of the ARM Cortex M3 based LPC1347 is that it's pin compatible with the Cortex M0 LPC11U24 and Cortex M0 LPC11U37. This gives me a decent selection of options between price/performance/flash size on a single PCB, with minimal SW changes, all of which have excellent power numbers:

the LPC1347 is a high-performance chip with a decent amount of flash - 72MHz M3, 64kB Flash, 8+2+2kB SRAM and 12-bit ADC

It's just a personal, weekend project, but I'll blog some more about this board when I get the PCBs in later this week since it was a big (if expensive) learning experience. Here's some photos of the PCB being manufactured, though, if you've never seen the different steps of the process (courtesy PCB Pool):