Design Patterns for Embedded Systems in C: An Embedded Software Engineering Toolkit

Design Patterns for Embedded Systems in C: An Embedded Software Engineering Toolkit

by Bruce Powel Douglass

View All Available Formats & Editions

A recent survey stated that 52% of embedded projects are late by 4-5 months. This book can help get those projects in on-time with design patterns. The author carefully takes into account the special concerns found in designing and developing embedded applications specifically concurrency, communication, speed, and memory usage. Patterns are given in UML (Unified…  See more details below


A recent survey stated that 52% of embedded projects are late by 4-5 months. This book can help get those projects in on-time with design patterns. The author carefully takes into account the special concerns found in designing and developing embedded applications specifically concurrency, communication, speed, and memory usage. Patterns are given in UML (Unified Modeling Language) with examples including ANSI C for direct and practical application to C code.

A basic C knowledge is a prerequisite for the book while UML notation and terminology is included. General C programming books do not include discussion of the contraints found within embedded system design. The practical examples give the reader an understanding of the use of UML and OO (Object Oriented) designs in a resource-limited environment. Also included are two chapters on state machines. The beauty of this book is that it can help you today. .

*Design Patterns within these pages are immediately applicable to your project
*Addresses embedded system design concerns such as concurrency, communication, and memory usage
*Examples are contain ANSI C for ease of use with C programming code

Read More

Product Details

Elsevier Science
Publication date:
Sold by:
Barnes & Noble
Sales rank:
File size:
6 MB

Read an Excerpt

Design Patterns for Embedded Systems in C

An Embedded Software Engineering Toolkit
By Bruce Powel Douglass


Copyright © 2011 Elsevier Inc.
All right reserved.

ISBN: 978-0-08-095971-9

Chapter One

What Is Embedded Programming?

Chapter Outline

1.1 What's Special About Embedded Systems? 1

1.1.1 Embedded Design Constraints 3 1.1.2 The Embedded Tool Chain 4 1.1.3 OS, RTOS, or Bareback? 5 1.1.4 Embedded Middleware 6 1.1.5 Codevelopment with Hardware 7 1.1.6 Debugging and Testing 8

1.2 OO or Structured — It's Your Choice 9

1.2.1 Classes 10 1.2.2 Objects 13 1.2.3 Polymorphism and Virtual Functions 14 1.2.4 Subclassing 15 1.2.5 Finite State Machines 25 1.3 What Did We Learn? 33

What you will learn

Basics of embedded systems

OO versus structured programming

Implementing classes, inheritance, and state machines in ITLITL

1.1 What's Special About Embedded Systems?

This book focuses solely on embedded systems development. In doing so, it is drawing a distinction between "embedded" systems and "others." Before we get into the depth of the discussion, we need to understand what this difference is so that we can appreciate what it forebodes with respect to the patterns and technologies we will use to develop embedded systems.

I define an embedded system as "a computerized system dedicated to performing a specific set of real-world functions, rather than to providing a generalized computing environment." Clearly, this is a broad categorization that includes tiny 8-bit computers embedded in cardiac pacemakers, linked 32-bit computers controlling avionics, communications, fire control for aircraft, and wide-area networks composed of hundreds of powerful computer systems for battlefield management in C4ISR (Command, Control, Communications, Computers, Intelligence, Surveillance, and Reconnaissance) systems. Many embedded systems have no disks, human interface, and barely any memory but the scope of the embedded systems market is far broader than such simple devices.

Embedded systems are everywhere:

In the medical field, embedded systems include implantable devices (e.g., cardiac pacemakers, defibrillators, and insulin pumps), monitoring equipment (e.g., ECG/EKG monitors, blood gas monitors, blood pressure monitors, EMG monitors), imaging systems (e.g., CT, SPECT, PET, TEM, and x-ray imagers), and therapy delivery devices (e.g., patient ventilator, drug vaporizers, and infusion pumps).

In the telecom market, there are devices ranging from cell phones, switching systems, routers, modems, and satellites.

In automotive environments, embedded systems optimize engine combustion, manage power delivery in transmissions, monitor sensor data, control anti-lock braking, provide security, and offer infotainment services such as CD and DVD players, and GPS routing (in some locations, they can offer radar and laser detection and even active radar and laser countermeasures).

In the office, embedded systems manage phones, printers, copies, fax machines, lights, digital projectors, security systems, and fire detection and suppression systems.

In the home, examples include ovens, televisions, radios, washing machines, and even some vacuum cleaners.

Embedded systems already control, augment, monitor, and manage virtually every high-tech device we have from televisions to trains to factory automation, and their use is on the rise.

An important subset of embedded systems are real-time systems. Many people have the mistaken impression that "real time" means "real fast" but that is not true. A real-time system is one in which timeliness constraints must be satisfied for system correctness. A common, if simplistic, categorization of real-time systems is into two groups. "Hard" real-time systems are ones in which timeliness constraints are modeled as deadlines, points in time by which the execution of specific actions are required to be complete. "Soft" real-time systems are those that are not "hard"; that is, some other (usually stochastic) measure than deadlines is used to determine timeliness. This may include average throughput, average execution time, maximum burst length, or some other measure. All systems may be modeled as hard real-time systems, but this often results in "over-designing" the system to be faster or have more available resources than is necessary, raising the recurring cost (approximately "manufacturing cost") of the system.

Even though all systems may be modeled as hard real-time systems, in actual fact, most are not. If the response is occasionally delayed or even an entire input event is missed, most systems will continue to function properly. The primary reason for modeling real-time systems as "hard" is because it eases the assurance of the system's timeliness through mathematical analysis.

1.1.1 Embedded Design Constraints

From the inside, one of the most striking characteristics of embedded systems is severity of their constraints. Unlike writing software for a general-purpose computer, an embedded system is usually shipped already integrated with all the hardware it needs. The hardware platform is not usually user-extensible, so resources such as memory, power, cooling, or computing power contribute to the per-unit cost (known as recurring cost). To maintain profitability, there is almost always tremendous pressure on the developer to minimize the use of such hardware resources. This means that embedded systems often require additional optimization efforts far beyond that required for desktop applications.

Beyond the need to minimize hardware, performance concerns are often critical to the success of a system. There are many aspects to performance, and different systems value these aspects differently. In some systems, throughput is a critical criterion. Throughput is normally measured in terms of the number of transactions, samples, connections, or messages that can be processed per unit time. In other systems, handling each request as quickly as possible is more important, a quality known as responsiveness, usually captured as a worst case execution time. Other systems value predictability of performance over maximum throughput or responsiveness. Predictability is usually measured as occurring within a range or as being drawn from a probability density function.

Reliability, robustness, and safety are other kinds of constraints levied on embedded systems. The reliability of a system is a (stochastic) measure of the likelihood that the system will deliver the correct functionality. Robustness refers to the ability of a system to deliver services properly when its preconditions (such as operating conditions or input data rates) are violated. Safety denotes the level of risk of a system, that is, the likelihood that using the system will result in an accident or loss. These concerns often require additional hardware and software measures to maintain the operation of the system within acceptable limits. For example, most embedded systems have a power on self-test (POST) as well as a periodic or continuous built-in test (BIT).

Collectively, these constraints on the system are known as the qualities of services (QoS) provided by the system. In addition to the various QoS constraints, to reduce recurring cost, it is common to create custom hardware that requires specialized device driver software.

1.1.2 The Embedded Tool Chain

Most embedded systems are created on a different system (the "host") than they execute on (the "target"). This has a number of effects on the developer and the tools used in the creation of embedded systems. The most obvious such tool is the cross-compiler. This is a compiler that runs on the host but creates executable code that runs on a different computer and operating environment. Many real-time operating systems (RTOSs) provide their own proprietary compilers or provide customizations for open-source compilers such as GCC (Gnu Compiler Collection).

A linker is a program that combines a set of executable codes together into an executable for a target. Some operating systems don't require an explicit link step because the OS loader dynamically links the program elements as it loads into memory. This is true of Unix-style embedded operating systems but most embedded OSs require an explicit linking step. The linker often relocates the program as well, meaning that the start address is specified during the link step and assembly language jump instructions must be updated to reflect the actual starting base address.

A loader is a tool that loads the object image output from the linking step into the memory of the target environment. This may be done via a serial or network link or by burning the software image into nonvolatile memory such as Flash or EPROM. As an alternative to loading the software image on a target platform, many developers use simulators for the target that execute on their host development systems. It is common, for example, to use Z80 or 8051 simulators running on Windows to begin to run, debug, and test your software even before target boards are available.

So far, the tools mentioned in the tool chain have been limited to getting software onto the system. Beyond that, we need to ensure that the software works properly. The next set of tools are debuggers — tools that give us a great measure over the execution of the software, including the ability to step into (execute line by line) or step over (execute in entirety) functions, set breakpoints, and to examine and modify variables. These debuggers may work over standard serial and network links or over JTAG ports.

Modern-day Integrated Development Environments (IDEs) link together most or all of the tools in the embedded tool chain to facilitate and automate the development process. The latest industry trend is to host the IDEs in the Eclipse platform because of the power of the integrated environment and the availability of third-party and open-source plug-ins. The Jazz Foundation takes the Eclipse platform further to integrate management, measurement, reporting, and other tools to better support collaborative software development and delivery.

1.1.3 OS, RTOS, or Bareback?

An operating system (OS) provides a set of system and platform execution services for the application developer, especially around the management and use of target system resources. These resources include memory, concurrency units (processes, tasks, or threads), event queues, interrupts, hardware, and application programs. Most OSs do not provide any guarantees about timeliness, and desktop OSs may invoke unpredictable delays due to internal processing, memory management, or garbage collection at unforeseeable times. This unpredictability, and the fact that most desktop OSs are huge (compared to available memory), makes them unsuitable for real-time and embedded environments that are constrained in both time and resources.

A real-time operating system (RTOS) is a multitasking operating system intended for real-time and embedded applications. RTOSs are generally written to provide services with good efficiency and performance, but usually the predictability of the performance is more important than the maximum throughput. In addition, RTOSs are smaller and often less capable than desktop OSs. RTOSs don't guarantee real-time performance but they provide an application environment so that appropriate developed applications can achieve real-time performance.

RTOSs run applications and tasks using one of three basic design schemas. Event-driven systems handle events as they arise and schedule tasks to handle the processing. Most such systems use task priority as a quantitative means by which to determine which task will run if multiple tasks are ready to run. Task priorities are most often static (i.e., specified at design time as such with rate-monotonic scheduling) but some are dynamic, varying the task priorities to account for current operating conditions (such as earliest deadline first scheduling). The other two approaches to task scheduling implement a "fairness doctrine" either by giving all tasks a periodic time slice in which to run (time-base schemas, such as round robin scheduling) or by running the task set cyclically (sequence-based schemas, such as cyclic executive scheduling).

Twenty years ago, most development houses specializing in real-time systems wrote their own proprietary RTOSs but the RTOS market has undergone a consolidation, enabling such houses to spend a greater percentage of their development efforts on their in-house specialties by buying a commercial RTOS instead.

Some of the challenges of using RTOSs include the fact that while there are some big players, such as Wind River (maker of VxWorks™) and Green Hills Software (maker of Integrity™), there are literally hundreds of RTOSs in use today, and each has its own Application Program Interface (API). Further, although RTOSs have a smaller footprint and timeliness impact than their desktop brethren, that is not the same as having no impact. Many embedded systems run on small 8-bit processors with only a few tens of kilobytes of memory — too little for a standard RTOS. Many RTOSs support a scalable set of services (based on the Microkernel Architecture Pattern) but the degree of fidelity of that scalability may not meet the needs of a tightlyconstrained application.

Some systems having too few resources to support both an RTOS and the actual application software opt to go bareback — that is, function without a commercial or proprietary RTOS at all. This means that the application code itself must replicate any RTOS services or functionality needed by the application. With the drop in hardware costs, systems formerly done with tiny 8-bit processors have moved up to larger 16- and 32-bit processors. This is needed to add the additional complexity of behavior required in modern embedded devices and is enabled by the lower recurring costs of parts and manufacturing.

For very simple embedded systems, there may be no explicit operating system functionality at all. The application may simply be a set of interrupt handlers that communicate via a shared resource scheme such as queuing or shared memory. Alternatively, a simple task loop implementation of a cyclic executive might suffice. Somewhat more complex systems may introduce operating system features such as memory or task management as they need them.

From one point of view, an operating system is an integrated set of design patterns that provides certain kinds of services and resources to applications. Chapter 3 in this book discusses patterns for accessing hardware resources, such as timers and memory while Chapter 4 focuses on ways of managing concurrency in your embedded system.

1.1.4 Embedded Middleware

Middleware is software that connects software components together in some way. Middleware as a term dates back to the 1968 NATO Software Engineering Conference. Like operating systems, there is commercial support for middleware, but in small systems it may be developed as a part of the application software. The most common middlewares for real-time and embedded systems include Common Object Request Broker Architecture (CORBA) and its many variants, and the Data Distribution Service (DDS). Both these middleware architectures are based on standards published by the Object Management Group (OMG). In the case of CORBA, there are many specialized variant standards from which to choose including RealTime CORBA, Embedded CORBA, and Minimum CORBA.

As you might guess, middleware is appropriate for larger-scale embedded applications — those consisting of multiple software components or applications that may be distributed across multiple processors and networks. Particularly when the components are to be developed by different organizations, the system will be extended by different organizations, or when the system is particularly long-lived, using standard middleware provides significant benefit to the developer

These middleware architectures, again like operating systems, are integrated collections of design patterns, such as Proxy, Data Bus, and Broker Pattern.


Excerpted from Design Patterns for Embedded Systems in C by Bruce Powel Douglass Copyright © 2011 by Elsevier Inc.. Excerpted by permission of Newnes. All rights reserved. No part of this excerpt may be reproduced or reprinted without permission in writing from the publisher.
Excerpts are provided by Dial-A-Book Inc. solely for the personal use of visitors to this web site.

Read More

Meet the Author

Embedded Software Methodologist. Triathlete. Systems engineer. Contributor to UML and SysML specifications. Writer. Black Belt. Neuroscientist. Classical guitarist. High school dropout. Bruce Powel Douglass, who has a doctorate in neurocybernetics from the USD Medical School, has over 35 years of experience developing safety-critical real-time applications in a variety of hard real-time environments. He is the author of over 5700 book pages from a number of technical books including Real-Time UML, Real-Time UML Workshop for Embedded Systems, Real-Time Design Patterns, Doing Hard Time, Real-Time Agility, and Design Patterns for Embedded Systems in C. He is the Chief Evangelist at IBM Rational, where he is a thought leader in the systems space and consulting with and mentors IBM customers all over the world. He can be followed on Twitter @BruceDouglass. Papers and presentations are available at his Real-Time UML Yahoo technical group ( and from his IBM thought leader page (

Read More

Customer Reviews

Average Review:

Write a Review

and post it to your social network


Most Helpful Customer Reviews

See all customer reviews >