Anda di halaman 1dari 36

Chapter 25

Embedded systems programming

Bjarne Stroustrup

www.stroustrup.com/Programming
Abstract
This lecture provides a brief overview of what
distinguishes embedded systems programming
from ordinary programming. It then touches
upon facilities that become prominent or
problems when working close to the
hardware such as free store use, bit
manipulation, and coding standards.
Remember: not all computers are little grey
boxes hiding under desks in offices.

Stroustrup/Programming Nov'13 2
Overview
Embedded systems
Whats special/different
predictability
Resource management
memory
Access to hardware
Absolute addresses
Bits unsigned
Coding standards

Stroustrup/Programming Nov'13 3
Embedded systems
Hard real time
Response must occur before the deadline
Soft real time
Response should occur before the deadline most of the time
Often there are plenty of resources to handle the common cases
But crises happen and must be handled
Predictability is key
Correctness is even more important than usual
correctness is not an abstract concept
but I assumed that the hardware worked correctly is no excuse
Over a long time and over a large range of conditions, it simply doesnt

Stroustrup/Programming Nov'13 4
Embedded systems

Computers used as part of a larger system


That usually doesnt look like a computer
That usually controls physical devices
Often reliability is critical
Critical as in if the system fails someone might die
Often resources (memory, processor capacity) are limited
Often real-time response is essential
Stroustrup/Programming Nov'13 5
Embedded systems
What are we talking about? Fuel injector controls
Assembly line quality monitors Medical equipment monitors
Bar code readers PDAs
Bread machines
Printer controllers
Cameras
Sound systems
Rice cookers
Car assembly robots Telephone switches
Cell phones Water pump controllers
Centrifuge controllers Welding machines
CD players Windmills
Disk drive controllers Wrist watches
Smart card processors

Stroustrup/Programming Nov'13 6
Do You Need to Know This Stuff ?
Computer Engineers You will build and oversee the building of
these systems
All close to the hardware code resembles this
The concern for correctness and predictability of embedded systems code is
simply a more critical form of what we want for all code
Electrical Engineers You will build and oversee the building of
these systems.
You have to work with the computer guys
You have to be able to talk to them
You may have to teach them
You may have to take over for them
Computer scientists youll know how to do this or only work on
web applications (and the like)

Stroustrup/Programming Nov'13 7
Predictability
C++ operations execute in constant, measurable time
E.g., you can simply measure the time for an add operation or a virtual
function call and thatll be the cost of every such add operation and every
virtual function call (pipelining, caching, implicit concurrency makes this
somewhat trickier on some modern processors)
With the exception of:
Free store allocation (new)
Exception throw
So throw and new are typically banned in hard real-time
applications
Today, I wouldnt fly in a plane that used those
In 5 years, well have solved the problem for throw
Each individual throw is predictable
Not just in C++ programs
Similar operations in other languages are similarly avoided
Stroustrup/Programming Nov'13 8
Ideals/aims
Given the constraints
Keep the highest level of abstraction
Dont write glorified assembler code
Represent your ideas directly in code
As always, try to write the clearest, cleanest, most
maintainable code
Dont optimize until you have to
People far too often optimize prematurely
John Bentleys rules for optimization
First law: Dont do it
Second law (for experts only): Dont do it yet

Stroustrup/Programming Nov'13 9
Embedded systems programming
You (usually) have to be much more aware of the resources
consumed in embedded systems programming than you have
to in ordinary programs
Time
Space
Communication channels
Files
ROM (Read-Only Memory)
Flash memory

You must take the time to learn about the way your language
features are implemented for a particular platform
Hardware
Operating system
Libraries
Stroustrup/Programming Nov'13 10
Embedded systems programming
A lot of this kind of programming is
Looking at specialized features of an RTOS (Real Time
Operating System)
Using a Non-hosted environment (thats one way of
saying a language right on top of hardware without an
operating system)
Involving (sometimes complex) device driver architectures
Dealing directly with hardware device interfaces

We wont go into details here
Thats what specific courses and manuals are for

Stroustrup/Programming Nov'13 11
How to live without new
old object

Free space old object


Whats the problem?
C++ code refers directly to memory
Once allocated, an object cannot be moved (or can it?) New object
Allocation delays
The effort needed to find a new free chunk of memory of a
given size depends on what has already been allocated
Fragmentation
If you have a hole (free space) of size N and you allocate an
object of size M where M<N in it, you now have a fragment of
size N-M to deal with
After a while, such fragments constitute much of the memory
Stroustrup/Programming Nov'13 12
How to live without new
Solution: pre-allocate Stack:
Global objects
Allocated at startup time
Sets aside a fixed amount of memory
Stacks
Grow and shrink only at the top
No fragmentation
Constant time operations
Pools of fixed sized objects
We can allocate and deallocate in any order
No fragmentation
Constant time operations
Top of stack
Pool:

Stroustrup/Programming Nov'13 13
How to live without new
No new (of course)
And no malloc() (memory allocation during runtime) either (for those
of you who speak C)
No standard library containers (they use free store indirectly)
Unless you have a special hard-real time implementation
Instead
Define (or borrow) fixed-sized Pools
Define (or borrow) fixed-sized Stacks
Do not regress to using arrays and lots of pointers

Stroustrup/Programming Nov'13 14
Pool example
// Note: element type known at compile time
// allocation times are completely predictable (and short)
// the user has to pre-calculate the maximum number of elements needed
template<class T, int N> class Pool {
public:
Pool(); // make pool of N Ts construct pools only during startup
T* get(); // get a T from the pool; return 0 if no free Ts
void free(T* p); // return a T given out by get() to the pool
private:
// keep track of T[N] array (e.g., a list of free objects)
};

Pool<Small_buffer, 10> sb_pool;


Pool<Status_indicator, 200> indicator_pool;

Stroustrup/Programming Nov'13 15
Stack example
// Note: allocation times completely predictable (and short)
// the user has to pre-calculate the maximum number of elements needed
template<int N> class Stack {
public:
Stack(); // make an N byte stack construct stacks only during startup
void* get(int N); // allocate n bytes from the stack; return 0 if no free space
void free(void* p); // return the last block returned by get() to the stack
private:
// keep track of an array of N bytes (e.g. a top of stack pointer)
};
Stack<50*1024> my_free_store; // 50K worth of storage to be used as a stack
void* pv1 = my_free_store.get(256 * sizeof(int)); // allocate array of ints
int* pi = static_cast<int*>(pv1); // you have to convert memory to objects
void* pv2 = my_free_store.get(50);
Pump_driver* pdriver = static_cast<Pump_driver*>(pv2);

Stroustrup/Programming Nov'13 16
Templates
Excellent for embedded systems work
No runtime overhead for inline operations
Sometimes performance matters
No memory used for unused operations
In embedded systems memory is often critical (limited)

Stroustrup/Programming Nov'13 17
How to live with failing hardware
Failing how?
In general, we cannot know
In practice, we can assume that some kinds of errors are more common than
others
But sometimes a memory bit just decides to change (cosmic ray, silicon fatigue, )
Why?
Power surges/failure
The connector vibrated out of its socket
Falling debris
Falling computer
X-rays

Transient errors are the worst
E.g., only when the temperature exceeds 100 F. and the cabinet door is closed
Errors that occur away from the lab are the worst
E.g., on Mars

Stroustrup/Programming Nov'13 18
How to live with failing hardware
Replicate
In emergency, use a spare
Self-check
Know when the program (or hardware) is misbehaving
Have a quick way out of misbehaving code
Make systems modular
Have some other module, computer, part of the system
responsible for serious errors
In the end, maybe a person i.e., manual override
Remember HAL ?
Monitor (sub)systems
In case they cant/dont notice problems themselves

Stroustrup/Programming Nov'13 19
Absolute addresses
Physical resources (e.g., control registers for external devices)
and their most basic software controls typically exist at
specific addresses in a low-level system (e.g., memory-
mapped I/O)
We have to enter such addresses into our programs and give a
type to such data
For example
Device_driver* p
= reinterpret_cast<Device_driver*>(0xffb8);
Serial_port_base* Com1
= reinterpret_cast<Serial_port_base*>(0x3f8);

Stroustrup/Programming Nov'13 20
Bit manipulation: Unsigned integers
How do you represent a set of bits in C++?
unsigned char uc; // 8 bits
unsigned short us;// typically 16 bits
unsigned int ui; // typically 16 bits or 32 bits
// (check before using)
// many embedded systems have 16-bit ints
unsigned long int ul; // typically 32 bits or 64 bits
std::vector<bool> vb(93); // 93 bits
true/false auto-converts to/from 1/0

Use only if you really need more than 32 bits

std::bitset bs(314); // 314 bits


Use if you really need more than 32 bits

Typically efficient for multiples of sizeof(int)

Stroustrup/Programming Nov'13 21
Bit manipulation
a: 1 0 1 0 1 0 1 0 0xaa

b: 0 0 0 0 1 1 1 1 0x0f

& and a&b: 0 0 0 0 1 0 1 0 0x0a

| inclusive or a|b: 1 0 1 0 1 1 1 1 0xaf

^ exclusive or a^b: 1 0 1 0 0 1 0 1 0xa5

<< left shift a<<1: 0 1 0 1 0 1 0 0 0x54

>> right shift b>>2: 0 0 0 0 0 0 1 1 0x03


~ ones complement ~b: 1 1 1 1 0 0 0 0 0xf0

Stroustrup/Programming Nov'13 22
Bit manipulation
Sign bit
Bitwise operations 8 bits == 1 byte
& (and)
| (or) val
^ (exclusive or xor) 0 1 1 0 0 0 1 1 0 1 0 0 1 1 0 1
<< (left shift)
>> (right shift)
~ (one's complement) 0xff: 1 1 1 1 1 1 1 1
Basically, what the hardware provides right: 0 1 0 0 1 1 0 1
true false
For example
void f(unsigned short val) // assume 16-bit, 2-byte unsigned short integer
{
unsigned char right = val & 0xff ; // rightmost (least significant) byte
unsigned char left = (val>>8) & 0xff ; // leftmost (most significant) byte
bool negative = val & 0x8000 ; // sign bit (if 2s complement)
//
}

Stroustrup/Programming Nov'13 23
Bit manipulation
Or | 0xff: 1 1 1 1 1 1 1 1
Set a bit (whether or not already set) val 1 0 1 0 1 0 1 0
And &
Is a bit set? Select (mask) some bits
For example:
enum Flags { bit4=1<<4, bit3=1<<3, bit2=1<<2, bit1=1<<1, bit0=1 };
unsigned char x = bit3 | bit1; // x becomes 8+2
x |= bit2; // x becomes 8+4+2
if (x & bit3) { // is bit3 set? (yes, it is)
//
}
unsigned char y = x & (bit4 | bit2); // y becomes 4
Flags z = Flags(bit2 | bit0); // the cast is necessary because the compiler
// doesnt know that 5 is in the Flags range

Stroustrup/Programming Nov'13 24
Bit manipulation
Exclusive or (xor) ^
a^b means (a|b) & !(a&b) either a or b but not both
unsigned char a = 0xaa;
unsigned char b = 0x0f;
unsigned char c = a^b;
Immensely important in graphics and cryptography
a: 1 0 1 0 1 0 1 0 0xaa

b: 0 0 0 0 1 1 1 1 0x0f

a^b: 1 0 1 0 0 1 0 1 0xa5

Stroustrup/Programming Nov'13 25
Unsigned integers
You can do ordinary arithmetic on unsigned integers
Avoid that when you can
Try never to use unsigned just to get another bit of precision
If you need one extra bit, soon, you ll need another
Dont mix signed and unsigned in an expression
int x = -2;// a negative number
unsigned int y = x;// a very large positive number
if (x < 1) cout << "no surprise: x<1\n";
if (y < 1) cout << "y<1\n"; else cout << "surprise? not y<1\n";
if (-3 < x) cout << "no surprise: -3<x\n";
if (-3 < y) cout << "surprise? -3<y\n";
if (3 < y) cout << "surprise? 3<y\n";

Stroustrup/Programming Nov'13 26
Unsigned integers
You can do ordinary arithmetic on unsigned integers
You cant
cant completely avoid unsigned arithmetic
Indexing into standard library containers uses unsigned
(in my opinion, thats
thats a design error; arrays use signed ints)
vector<int> v;
//
for (int i = 0; i<v.size(); ++i)
for (unsigned int i = 0; i<v.size(); ++i)
for (vector<int>::size_type i = 0; i<v.size(); ++i)
for (vector<int>::iterator p = v.begin(); p!=v.end(); ++p)
for (auto p = v.begin(); p!=v.end(); ++p) unsigned
signed for (auto i = 0; i<v.size(); ++i)
for (int x : v)
correct, but pedantic

A C++11 way

signed

Yet another C++11 way Stroustrup/Programming Nov'13 27


Complexity
One source of errors is complicated problems
Inherent complexity
Another source of errors is poorly-written code
Incidental complexity
Reasons for unnecessarily complicated code
Overly clever programmers
Who use features they dont understand
Undereducated programmers
Who dont use the most appropriate features
Large variations in programming style

Stroustrup/Programming Nov'13 28
Coding standards
A coding standard is a set of rules for what code should
look like
Typically specifying naming and indentation rules
E.g., use Stroustrup layout
Typically specifying a subset of a language
E.g., dont use new or throw (to avoid predictability problems)
Typically specifying rules for commenting
Every function must have a comment explaining what it does
Often requiring the use of certain libraries
E.g., use <iostream> rather than <stdio.h> to avoid safety problems
Organizations often try to manage complexity through
coding standards
Often they fail and create more complexity than they manage

Stroustrup/Programming Nov'13 29
Coding standards
A good coding standard is better than no standard
I wouldnt start a major (multi-person, multi-year) industrial project without one
A poor coding standard can be worse than no standard
C++ coding standards that restrict programming to something like the C subset do
harm
They are not uncommon
All coding standards are disliked by programmers
Even the good ones
All programmers want to write their code exactly their own way
A good coding standard is prescriptive as well as restrictive
Here is a good way of doing things as well as
Never do this
A good coding standard gives rationales for its rules
And examples

Stroustrup/Programming Nov'13 30
Coding standards
Common aims
Reliability
Portability
Maintainability
Testability
Reusability
Extensibility
Readability

Stroustrup/Programming Nov'13 31
Some sample rules
No function shall have more than 200 lines (30 would be even better)
that is, 200 non-comment source lines
Each new statement starts on a new line
E.g., int a = 7; x = a+7; f(x,9); // violation!
No macros shall be used except for source control
using #ifdef and #ifndef
Identifiers should be given descriptive names
May contain common abbreviations and acronyms
When used conventionally, x, y, i, j, etc., are descriptive
Use the number_of_elements style rather than the numberOfElements style
Type names and constants start with a capital letter
E.g., Device_driver and Buffer_pool
Identifiers shall not differ only by case
E.g., Head and head // violation!

Stroustrup/Programming Nov'13 32
Some more sample rules
Identifiers in an inner scope should not be identical to identifiers
in an outer scope
E.g., int var = 9; { int var = 7; ++var; } // violation: var hides var
Declarations shall be declared in the smallest possible scope
Variables shall be initialized
E.g., int var; // violation: var is not initialized
Casts should be used only when essential
Code should not depend on precedence rules below the level of
arithmetic expressions
E.g., x = a*b+c; // ok
if( a<b || c<=d) // violation: parenthesize (a<b) and (c<=d)
Increment and decrement operations shall not be used as
subexpressions
E.g., int x = v[++i]; // violation (that increment might be overlooked)

Stroustrup/Programming Nov'13 33
An example of bit manipulation
The Tiny Encryption Algorithm (TEA)
Originally by David Wheeler
http://143.53.36.235:8080/tea.htm
Dont look too hard at the code (unless you happen to need a
good simple encryption algorithm for an application); its
simply to give you the flavor of some bit manipulation code
It takes one word (4 bytes at a time)
E.g., 4 characters from a string or an image file
It assumes 4-byte long integers
Explanation is at the link (and in the book)
Without the explanation this is just an example of how bit manipulation
code can look. This code is not meant to be self-explanatory.

Stroustrup/Programming Nov'13 34
TEA
void encipher(
const unsigned long *const v,
unsigned long *const w,
const unsigned long * const k)
{
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0;
unsigned long delta = 0x9E3779B9;
unsigned long n = 32;
while(n-->0) {
y += (z << 4 ^ z >> 5) + z ^ sum + k[sum&3];
sum += delta;
z += (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3];
}
w[0]=y;
w[1]=z;
} Stroustrup/Programming Nov'13 35
void decipher(
TEA
const unsigned long *const v,
unsigned long *const w,
const unsigned long * const k)
{
unsigned long y = v[0];
unsigned long z = v[1];
unsigned long sum = 0xC6EF3720;
unsigned long delta = 0x9E3779B9;
unsigned long n = 32;
// sum = delta<<5; in general, sum = delta * n
while(n-->0) {
z -= (y << 4 ^ y >> 5) + y ^ sum + k[sum>>11 & 3];
sum -= delta;
y -= (z << 4 ^ z >> 5) + z ^ sum + k[sum&3];
}
w[0]=y;
w[1]=z;
}
Stroustrup/Programming Nov'13 36

Anda mungkin juga menyukai