Why Code Reuse Matters

By Jacob Beningo

Over the past several decades, embedded systems have steadily increased in complexity. The internet’s birth has only accelerated the process as our society has been in a race to connect nearly every device imaginable. Systems that were once simple and stand-alone must now connect through the internet in a secure and fail-safe manner in order to stream critical information up into the cloud. Complexity and features are increasing at an exponential rate with each device generation forcing engineers to reevaluate how to successfully develop embedded software within the allotted time frame and budget.

The increased demand for product features along with the need to connect systems to the internet has dramatically increased the amount of software that needs to be developed to launch a product. While software complexity and features have been increasing, the time available to develop a product has for the most part remained constant with a negligible increase in development time (2 weeks in 5 years) as can be seen in Figure 1.

Figure 1 – Average Firmware Project Development Time (in months)

In order to meet project timelines, developers are forced to either purchase commercial off-the-shelf (COTS) software that can decrease their development time, or they need to reuse as much code as possible from previous projects.

Firmware for microcontrollers has conventionally been developed for a specific application using functional design methodologies (if any methodology has been used at all) that typically tie the low-level hardware directly into the application code, making the software difficult, if not impossible to reuse and port on the same hardware architectures—let alone reuse on a different architecture. The primary driving factor behind developing throw-away firmware has been the resource constrained nature many embedded products exhibit. Microcontrollers with RAM greater than a few kilobytes and flash sizes greater than 16 kB were once expensive and could not be designed into a product without destroying any hope for making a profit. Embedded software developers did not have large memories or powerful processors to work with, which prevented modern software design techniques from being used in application development.

Modern microcontrollers are beginning to change the game. A typical low end ARM Cortex-M microcontroller now costs just a few U.S. dollars and offers at a minimum 16 kB of RAM and 64 kB of flash. The dramatic cost decreases in memory, larger memory availability and more efficient CPU architectures are removing the resource constrained nature that firmware developers have been stuck with. The result is developers can now start utilizing design methods that decouple the application code from the hardware and allow a radical increase in code reuse.

Portable Firmware

Firmware developed today is written in a rather archaic manner. Each product development cycle results in limited to no code reuse with reinvention being a major theme amongst development teams. A simple example is when development teams refuse to use an available real-time operating system (RTOS) and instead develop their own in-house scheduler. Beyond wanting to build their own custom scheduler, there are two primary examples that demonstrate the issue with reinvention.

First, nearly every development team writes their own drivers, because microcontroller vendors provide only example code and not production ready drivers. Examples provide a great jump-start to understanding the microcontroller peripherals, but still require a significant time investment to get a production intent system. There could be a hundred companies using the exact same microcontroller, and each and every one will waste as much as thirty percent or more development time getting their microcontroller drivers written and integrated with their middleware! I have seen this happen repeatedly amongst my client base and heard numerous corroborating stories from the hundreds of engineers I interact with on a yearly basis.

Second, there are so many features that need to be packed into a product, and with a typical design cycle being twelve months1, developers don’t take the time to properly architect their systems for reuse. High-level application code becomes tightly coupled to low-level microcontroller code, which makes separating, reusing or porting the application code costly, time consuming and buggy. The end result is developers just start from scratch every time.

In order to keep up with the rapid development pace in today’s design cycles, developers need to be highly skilled in developing portable firmware. Portable firmware is embedded software that is designed to run on more than one microcontroller or processor architecture with little to no modification. Writing firmware that can be ported from one microcontroller architecture to the next has many direct advantages, such as:

  • Decreasing time-to-market by not having to reinvent the wheel (which can be time consuming)
  • Decreasing project costs by leveraging existing components and libraries
  • Improved product quality through using proven and continuously tested software

Portable firmware also has several indirect advantages many teams overlook, but can far outweigh the direct benefits, such as:

  • More time in the development cycle to focus on product innovation and differentiation
  • Decreased team stress levels due to limiting how much total code needs to be developed (happy, relaxed engineers are more innovative and efficient)
  • Organized and well documented code that can make porting and maintenance easier and more cost effective

Using portable and reusable code can result in some very fast and amazing results, as seen in the case study, “Firmware Development for a Smart Solar Panel,” but there are also a few disadvantages. The disadvantages are related to upfront time and effort such as:

  • The software architecture needing to be well thought through 
  • Understanding potential architectural differences between microcontrollers
  • Developing regression tests to ensure porting is successful
  • Selecting real-time languages and understanding their interoperability or lack thereof
  • Experienced and high-skilled engineers being available to develop a portable and scalable architecture

For development teams to successfully enjoy the benefits of portable code use, extra time and money needs to be spent up front. However, after the initial investment, development cycles have a jump start to potentially decrease development time by months versus the traditional embedded software design cycle. The long-term benefits and cost savings usually overshadow the upfront design costs along with the potential to speed up the development schedule.

Developing firmware with the intent to reuse also means that developers may be stuck with a single programming language. How does one choose a language for software that may stick around for a decade or longer? Using a single programming language is not a major concern in embedded software development as one might initially think. The most popular embedded language, ANSI-C, was developed in 1972 and has proven to be nearly impossible to usurp. Figure 2 shows the popularity of programming languages, for all uses and applications, dating back to 2002. Despite advances in computer science and the development of object-oriented programming languages, C has remained very popular as a general language and is heavily entrenched in embedded software.


Figure 2 – TIOBE Computer Programming Index

The C programming languages’ popularity and steady use for decades doesn’t appear to be changing anytime soon. When and if the Internet of Things (IoT) begins to gain momentum, C may even begin to grow in its use and popularity as millions of devices are developed and deployed using it. Developing portable and reusable software becomes a viable option when one considers the steady and near constant use that the C language has enjoyed in industry for developing embedded systems. When a development team considers the timelines, feature needs and limited budgets for the product development cycle, developing portable code should be considered a mandatory requirement.

The decision to develop portable firmware should not be taken lightly. In order to develop truly portable and reusable firmware, there are a few characteristics that a developer should review and make sure that the firmware will exhibit. First, the software needs to be modular. Writing an application that exists in a single source file is not an option (yes, I still see this done even in 2018). The software needs to be broken up into manageable pieces with minimal dependencies between modules and similar functions being grouped together.

About the Author

Jacob Beningo​​​​​​​ is an embedded software consultant with over 15 years of experience in microcontroller based real-time embedded systems. After spending over ten years designing embedded systems for automotive,defense and space industries, Jacob founded Beningo Embedded Group in 2009. Jacob has worked with clients in more than a dozen countries to dramatically transform their businesses by improving product quality, cost and time to market. He has published more than 200 articles on embedded software development techniques, is a sought-after speaker and technical trainer who holds three degrees which include a Masters of Engineering from the University of Michigan.  Jacob is an avid writer, trainer, consultant and entrepreneur who transforms the complex into simple and understandable concepts that accelerate technological innovation. 

Want more from Jacob? Pick up Reusable Firmware Development, now available on Apress.com.