A Classic Paper on Designing Hardware Abstractions for Embedded Systems

The central theme in our Practical Architecture series is exploring ways that we can design our systems to reduce the costs of change. We’ve worked with many teams who are asked to change the processor or RTOS, only to realize that their entire program must be rewritten because SDK functions are used throughout the code base. Even simpler cases, such as replacing an end-of-life component with a newer version or supporting multiple component options, can trigger unexpectedly lengthy rework efforts.

This is not a new challenge. Here’s a quote from a paper published in 1981 (emphasis mine):

It is a common but undesirable property of embedded software that a change in a device interface requires widespread changes to the software because many programs are based on arbitrary interface details. If an interface changes, programs depending on it become invalid. Because these dependencies are seldom explicitly documented, interface changes often have surprising ramifications.

The first step toward improving the changeability of our systems is to confine the impact of hardware changes to a limited subset of modules. In the ideal scenario, if we change the hardware components in our system (including the processor), we will only need to change the associated driver(s) and configuration code. Other modules in our program will still work as intended. This is the goal we are working toward in this series.

One method that moves us closer to this goal is to enforce the use of abstract interfaces when interfacing with hardware. By using abstract interfaces, we can essentially divide our program into two camps: the portion that contains device-dependent code (e.g., drivers and hardware configuration modules) and a device-independent portion that will work with any hardware configuration that supports the required abstract interfaces.

In practical terms, we would say that most of our program doesn’t really need to know that there’s an ST VL53L1X time-of-flight sensor in the system. Instead, most of the program will work just fine by talking to a virtual time-of-flight sensor that supports a standard interface expected by the device-independent software layer.

In the next article, we will showcase practical techniques for creating virtual drivers and enforcing their use in our programs. First, we need to understand the overall strategy used in designing the abstract interfaces. We’ll start by reading an essential and classic paper: “A Procedure for Designing Abstract Interfaces for Device Interface Modules”. This paper explains the underlying goals, describes a procedure for creating abstract interfaces, and discusses common design challenges faced by embedded engineers who are striving to create abstract interfaces for device drivers.

Unlike many other papers which assume an academic audience, this one is targeted at embedded software developers in industry. There are many practical ideas that can be extracted from this paper and applied to your embedded software work.

The procedure is a practical approach to a recurring problem. As a result, we expect the paper to be more of interest to practicing software engineers than to researchers interested in today’s hot topics.

Read this paper to gain an understanding of the process for designing an abstract interface and handling common design tradeoffs that you will encounter. In the next article, we’ll apply the ideas described in the paper.

Members can access our commentary in the field atlas and discussion in the community forum.

Further Reading

Share Your Thoughts

This site uses Akismet to reduce spam. Learn how your comment data is processed.