Choosing Embedded Processors for AltOS
When Bdale and I started building rocketry hardware together, we had already picked out a target processor, the TI cc1111. We picked that chip almost entirely based on the digital transceiver that is built in to the chip, and not because we had any particular love for the 8051 microcontroller. At that time, I'd seen people struggle with PIC processors, battle AVR to a draw and spend a lot of time trying to get various ARM processors running. So, the 8051 didn't seem all that far from normal, and the cc1111 implementation of it is pretty reasonable, including credible USB support and a built-in DMA engine.
Since those early days, we've gone on to build boards with a slightly wider range of processors:
- TI cc1111
- Atmel ATmega32U4
- Atmel ATiny85
- STMicroelectronics STM32L151/STM32L152
- NXP LPC11U14
Bdale thinks we should reduce the number of components we use to focus our efforts better. He's probably right, but I have to admit that I've had way too much fun getting each of these chips running.
I thought I'd spend a bit of time describing our general process for selecting a new CPU.
Free software. I'm long past the age at which I trust hardware vendors to deliver credible binary software. If you want me to use your silicon, make sure the tools required to use it are all free software.
Debian support required. Bdale and I do everything on Debian, so any processor we use needs to have tools that run under Debian. We're more than willing to package software for Debian, so if it's just generic Linux-compatible free software, that's fine.
Built-in USB. Everything we build needs to talk to a computer for configuration and data download. Don't even think of asking me to attach another chip for USB support. Ok, so the ATtiny85 doesn't qualify here, and that project does use an external chip for USB which is connected to the ATtiny85 through an LED and phototransistor. I was excited when TI came out with the CC340 chips because the MSP430 is a much nicer CPU than the 8051. But, they still haven't added USB. If I'm going to add another chip for USB, it'll be a CPU anyways, at which point I'll use a stand-alone RF chip.
Cheap developer boards. TI sells a tiny little cc1111 developer board; STmicroelectronics and NXP both sell boards that include a programmer and a target CPU for prototyping software. And, there are a million "Arduino" clones with various Atmel processors on them. Cheap means I can buy them without thinking too hard; having a built-in programmer means that early OS development can be done without first having to figure out how to wire up a programmer.
Probably 32 bits, probably an ARM. Yeah, the cc1111 and Atmel processors were fun to bring up, but I'm pretty much over the 8-bit microcontroller now. ARM processors are far more sophisticated in terms of power management and built-in device capability, plus they're a ton faster at doing any math. The ATtiny85 remains an exception here; it's smaller than any ARM I can get, and so it's still useful for projects too small for an ARM.
Available in small quantities from a reasonable on-line retailer like Digikey, Mouser or even Avnet Express. I'd love to try out the new low-cost STM32L100 parts, but the only one available is the largest one in the 64LQFP package, and I really don't need that many pins for most products.
CC1111 involved a lot of software hacking
The 8051 processor in the CC1111 is very well documented, including the two-wire debugging interface. What was missing was a canned solution for programming and debugging the chip from Debian. However, with sufficient motivation and accurate docs, I was able to create a programmer from a USB device with a couple of GPIOs and a lot of ugly software on Linux. That sufficed to get the USB stack limping along, at which point I wrote a much faster programmer that ran on the cc1111 itself and could program another cc1111.
With that, I created an assembly-level debugger that could be hooked to the existing SDCC source level debugger and had a full source-level debugging environment for the 8051. This turned out to be way better than what I could get on the Atmel processors, where I've got a program loader and a whole lot of printf debugging.
STM has been great
The STM32L-Discovery board has a standard STM debugging setup for the Cortex SWD interface right on the same board as a target CPU. That made for completely self-contained development, with no jumper wires (a first for me, for sure). There's free software, stlink which can talk over the debugger USB connection to drive the SWD interface. This is sufficient to flash and debug applications using GDB.
Of course, GCC supports ARM quite well; the only hard part was figuring out what to do for a C library. I settled on pdclib, which is at least easy to understand, if not highly optimized for ARM.
We've built a ton of boards with the STM32L151 and STM32L152; at this point I'm pretty darn comfortable with the architecture and our tool chain.
Adventures with NXP
The NXP LPC11U14 is a very different beast. I'm using this because:
It's small (5mm x 5mm)
It's cheap ($1.48 q100)
The LPCXpresso board looks much like the STM32L-Discovery, with a debugger interface wired to the CPU directly on the board. However, I haven't found free software tools to drive this programmer; all I've found are binary-only tools from NXP. No thanks.
Fortunately, the LPC11U14 uses exactly the same SWD interface as the STM32L, so I was able to sever the link between the programmer and the target on the LPCXpresso board and hook the target to an ST-Link device (either the one on the STM32L-Discovery board, or the new stand-along programming dongle I bought). With that, I wrote an openocd script to talk to the LPC11U14 and was in business.
What I found in the NXP processor was a bit disturbing though -- there's a mask ROM that contains a boot loader, which always runs when the chip starts, and a bunch of utility code, including the only documented interface to programming the flash memory. I cannot fathom why anyone thought this was a good idea -- I don't want a BIOS in my embedded CPU, thankyouverymuch; I'd really like my code to be the first instructions executed by the CPU. And, any embedded developer is more than capable of programming flash using a register specification, and calling some random embedded code in ROM from the middle of my operating system is more than a bit scary.
NXP could do two simple things to make me like their parts a whole lot more:
Publish the programmer source code. The programming dongle is a tool for selling your silicon, not a separate revenue stream. Publish the source under a free software license (GPL recommended, of course). We'll take it, make it better, and ensure that you get the changes back to help your other customers. It's a win-win plan.
Document the flash programming registers. Yeah, I could probably disassemble the mask-rom bits that are on the chip, but I have better things to do with my time. Heck, go wild and document any other hidden bits in the silicon. Again, we're embedded developers, we don't like magic hardware hidden from view any more than PC developers like the BIOS and SMM.
Right now, I'm hoping the STM32L100C6 parts become available in small quantities so I can try them out; they promise to be as cheap as the LPC11U14, but are better supported by free software and offer more complete hardware documentation. Yeah, they're a bit larger; that will probably be annoying.