One interesting fact that I’ve noticed about embedded software development is that development processes and techniques tend to lag the general software industry. When I first started to write embedded software back in the late 1990’s, the focus seemed to be on moving away from writing assembly language and adopting C along with the best practices that went with it. Applications were monolithic beasts will little to no organization. If you look at the goals for the software industry at that time, there was a big push into object-oriented design, reuse and scalability for applications. Even today, the general software industry has adopted build pipelines, continuous integration and test harnesses while the general embedded industry seems to barely realize that these processes exist (at least among companies with market caps well below a billion dollars). Let’s examine how embedded developers can create their own build pipelines.
A Build Pipeline Overview
Developing a more sophisticated build pipeline can have dramatic effects on the embedded software development life cycle. For example, over the lifetime for a software product, a well thought out build pipeline can:
- Improve software quality
- Decrease the time spent debugging
- Decrease project costs
- Enhance the ability to meet deadlines
- Simplify the software deployment process
A software build pipeline is nothing more than the process and tools that are used to manage, test and deploy an application. For example, embedded software developers will typically commit their software to a revision control system, manually test their code and then issue an application image that can be manually deployed to their system. This build pipeline is very traditional, but it lacks the sophistication and automation that a modern build pipeline can offer.
A more modern build pipeline that embedded developers can leverage consists of four stages that can be completely automated and manually kicked off. These stages include:
- Committing software (The manual trigger)
- Build and Analysis (Automated)
- Test and Reporting (Automated)
- Deployment (Automated or manual)
Each stage has its own process and tools that are associated with it, but the last three stages can all be done as part of a continuous integration / continuous deployment process (CI/CD). The idea behind CI/CD is that a developer can commit their code to the repository at the end of the day which then kicks off a series of automated build, metric and tests that can provide a developer feedback the next day or if everything goes well automatically deploy the firmware to devices in the field. An overview for this process and the general tools involved can be seen in the figure below:
Notice that this diagram consists of two halves, an upper half that describes the process that is being followed and bottom half that describes the tools that are involved. There is also a barrier between the test and report stage and the deployment phase. Software should only be deployed if it has passed all the build and analysis criteria in addition to all the test cases. If any of the build or tests cases create warnings or errors, this feedback can be reported to the developer which triggers updates to the software and then a new commit which then kick-off the automated stages again.
Enhancing the Embedded Software Build Pipeline
Creating an automated build pipeline is not going to happen overnight. It takes time to research the right tools, implement them, test the process and then train the engineers on how to use it properly. As I mentioned before, the benefits can easily outweigh those costs. So how does one go about enhancing their software build pipeline?
First, it’s important to make sure that you have a robust revision control process in place. Most teams that I talk with now-a-days use version control. This is a great improvement from just a few years ago, but many teams I talk to will mention that they only commit code once a week or even less than that. I believe that software should be developed in small enough chunks that code is committed at least once a day if not several times a day. Doing so will then allow the pipeline to provide feedback much more frequently.
Second, you need to implement a continuous integration server. One of the most popular ones out there that can also be used by embedded software developers is Jenkins (although there are others out there). A continuous integration server is designed to automate building and deploying software and you’ll find that there are often many integrations that can be used to automate nearly anything you might want.
Third, you’ll want to make sure that your compiler and static code analysis tools can be executed through command line interface or that they include plug-ins for your continuous integration server. What if you don’t have a static code analysis tool? Static code analysis is an important step in the software development process and now is a great time to find one.
Fourth, and perhaps the most difficult is to select a test harness and integrate it into the development process. Automated tests are great for regression testing and verifying software, but they do require that the tests be designed and implemented as part of the development process. Automating tests that don’t test the software fully can leave holes in the software and result in a deployment that is lower quality than one would expect. For this reason, test harnesses should be developed from the beginning if possible and integrated in a process like test driven development (TDD).
Finally, you don’t have to do all of this at once. Enhancing the build pipeline can be done in steps. Start with each of the above steps one at a time and build out your tool chains and processes so that they are rock solid. Once each phase is rock solid, add to it until you eventually have a modern build pipeline that fully automates your build, testing and deployment.
Modernizing the embedded software build pipeline can generate a lot of benefits to the development team and the business in general. Just like with any process though, properly building up a modern build pipeline for embedded systems development requires a time and budget investment in order to architect and implement the pipeline. Given the volatile environment that I see so many development teams in, a modern build pipeline can help to illuminate the path forward, monitor software quality and even simplify software updates.