Why globals will make you miserable

Instead of moving data around through functions calls -- which are (relatively) easy to trace -- globals are a kind of wormhole from one part of the application to the next. A wormhole where anything can jump in and change the behavior of the application.

Read More

A maturity test for firmware organizations

Over the years I've worked in and with many different firmware organizations. In my experience most people are really trying to do their best but I see many struggling with the same, common problems of organizational maturity.

When an organization is mature it makes disciplined use of best practices and tools to regularly and continuously deliver high quality firmware.

When an organization is immature, things are done in an ad hoc (often reactionary) way. Successful results are not easily repeatable and it is often the responsibility of just one or two individuals to try to hold it all together.

Read More

Simple metrics for embedded software

How do you know when code is good or bad? Or complicated or simple? Chances are you know it when you see it, but that isn’t very quantifiable.

I find that some simple software metrics can help with this. In particular, metrics can help identify the most complicated areas of the code. This is useful in a few different situations.

Read More

Jenkins: Your code butler

Before I started working with Jenkins, I had heard about it — and I knew that people used it to do something useful. However, I didn't really understand what Jenkins does or how it works.

Also, there is quite a bit of Jenkins documentation around but I've found that a lot of is out-of-date and didn't apply to me and my needs for embedded software development.

In this article I'll explain a bit about what Jenkins does, how it works and why you might want to think about using it — particularly for your embedded software projects.

Read More

Simple embedded build environments with Docker

When building embedded systems, there are typically at least a few specialized tools required. This includes things like the build tool, cross-compiler, unit test tools or documentation generators.

Getting all of these things set up on your machine can be tedious. And then when it's time to bring someone else on to the project, setting up the build environment just takes extra time.

Read More

7 tips for adding unit tests to existing firmware

I've written before about the how to configure Ceedling to run unit tests with an existing project. But after you have your unit test tools set up, it can still be difficult to figure out how to start writing tests. Code that hasn't been designed to be unit tested can be especially difficult. Here a few tips to help you out.

Read More

Unit testing with asserts

Assert statements are a great tool for programming defensively. This is especially true in embedded systems where we don't typically have a lot of user interface to help our users figure out an error. Often it's better to crash or reset the application programmatically than risk executing the code in and undefined state. But how do you write unit tests for code that can assert?

Read More

Avoiding mocks by enqueuing events

Including mocks in your tests means that those tests know a lot about the internal implementation of the unit under test. Make a change in the interface of any mocked module, and you not only drive changes in every caller of that interface, you create a cascading series of changes in the tests for each of those callers as well.

Because tests that rely on mocks are prone to breakage, or brittle, they're an active disincentive for making changes to existing code. You're forced to either update the tests with every change you make, allow the tests to break and lose the benefits of unit testing, or just avoid making changes to the code.

Read More

Practice writing code without the hardware

For most of my time as an embedded software developer, I almost exclusively wrote code that was going to be run on some microcontroller. I'd fire up the IDE, crank out some code, download (this often took a couple minutes) an run. Then I'd somehow try to figure out if what I had written was correct.

Read More

Event-based interfaces for testability

Unit testing is great for verifying the behavior of individual modules, but how do you put those modules together in a way that makes things testable?

One of the most useful ways I've found to do this is to think about the system in terms of events.

Read More

Getting Started with Ceedling [3/3] - Building a release binary

This is the third of a three video series to show how to quickly get started with Ceedling for test driven development in C -- by test driving a simple "FizzBuzz" example.

In the previous video we test drove a simple example -- writing the tests along with the code.

In this video we look at how to use Ceedling to build a release binary (it's pretty easy!).

In this example we used native GCC to compile for our host platform, but you can could the release_compiler setting in the project.yml file to compile for whatever target you want.

I hope you enjoyed this quick intoduction to test-driving embedded software with Ceedling. If you're new to unit testing or test driven developement, Ceedling is a really great way to get started. In just a few minutes we were able to create a new project and develop a high quality, well-tested FizzBuzz implementation.

Getting Started with Ceedling [1/3] - Creating a new project

This is the first of a three video series to show how to quickly get started with Ceedling, by test driving a simple "FizzBuzz" example.

In this video we introduce our example problem, create Ceedling project, create a source code module (easily using Ceedling!) and look at how to run the tests.

Read More

Changes to Ceedling - no more rake

Have you tried to use Ceedling recently, but got this error when you tried to run rake?

No Rakefile found (looking for: rakefile, Rakefile, rakefile.rb, Rakefile.rb)
Read More

Unit testing with flash (EEPROM)

Do your embedded applications ever save any data to flash memory (aka EEPROM)? This where you typically store non-volatile information that needs to preserved if the device is powered down.

This sort of thing is tough to test in the traditional way -- by loading code onto the target and running it -- because it's hard to set and _re-set_ the data in flash for testing. It can also be harder to inspect the data when it's in flash memory.

Read More

Designing firmware from the inside out

I don't know about you, but a very natural way for me to think about designing embedded software is from the "outside in". I've been thinking about this a bit recently, and I'm not so sure that's the best approach.

Read More

When you want to unit test... abstract the hardware

So you write embedded software in C and you think that unit testing might help you do it better. You already know about creating well-defined software modules and how this makes it easier to write unit tests. But what else can you do to make these modules easier to test? What are some more coding patterns that make unit testing easier?

Read More