Posts Tagged ‘safety’

Firmware Disasters

Tuesday, June 23rd, 2009 Michael Barr

First, an Airbus A330 fell out of the sky. Then two D.C. Metro trains collided. Several hundred people have been killed and injured in these disastrous system failures. Did bugs in embedded software play a role in either or both disasters?

An incident on an earlier (October 2006) Airbus A330 flight may offer clues to the crash of Air France 447:

Qantas Flight 72 had been airborne for three hours, flying uneventfully on autopilot from Singapore to Perth, Australia. But as the in-flight dinner service wrapped up, the aircraft’s flight-control computer went crazy. The plane abruptly entered a smooth 650-ft. dive (which the crew sensed was not being caused by turbulence) that sent dozens of people smashing into the airplane’s luggage bins and ceiling. More than 100 of the 300 people on board were hurt, with broken bones, neck and spinal injuries, and severe lacerations splattering blood throughout the cabin. (Article, Time Magazine, June 3, 2009)

Authorities have blamed a pair of simultaneous computer failures for that event in the fly-by-wire A330. First, one of three redundant air data inertial reference units (ADIRUs) began giving bad angle of attack (AOA) data. Simultaneously, a voting algorithm intended to handle precisely such a failure in 1 of the 3 units by relying only on the other matching data failed to work as designed; the flight computer instead made decisions only on the basis of the one failed ADIRU!

(A later analysis by Airbus “found data fingerprints suggesting similar ADIRU problems had occurred on a total of four flights. One of the earlier instances, in fact, included a September 2006 event on the same [equipment] that entered the uncommanded dive in October [2006].” Ibid.)

Much of the attention in the publicly disclosed details of the Air France 447 crash has focused on the failure of one of several air speed indicators. Were there three of those as well? If so, was the same flight computer to blame for failing to recognize which to trust and which was unreliable?

It is very early in the investigation of yesterday’s collision between two D.C. Metro red line trains, in which a stopped train was rear-ended and heavily damaged by a moving train on the same track, to place blame. But a WashingtonPost.com article headlined “Collision was Supposed to be Impossible” says it all:

Metro was designed with a fail-safe computerized signal system that is supposed to prevent trains from colliding.

and

During morning and afternoon rush hours, all trains except longer eight-car trains typically operate in automatic mode, meaning their movements are controlled by computerized systems and the central Operations Control Center. Both trains in yesterday’s crash [about 5pm] were six-car trains. (Article, Washington Post, June 23, 2009)

Are bugs in embedded software to blame for these two disasters? You can bet the lawyers are already looking into it.

Coding Standard Rule #10: Don’t Use the Comma Delimiter Within Variable Declarations

Monday, April 6th, 2009 Michael Barr

Rule: The comma (‘,’) operator shall not be used within variable declarations.

Example (don’t):

char * x, y;   // did you want y to be a pointer or not?

Reasoning: The cost of placing each declaration on a line of its own is low. By contrast, the risk that you’ve made a mistake and the compiler or a maintainer won’t understand your intentions is high.

Coding Standard Rule #9

These rules are excerpts from the Embedded C Coding Standard book.

Coding Standard Rule #9: Don’t Create Function-Like Macros

Friday, April 3rd, 2009 Michael Barr

Rule: Parameterized macros shall not be used if an inline function can be written to accomplish the same task.

Example:

#define MAX(A, B)   ((A) > (B) ? (A) : (B))     // Don’t do this ...inline int max(int a, int b)           // ... if you can do this instead.

Reasoning: There are a lot of risks associated with the use of preprocessor #defines, and many of them relate to the creation of parameterized macros. The extensive use of parentheses (as shown in the example) is important, but does not eliminate the unintended double increment possibility of a call such as MAX(i++, j++). Other risks of macro misuse include comparison of signed and unsigned data or any test of floating-point data. The C++ keyword inline was added to the C standard in the 1999 ISO update.

Coding Standard Rule #8
Coding Standard Rule #10

These rules are excerpts from the Embedded C Coding Standard book.

Coding Standard Rule #8: Don’t Mix Signed and Unsigned Data

Thursday, April 2nd, 2009 Michael Barr

Rule: Signed integers shall not be combined with unsigned integers in comparisons or expressions. In support of this, decimal constants meant to be unsigned should be declared with a ‘u’ at the end.

Example (don’t):

uint8_t a = 6u;
int8_t b = -9;

if (a + b < 4)
{
// This correct path should be executed
// if -9 + 6 were -3 < 4, as anticipated.
}
else
{
// This incorrect path is actually executed
// because -9 + 6 becomes (0xFF – 9) + 6 = 252.
}

Reasoning: Several details of the manipulation of binary data within signed integer containers are implementation-defined behaviors of the C standard. Additionally, the results of mixing signed and unsigned data can lead to data-dependent bugs.

Coding Standard Rule #7
Coding Standard Rule #9

These rules are excerpts of the Embedded C Coding Standard book.

Coding Standard Rule #6: Use C99’s Fixed-Width Integer Type Names

Tuesday, March 31st, 2009 Michael Barr

This is the sixth in a continuing series of blog posts describing simple coding rules that help keep bugs out of embedded C programs.

Rule: Whenever the width, in bits or bytes, of an integer value matters in the program, fixed width data types shall be used in place of char, short, int, long, or long long. The signed and unsigned fixed width integer types shall be as shown in the table below.

Integer Width Signed Type Unsigned Type
8 bits / 1 byte int8_t uint8_t
16 bits / 2 bytes int16_t uint16_t
32 bits / 4 bytes int32_t uint32_t
64 bits / 8 bytes int64_t uint64_t

Reasoning: The ISO C standard allows implementation-defined widths for char, short, int, long, and long long types, which leads to portability problems. Though the 1999 standard did not change this underlying issue, it did introduce the uniform type names shown in the table, which are defined in the new header file stdint.h. These are the names to use even if you have to create the typdefs by hand.

Coding Standard Rule #5
Coding Standard Rule #7

These rules are excerpts from the Embedded C Coding Standard book.