The education of embedded systems software engineers: failures and fixes

(A professional embedded systems software engineer requires specific knowledge in a number of areas, together with problem-solving skills to apply this knowledge as a team member in building safe, secure, and reliable systems. Regrettably, says Adacore’s Robert Dewar, emeritus professor at New York University, the educational approach typically seen in university Computer Science programs, especially in the U.S., fails to provide either. Changes in course content and focus are needed.

Embedded systems programming is hard.

An immediate issue is the (con)fusion of levels: platform-specific characteristics that would ordinarily be encapsulated behind high-level interfaces are often the essence of an embedded system’s architecture and thus emerge at all layers of the design.

Parallelism is typical, introducing opportunities for nasty bugs such as data corruption, race conditions, deadlock, and starvation. External devices generally communicate through interrupts, a software engineering nightmare: asynchronous function calls occurring at unpredictable points of execution, delivering results through shared data.

Embedded systems commonly monitor and/or control external devices, so reliability (including the meeting of real-time constraints) is essential or equipment may be at risk. Since malfunctioning equipment could jeopardize human life or material assets, embedded systems are often safety critical or high security, requiring certification against domain-specific standards.

The development process for embedded software is much more complicated than for native systems, involving cross-compilation environments, emulators, and other specialized (and often expensive) tools and hardware.

Finally and significantly, many of the most critical embedded systems contain a large amount of software, perhaps millions of lines of code, are developed by teams that may be geographically distributed, and must evolve over time in response to changes in requirements.

Embedded systems must therefore be modular, extensible, and adaptable, and developers need to rigorously follow sound processes for version control, configuration management, and quality assurance.

All of this presents quite a challenge to professional embedded system programmers. A natural question is: How well the Computer Science education offered by universities prepares them to deal with such real-world issues?

The unfortunate answer, at least in the US, is “not very”. This article, a follow-up to [1], identifies some of the root causes for this gap and suggests how to make progress.

Why Johnny and Janie can’t program

The problems start early in the curriculum. Too often an introductory Computer Science course will fall into one of two extremes: either focusing on the syntactic details of the programming language that is being used – “where the semicolons go” – or else treating programming as a matter of choosing components and plugging them into a GUI.

The basics – how to design and analyze algorithms and data structures – are covered summarily if at all. Software methodologies such as Object Orientation that are best approached in the context of the development life cycle for large applications, are introduced through trivial examples before their benefits can be appreciated: the proverbial cannon that is used to shoot a fly.

Important issues, such as understanding language-related vulnerabilities and knowing how to avoid them [2], are not explored.

The rush of universities to jump on the Java bandwagon in the late 1990s precipitated some of these problems. Java is a fine language for many kinds of applications, especially ones that need dynamic flexibility. However, its Object Orientation bias makes it clumsy for more traditional systems, its reliance on Garbage Collection hides the memory management issues that embedded systems programmers need to understand and deal with, and its thread model is a source of subtle traps and pitfalls [3].

To be blunt, adopting Java to replace previous languages used in introductory programming courses – such as Pascal, Ada, C, or C++ — was a step backward pedagogically. Many universities went to Java because “that’s where the jobs are”, but ironically may have produced a generation of programmers with over-specific but superficial skills who are now losing jobs to overseas competition with broader and deeper talents.

As explained in [1], universities need to take a fresh look at goals for the programming language(s) used in introductory computer science courses, and ensure that, at least at the upper levels, students gain practical experience with a broad spectrum of languages.