Comparing Microcontroller Package Sizes

When building electronic hardware prototypes, one major source of frustration for circuit designers is the difference in chip package sizes, even when they are identically named.

Each integrated-circuit manufacturer usually has slightly different specifications for their version of SO-8, TSSOP-20, QFN32, LQFP-64, and so on.

To get some clarity on the topic, and to see how each manufacturer’s dimensions could differ, I compiled together a bunch of excerpts from various publicly-available packaging datasheets.

I wanted to put these excerpts all in one place, so that I could visually and numerically check the differences (something humans are still good at, take that machines!)

So without further ado, please find the results of the survey at this Github repo, and please feel to either comment here or in the issues there if you have any suggestions. Pull requests are also always welcome.

That Time Of Year Again, 2018 Edition

It’s that time of year again where I start planning things for 2018.

Every year, I hack together a simple Year-at-a-Glance calendar, in the German style (but without Kalenderwochen).

— It fits on two double-sided A4 or letter-sized sheets of paper.
— It doesn’t have any stupid inspirational quotes.
— It doesn’t violate any of Edward Tufte’s rules for honest information design.
— It doesn’t win any awards for originality.

Here’s my 2018 Year-at-a-Glance Calendar (A4-sized)

Here’s what it looks like on A4 paper, easy to use, easy to carry around:

Every year I hack up a 2-page calendar, which is easy to carry around and helps me keep track of things. I am not Franklin Covey, I am a highly-effective person, I hate carrying useless paper around.

Here’s the 2018 Year-at-a-Glance Calendar (Letter-sized).

With a double-sided printer, print pages 1 and 4 first, then 2 and 3; doing this means you can look at 6 months at a time.

Embedded C++11 FTW

This is a rant.

Need Moar C++11 In Embedded Software

We really need to embrace the use of C++11 in embedded software development with proper, type-safe, interrupt-driven events and callbacks, and we need to do this as natively as possible.

Since IAR finally released a C++11-compatible compiler this year, it should be the goal to actually make use of C++11 now that all of the “Big 3” (IAR, Keil, and GCC) support it.

(Shame on you, IAR, for taking this long to make this possible.)

I’d really like to see a clean C++ API on embedded chips taking advantage of C++11 features, running as close to the metal as possible.

mbed is close, but I’ve definitely seen many odd behaviors where it wraps the low level APIs provided by vendors and ends up blocking, crashing, or doing other stupid things that aren’t anticipated in the mbed API.

Which leads me to my next point.

Procedural, Embedded C With Blocking APIs Needs To Die

We should stop writing procedural C APIs for microcontrollers. Apple’s IOKit object-oriented driver architecture shows us a better way, and it was invented decades ago, even if not that many people ended up using it.

We should also stop using blocking APIs on as many microcontrollers as possible.

The bare-metal HALs and SDKs that offer these types of code examples should remove them because they tend to encourage bad programming practices, even when an RTOS is in use (because most microcontroller RTOSes don’t tend to properly handle event-driven wakeup on I/O and leave this to the user anyways).

I’ve seen too many examples of code where reading a serial port involves:

  1. Setting up the serial port read.
  2. Running a while() loop.
  3. Waiting until the serial port indicates that a single byte of data is available.
  4. Exiting the loop and reading the byte.
  5. Going back to step 1.

Think about this: In one millisecond, a 12MHz processor can run 12000 instructions, more or less. Let’s say it takes the unskilled program 20 instructions to set up the registers to receive a byte on the serial port and enter a while loop.

The processor will busy-wait for 11980 cycles, consuming 100% power. This is idiotic.

The primary benefit of thinking in events and callbacks is power-related, we really should avoid sleeps that are not real sleeps.

It kills me to see people still using superloops without proper sleep / WFI / WFE calls. Pretty much all Arduino code falls into this category.

My experience with mbed is also that its power consumption is quite atrocious. It insanely does not yet have a tickless scheduler as part of its RTX RTOS codebase, making it essentially useless for battery-powered devices.

Goals Hardware Manufacturers Should Pursue

Every hardware manufacturer has something that slightly odd about its software offerings. I never understood this. NXP has LPCOpen, which is a set of C SDKs for their LPC microcontrollers, but each chip has its own SDK ZIPfile blob which may or may not have a consistent API with other LPC microcontrollers. STM has its STMCube software which is in a similar position. Atmel and Atmel Studio is pretty good, but their chips often seem to be pretty expensive and they just automate away some of these issues via clever IDE wizards. Cypress and TI have decent hardware, but the PSoC C APIs never seemed all that easy to get around and I have no idea who pays for Code Composer Studio.

NXP has a decent set of development tools, STM does not make its own (seriously, WTF), neither does Nordic Semiconductor (who just leaves you to puzzle through their horrendously-architected nRF5 SDK and fight multiple times with various not-well-documented headers just to get printf with RTT working and to struggle with integrating multiple projects together to get the various types of hardware working together).

Silicon Labs has a fantastic development environment, with amazing debug, energy measurement (AEM is amazing), and low-power state management (setup EM4!) but no one really uses them. So sad.

But at the end of the day, I feel like I’m always porting, even between chips in the same family, from the same company.

So here’s what I wish these damned hardware manufacturers would actually do:

  • No more crappy SDKs with slight differences in APIs and implementations per chip.
  • No more wrapping crappy, blocking C APIs.
  • No more always needing to pass a pointer to a C struct as the first parameter of an API call.
  • No more writing delay loops that are while(delay) { NOP() }.
  • No more abusing the C preprocessor to generate or to validate code.
  • No more needing to copy and paste source files with minor modifications to use a second instance of hardware.
  • No more violations of Don’t Repeat Yourself (DRY), where a chip feature is controlled by a preprocessor flag in an sdk_config.h file, and by a statically-defined variable, and by a variable in a configuration struct pointer somewhere. (I’m looking at you, Nordic Semiconductor.)
  • No more writing code without measuring power consumption in your labs.
  • Use decent, modern, C++11 with Dependency Injection and well-architected objects that receive base addresses as parameters from your CMSIS microprocessor definitions to represent the peripherals in your microcontrollers. No more hard-to-change dependencies on your company’s CMSIS definitions, please!

Why is this so hard to get right? Baseline functionality should have me doing less plumbing and more coding on my own application and it is high time, in 2017, to get this right.

The rest of the programming world moved to object orientation years ago, and the resources available on today’s microcontrollers should allow us to place greater value on programmer time and programmer effectiveness.

We need to stop chasing the smallest possible firmware and start chasing the most bang-per-line-of-code and bang-per-minute-of-programmer-time.

Postscript

Whenever I see the code example:

I want to punch someone at Arduino for wasting so much electricity.