{[ promptMessage ]}

Bookmark it

{[ promptMessage ]}

Chapter 25 - Chapter 25 Chapter Embedded systems...

Info iconThis preview shows page 1. Sign up to view the full content.

View Full Document Right Arrow Icon
This is the end of the preview. Sign up to access the rest of the document.

Unformatted text preview: Chapter 25 Chapter Embedded systems programming Bjarne Stroustrup www.stroustrup.com/Programming Abstract Abstract This lecture provides a brief overview of what This 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. boxes Stroustrup/Programming 2 Overview Overview Embedded systems What’s special/different Resource management memory Access to hardware predictability Absolute addresses Bits – unsigned Coding standards Stroustrup/Programming 3 Embedded systems Embedded Hard real time Soft real time Response should occur before the deadline most of the time Often there are plenty of resources to handle the common cases Response must occur before the deadline 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 doesn’t Stroustrup/Programming 4 Embedded systems Embedded Computers used as part of a larger system Often reliability is critical That usually doesn’t look like a computer That usually controls physical devices “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 5 Embedded systems Embedded What are we talking about? Assembly line quality monitors Bar code readers Bread machines Cameras Car assembly robots Cell phones Centrifuge controllers CD players Disk drive controllers “Smart card” processors Stroustrup/Programming Fuel injector controls Medical equipment monitors PDAs Printer controllers Sound systems Rice cookers Telephone switches Water pump controllers Welding machines Windmills Windmills Wrist watches … 6 Do You Need to Know This Stuff ? Do Computer Engineers – You will build and oversee the building Computer of these systems of Electrical Engineers – You will build and oversee the building Electrical of these systems. of All “close to he hardware” code resembles this The concern for correctness and predictability of embedded systems The code is simply a more critical form of what we want for all code code 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 – you’ll know to do this or only work on Computer web applications (and the like) Stroustrup/Programming 7 Predictability Predictability C++ operations execute in constant, measurable time With the exception of: E.g., you can simply measure the time for an add operation or a virtual E.g., function call and that’ll 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) somewhat Free store allocation (new) Exception throw Exception throw So throw and new are typically banned in hard real-time So and applications applications Today, I wouldn’t fly in a plane that used those In 5 years, we’ll have solved the problem for throw In throw Each individual throw is predictable Each throw Not just in C++ programs Similar operations in other languages are similarly avoided Stroustrup/Programming 8 Ideals/aims Ideals/aims Given the constraints Keep the highest level of abstraction Don’t write glorified assembler code Represent your ideas directly in code As always, try to write the clearest, cleanest, most As maintainable code maintainable Don’t optimize until you have to People far too often optimize prematurely John Bentley's rules for optimization First law: Don’t do it Second law (for experts only): Don’t do it yet Stroustrup/Programming 9 Embedded systems programming Embedded You (usually) have to be much more aware of the resources You consumed in embedded systems programming than you have to in “ordinary” programs to Time Space Communication channels Files ROM (Read-Only Memory) Flash memory … You must take the time to learn about the way your language You features are implemented for a particular platform features Hardware Operating system Libraries Libraries Stroustrup/Programming 10 10 Embedded systems programming Embedded A lot of this kind of programming is Looking at specialized features of an RTOS (Real Time Looking Operating System) Operating Using a “Non-hosted environment” (that’s one way of Using saying “a language right on top of hardware without an operating system”) operating Involving (sometimes complex) device driver architectures Dealing directly with hardware device interfaces … We won’t go into details here That’s what specific courses and manuals are for Stroustrup/Programming 11 How to live without new new old object Free space old object What’s the problem C++ code refers directly to memory New object Allocation delays Once allocated, an object cannot be moved (or can it?) The effort needed to find a new free chunk of memory of a The given size depends on what has already been allocated Fragmentation If you have a “hole” (free space) of size N and you allocate an If object of size M where M<N in it, you now have a fragment of size N-M to deal with size After a while, such fragments constitute much of the memory Stroustrup/Programming 12 How to live without new new Solution: pre-allocate Global objects Allocated at startup time Sets aside a fixed amount of memory Sets Stacks Grow and shrink only at the top Stack: No fragmentation Constant time operations Pools of fixed sized objects We can allocate and deallocate No fragmentation Constant time operations Top of stack Pool: Stroustrup/Programming 13 How to live without new new No new (of course) No new No standard library containers (they use free store indirectly) Instead And no malloc() (memory allocation during runtime) either (for those And malloc() of you who speak C) of Define (or borrow) fixed-sized Pools Define (or borrow) fixed-sized Stacks Do not regress to using arrays and lots of pointers Stroustrup/Programming 14 Pool example Pool // Note: element type known at compile time Note: // allocation times are completely predictable (and short) // the user has to pre-calculate the maximum number of elements needed the template<class T, int N>class Pool { public: Pool(); // make pool of N Ts – construct pools only during startup // make T* get(); // get a T from the pool; return 0 if no free Ts // get void free(T*); // return a T given out by get() to the pool // return given to private: // keep track of T[N] array (e.g., a list of free objects) // keep }; Pool<Small_buffer,10> sb_pool; Pool<Status_indicator,200> indicator_pool; Stroustrup/Programming 15 Stack example Stack // Note: allocation times completely predictable (and short) // Note: // the user has to pre-calculate the maximum number of elements needed // the template<int N>class Stack { public: Stack(); // make an N byte stack – construct stacks only during startup // make byte void* get(int N); // allocate n bytes from the stack; return 0 if no free space void* void free(void* p); // return the last block returned by get() to the stack void to private: // keep track of an array of N bytes (e.g. a top of stack pointer) // keep an }; Stack<50*1024> my_free_store; // 50K worth of storage to be used as a stack // 50K void* pv1 = my_free_store.get(1024); int* pi = static_cast<int*>(pv1); // you have to convert memory to objects // you void* pv2 = my_free_store.get(50); Pump_driver* pdriver = static_cast<Pump_driver*>(pv2); Stroustrup/Programming 16 Templates 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 17 How to live with failing hardware How Failing how? In general, we cannot know In practice, we can assume that some kinds of errors are more common than In others others Why? Power surges/failure The connector vibrated out of its socket Falling debris Falling computer X-rays … Transient errors are the worst But sometimes a memory bit just decides to change 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 18 How to live with failing hardware How Replicate Self-check In emergency, use a spare 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 Have responsible for serious errors responsible In the end, maybe a person i.e., manual override In Remember HAL ? Remember Monitor (sub)systems In case they can’t/don’t notice problems themselves Stroustrup/Programming 19 Absolute addresses Absolute Physical resources (e.g., control registers for external devices) control and their most basic software controls typically exist at specific addresses in a low-level system specific We have to enter such addresses into our programs and give a We type to such data type For example Device_driver* p = reinterpret_cast<Device_driver*>(0xffb8); Serial_port_base *COM1 = Serial_port_base reinterpret_cast<Serial_port_base*>(0x3f8); reinterpret_cast<Serial_port_base*>(0x3f8); Stroustrup/Programming 20 Bit manipulation: Unsigned integers Bit How do you represent a set of bits in C++? unsigned char uc; unsigned short us; unsigned int ui; // 8 bits // bits // typically 16 bits // typically // typically 16 bits or 32 bits // typically // (check before using) // (check // many embedded systems have 16-bit ints // many // typically 32 bits or 64 bits // typically unsigned long int ul; std::vector<bool> vb(93); // 93 bits // 93 Use only if you really need more than 32 bits std::bitset bs(314); // 314 bits // 314 Use only if you really need more than 32 bits Typically efficient for multiples of sizeof(int) Typically sizeof(int) Stroustrup/Programming 21 Bit manipulation Bit a: b: & | ^ << >> >> ~ and and inclusive or inclusive exclusive or exclusive left shift right shift one’s complement one’s 1 0 1 0 1 0 1 0 0xaa 0 0 0 0 1 1 1 1 0x0f a&b: 0 0 0 0 1 0 1 0 0x0a a|b: 1 0 1 0 1 1 1 1 0xaf a^b: 1 0 1 0 0 1 0 1 0xa5 a<<1: 0 1 0 1 0 1 0 0 0x54 b>>2: 0 0 0 0 0 0 1 1 0x03 ~b: 1 1 1 1 0 0 0 0 0xf0 Stroustrup/Programming 22 Bit manipulation Bit Bitwise operations Sign bit 8 bits == 1 byte & (and) val | (or) (or) 0110001101001101 ^ (exclusive or – xor) (exclusive << (left shift) >> (right shift) 0xff: 1 1 1 1 1 1 1 1 ~ (one's complement) 01001101 Basically, what the hardware provides right: right: true false For example void f(unsigned short val) // assume 16-bit, 2-byte short integer // assume { unsigned char right = val & 0xff ; // rightmost (least significant) byte // rightmost unsigned char left = (val>>8) & 0xff ; // leftmost (most significant) byte unsigned // leftmost bool negative = val & 0x8000 ; // sign bit (if 2’s complement) // sign // … } Stroustrup/Programming 23 Bit manipulation Bit Or | 11111111 val Set a bit And & 0xff: 10101010 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 // becomes x |= bit2; // x becomes 8+4+2 // 8+4+2 if (x&bit3) { // is bit3 set? (yes, it is) set? // … // } unsigned char y = x &(bit4|bit2); // y becomes 4 // Flags z = Flags(bit2|bit0); // the cast is necessary because the compiler Flags the // doesn’t know that 5 is in the Flags range doesn’t is range Stroustrup/Programming 24 Bit manipulation Bit 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 25 Unsigned integers Unsigned You can do ordinary arithmetic on unsigned integers Avoid that when you can You can’t completely avoid unsigned arithmetic signed Try never to use unsigned just to get another bit of precision If you need one extra bit, soon, you’ll need another Don’t mix signed and unsigned in an expression Indexing into standard library containers uses unsigned (in my opinion, that’s a design error) vector<int> v; unsigned correct, but pedantic // … for (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) … Yet another way Stroustrup/Programming 26 Complexity Complexity One source of errors is complicated problems Another source of errors is poorly-written code Inherent complexity Incidental complexity Reasons for unnecessarily complicated code Overly clever programmers Undereducated programmers Who use features they don’t understand Who don’t use the most appropriate features Large variations in programming style Stroustrup/Programming 27 Coding standards Coding A coding standard is a set of rules for what code should coding look like look Typically specifying naming and indentation rules Typically specifying a subset of a language Every function must have a comment explaining what it does Often requiring the use of certain libraries E.g., don’t use new or throw to avoid predictability problems E.g., new to Typically specifying rules for commenting E.g., use “Stroustrup” layout E.g., use E.g., use <iostream> rather than <stdio.h> to avoid safety problems E.g., to Organizations often try to manage complexity through Organizations coding standards coding Often they fail and create more complexity than they manage Stroustrup/Programming 28 Coding standards Coding A good coding standard is better than no standard A poor coding standard can be worse than no standard 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 C++ coding standards that restrict programming to something like the C C++ subset do harm subset They are not uncommon All coding standards are disliked by programmers I wouldn’t start a major (multi-person, multi-year) industrial project wouldn’t without one without “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 29 Coding standards Coding Common aims Reliability Portability Maintainability Testability Reusability Extensibility Readability Stroustrup/Programming 30 Some sample rules Some No function shall have more than 200 lines (30 would be even No better) better) Each new statement starts on a new line E.g., int a = 7; x = a+7; f(x,9); E.g., int // violation! violation! No macros shall be used except for source control that is, 200 non-comment source lines using #ifdef and #ifndef using #ifdef #ifndef Identifiers should be given descriptive names May contain common abbreviations and acronyms When used conventionally, x, y, i, j, etc., are descriptive When x, Use the number_of_elements style rather than the numberOfElements style Use number_of_elements numberOfElements Type names and constants start with a capital letter E.g., Device_driver and Buffer_pool E.g., Buffer_pool Identifiers shall not differ only by case E.g., Head and head E.g., Head head // violation! // violation! Stroustrup/Programming 31 Some more sample rules Some Identifiers in an inner scope should not be identical to identifiers Identifiers in an outer scope in E.g., int var; E.g., int // violation: var is not initialized var Casts should be used only when essential Code should not depend on precedence rules below the level of Code arithmetic expressions arithmetic E.g., x = a*b+c; E.g., a*b+c; if( a<b || c<=d) // violation: var hides var var Declarations shall be declared in the smallest possible scope Variables shall be initialized E.g., int var = 9; { int var = 7; ++var; } E.g., int // ok // ok // violation: parenthesize (a<b) and (c<=d) // violation: (c<=d) Increment and decrement operations shall not be used as Increment subexpressions subexpressions E.g., int x = v[++i]; // violation (that increment might be overlooked) E.g., int violation Stroustrup/Programming 32 An example of bit manipulation An The Tiny Encryption Algorithm (TEA) Don’t look too hard at the code (unless you happen to need a Don’t good simple encryption algorithm for an application); it’s simply to give you the flavor of some bit manipulation code simply It takes one word (4 bytes at a time) Originally by David Wheeler E.g., 4 characters from a string or an image file E.g., characters 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 Without manipulation code can look. This code is not meant to be selfnot explanatory. Stroustrup/Programming 33 TEA 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 34 TEA TEA void decipher( const unsigned long *const v, unsigned long *const w, const unsigned long * const k) { unsigned long y = v[0]; unsigned 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 // sum 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 35 35 ...
View Full Document

{[ snackBarMessage ]}