HU powerpoint-presentatie

HU powerpoint-presentatie

Objects? No Thanks! Using C++ effectively on small microcontrollers Wouter van Ooijen MSc Hogeschool Utrecht, Netherlands, senior lecturer Computer Engineering [email protected] BeC++ 2016-06-30 Embedded a meaning Means: part of something larger (not stand-alone) subservient to that larger thing with a dedicated task (not general-purpose). Note that this does not imply a particular type of hardware or style of programming. Often computer hardware is used for embedded systems that is the same or very similar to what is used on a desktop. C++ on small microcontrollers -2 Embedded some differences The computer hardware is part of the product

The price of the hardware is reflected in the price of the product. There is economic pressure to be efficient (use the cheapest posible hardware). Often the larger thing has (hard) real-time requirements. The embedded system must (always) be fast enough. Often the system is used to control real hardware. Failures have interesting consequences (up to loss of life). C++ on small microcontrollers -3 Real-Time Means: utility depends critically on some timing parameter. Variations (terms vary): Soft real-time: usefulness degrades (rapidly) Firm real-time: may occasionally be late or lower-quality C++ on small microcontrollers -4

Soft real-time usefulness degrades (rapidly) beyond the deadline C++ on small microcontrollers (if there was any to begin with) -5 Firm real-time If the perfect result cant be calculated in time give what you have, but be on time! C++ on small microcontrollers -6 Hard real-time (and mission-critical) Late might even be worse than not at all C++ on small microcontrollers -7 Embedded a wide range of seriousness Consequently, a wide range of development styles:

JBF*, Agile, prototyping, waterfall, C++ on small microcontrollers * Jan Boere Fluitjes: Dutch saying, meaning roughly casual, with as little effort as possible -8 C++ in (very) serious embedded systems CppCon 2014: Mark Maimone "C++ on Mars: Incorporating C++ into Mars Rover Flight Software" CppCon2014: Bill Emshoff "Using C++ on Mission and Safety Critical Platforms" C++ on small microcontrollers -9 Embedded a wide range of hardware capabilities 1Kb 1Mb

1Gb C++ on small microcontrollers - 10 Embedded a wide range of hardware capabilities 1Kb 1Mb 4-bit 1Gb 64-bit 8-bit : 8051, PIC, AVR, No full standard C/C++ 16-bit : MSP430, PIC, 32-bit : ARM, MIPS, Intel, C++ on small microcontrollers

- 11 Embedded a wide range of hardware capabilities 1Kb 1Mb 1Gb Wide range of support software: Bare metal: libraries, but no OS RTOS Desktop OS: Linux Windows C++ on small microcontrollers - 12

Some small micro-controllers PIC12F200 8-bit CPU 256 Flash 16 RAM [email protected] As yet no C++ compiler*: 8-bits crazy CPU architecture MKE04Z8VTG 4 32-bit CPU 8k Flash 2k RAM [email protected] A low-end chip for C++: 32 bits Cortex-M0 GCC * There are 8-bit CPUs that do support C++ (well, most of it).

Objects? No Thanks! - 13 Micro-controllers are everywhere Objects? No Thanks! - 14 Small micro-controller programming Typically Applications are small Volumes are high Worst-case timing constraints must be met (average timing is not important) User-requirements are fixed (but hardware might change over time) C dominates (even assembler is still used) Objects? No Thanks! - 15 Small microcontroller economics n

Product cost scales with use of resources: CPU speed (power consumption!!) code size (Flash) data size (RAM) Those prices are payed by the manufacturer, not by the end user (as for desktop software). Pressure on the developers to reduce resource use: every data byte or instruction counts (even if only in the perception of the managers). Objects? No Thanks! - 16 Embedded programming languages VDC survey 2010; languages *used*, != LOC C++ on small microcontrollers - 17 Use across the spectrum 1Mb 1Kb

Assembly 1Gb C C++, C, Java, C#, Perl, Python, C++ on small microcontrollers - 18 Code re-use Is hindered by Small size, so (perceived) benefit is small Code is often written by electrical engineers Lack of abstraction mechanisms in C Each application has unique aspects, down to the lowest levels Objects? No Thanks! - 19 Language use across the spectrum 1Mb

1Kb 1Gb C++ gap Assembly C C++, C, Java, C#, Perl, Python, C++ on small microcontrollers - 20 So why should C++ be used? As a better C

Enables other programming styles (same programming style, less room for errors) (OO, functional, templates, . . .) More opportunities for (efficient) code re-use Objects? No Thanks! - 21 But not like C++ on a desktop

Performance is different Heap: forget it Floating point: often not practical Exceptions: debatable C++ standard library: large parts are unusable (heap, float/double, worst-case performance) OO at run-time (virtuals): often not needed ROM is scarce, RAM even more so std::ostream, std::cout ?? C++ on small microcontrollers - 22 Heap The heap is flexibility with respect to the amount of data, at the cost of (some) unpredictability in run-time and maximum available memory (fragmentation). A typical small embedded system has a rigidly prescribed task, including the size of the data involved Must meet real-time constraints Should be certain to meet work OK all the time (not just for a certain sequence of actions).

A heap and a small embedded system dont match very well. Better: Global allocation (!) Fixed size pools or (better?) fixed size containers on the stack Avoiding some dangling pointer is a nice extra C++ on small microcontrollers - 23 Exceptions Exceptions are great to handle a local problem that requires a (more) global response. A small system often has a rather simple, rigidly defined task there are no exceptions, only different situations. No heap one reason less to use exceptions.

Exception implementation often uses the heap. Straw man: exceptions are slow and have unpredictable timing. C++ on small microcontrollers - 24 Floating point FP is useful when a wide dynamic range is needed. For an embedded application the ranges are often very well known. Small micro-controllers often dont have a hardware FPU. A software FP library Is considerably slower Generally not needed (value range is known) Takes up ROM C++ on small microcontrollers - 25 C++ test case: blink a LED The embedded equivalent of Hello world Objects? No Thanks! - 26

Blink a LED in C // return the pointer to an IO port related register #define GPIOREG( port, offset ) \ (*(volatile int *)( 0x50000000 + (port) * 0x10000 + (offset))) // set the pin port.pin to value #define PIN_SET( port, pin, value ) \ { GPIOREG( (port), 0x04 << (pin) ) = (value) ? -1 : 0; } int main(){ for(;;){ PIN_SET( 1, 0, 1 ); delay(); PIN_SET( 1, 0, 0 ); delay(); } } Some ugly details (initialization, timing, ) have been omitted to concentrate on making the pin high and low. .L97: ldr

r4, .L98 // mov r3, #1 // neg r0, r3 str r0, [r4] // bl delay mov r1, #0 str r1, [r4] // bl delay b .L97 .align 2 .L98: .word 1074036740 get the I/O register address get -1 into r3 store -1 in the I/O register store 0 in the I/O register

Objects? No Thanks! - 27 PIN_SET( 1, 0, 1 ) // set the pin port.pin to value #define PIN_SET( port, pin, value ) \ { GPIOREG( (port), 0x04 << (pin) ) = (value) ? -1 : 0; } Abstraction of an I/O pin + Efficient - Cant easily be replaced or augmented by the user - It is a macro! (scope, textual parameters, ) Objects? No Thanks! - 28 Classic OO pin abstraction struct pin_out { virtual void set( bool ) = 0; }; volatile int & gpioreg( int port, int offset ){ return * (volatile int *) ( 0x50000000 + port * 0x10000 + offset ); } void blink( pin_out & pin ){

struct lpc1114_gpio : public pin_out { for(;;){ const int port, pin; pin.set( 1 ); delay(); lpc1114_gpio( int port, int pin ) pin.set( 0 ); : port{ port }, pin{ pin }{} delay(); } void set( bool x ) override { } gpioreg( port, 0x04 << pin ) = x ? -1 : 0; } int main(){ }; lpc1114_gpio led( 1, 0 ); blink( led ); } Abstract class with virtual functions Objects? No Thanks! - 29 Metrics for set(1) + set(0) + support code

PIN_SET( 1, 0, 1 ); PIN_SET( 1, 0, 0 ); Code (bytes Flash) RAM CPU cycles C (macro) 16 0 ~9 pin.set( 1 ); pin.set( 0 ); C++ (virtual functions) 68 12 ~ 56 What has gone wrong?

Objects? No Thanks! - 30 Generated code (C++ OO-style) push {r4, lr} mov r4, r0 .L12: ldr r3, [r4] mov r0, r4 ldr r3, [r3] mov r1, #1 blx r3 bl _Z5delayv ldr r3, [r4] mov r0, r4 ldr r3, [r3] mov r1, #0 blx r3 bl _Z5delayv b .L12

void blink( pin_out & pin ){ for(;;){ pin.set( 1 ); delay(); pin.set( 0 ); delay(); } } int main(){ lpc1114_gpio led( 1, 0 ); blink( led ); } ldr r3, .L14 add r0, sp, #4 str r3, [sp, #4] mov r3, #1 str r3, [sp, #8] mov r3, #0 str r3, [sp, #12] bl _Z5blinkR7pin_out .align 2 .L14: .word

1342177284 18 _ZN12lpc1114_gpio3setEb: ldr r3, [r0, #4] push {r4, lr} mov r4, #160 lsl r4, r4, #7 add r2, r3, r4 ldr r3, [r0, #8] mov r0, #4 lsl r2, r2, #16 lsl r0, r0, r3 add r3, r2, r0 neg r1, r1 str r1, [r3] pop {r4, pc} 26 24

Objects? No Thanks! - 31 Why so much code? Run-time polymorphism: Connection between operation and implementation is made at run time This takes code, CPU cycles, even some RAM, and blocks optimizations Fixed-hardware embedded systems dont need such run-time flexibility, but Efficient use of libraries does require compile-time flexibility Objects? No Thanks! - 32 Alternative: compile-time polymorphism

Static classes (or structs) can be used as compile-time encapsulation of data and operations. Template parameters can be used to pass such an encapsulation to another one. These are compile-time-only actions, hence fully visible to the optimizer. Objects? No Thanks! - 33 Run-time polymorphism Compile-time polymorphism struct pin_out { virtual void set( bool ) = 0; }; struct pin_out_archetype { typedef void has_pin_out; static void set( bool value ){} }

struct lpc1114_gpio : public pin_out { lpc1114_gpio( . . . ) . . . void set( bool x ) override { . . . } }; template< int port, int pin > struct lpc1114_gpio : public pin_out_archetype { static void set( bool value ){ . . . } }; struct blink { pin_out & pin; blink( pin_out & pin ): pin( pin ){} void run(){ . . . pin.set( 1 ); } } template< typename pin > struct blink { void run(){ . . .

pin::set( 1 ); } } int main(){ blink( lpc1114_gpio( 1, 2 )).run(); } int main(){ blink< lpc1114_gpio< 1, 2 >>::run(); } As before, some ugly details (initialization, timing, ) are omitted. Objects? No Thanks! - 34 Generated code (C versus C++ C-T-P) // C with macros .L97: ldr r4, .L98 mov r3, #1 neg

r0, r3 str r0, [r4] bl delay mov r1, #0 str r1, [r4] bl delay b .L97 // C++ with compile-time polymorphism .L3: ldr r4, .L5+12 mov r3, #1 neg r3, r3 str r3, [r4] ldr r0, .L5+16 bl

_...waiting_324waitEj mov r3, #0 str r3, [r4] ldr r0, .L5+16 bl _...waiting_324waitEj b .L3 Code (bytes Flash) RAM C 16 0 C++ 16 0 CPU cycles

~9 ~9 Objects? No Thanks! - 35 Blink: some (ugly?) details #include "targets/lpc1114fn28.hpp" typedef hwcpp::lpc1114fn28<> target; template< typename arg_pin, typename arg_timing > struct blinking { int main(){ hwcpp::blink< target::gpio_1_2, target::waiting >::run(); } #include "targets/lpc1114fn28.hpp" typedef arg_pin >target; pin;

typedefpin_out_from< hwcpp::lpc1114fn28<> typedef waiting_from< arg_timing > timing; Type narrowing int main(){ typedef typename timing::duration duration; hwcpp::blink< target::gpio_0_0, target::waiting >::run(); } static void run( const duration t = duration::ms( 500 ) ){ timing::init(); pin::init(); for(;;){ pin::set( 1 ); timing::wait( t / 2 ); pin::set( 0 ); timing::wait( t / 2 ); } }

Explicit initialization }; Objects? No Thanks! - 36 Four pin archetypes struct pin_in_archetype { typedef void has_pin_in; static void init(); static bool get(); }; struct pin_out_archetype { typedef void has_pin_out; static void init(); static void set( bool value ); }; struct pin_in_out_archetype { typedef void has_pin_in_out; static void init(); static void direction_set_input(); static void direction_set_output();

static bool get(); static void set( bool value ); }; struct pin_oc_archetype { typedef void has_pin_oc; static void init(); static bool get(); static void set( bool value ); }; Objects? No Thanks! - 37 Type narrowing class target { typedef . . . pin_a0; } class target { typedef . . . pin_a0; } typedef target::pin_a0 alarm; typedef pin_out_from< target::pin_a0 > alarm;

int main(){ alarm::init(); alarm::direction_set_output(); alarm::set( false ); int main(){ alarm::init(); alarm::direction_set_output(); alarm::set( false ); if( . . . ){ alarm::set( true ); } } if( . . . ){ alarm::set( true ); }

} The template parameter is type-checked The template adapts to the parameter type Initialization is complete The code cant accidentally use an inappropriate method Objects? No Thanks! - 38 pin_out_from< . . . > template template< class unsupported, class dummy = void > struct pin_out_from { static_assert( sizeof( unsupported ) == 0, . . . ); }; template< class unsupported, pin > struct class pin_out_from pin,>typename pin::has_pin_out > : dummy =

{ static class void init(){ pin::init(); } template< pin > struct pin_out_from < pin, typename pin::has_pin_out > : static pin_out_archetype void set( bool value ){ pin::set( value ); } public }; { static void init(){ pin::init(); } template< classset( pin bool > struct pin_out_from < value pin, typename pin::has_pin_oc > : static void

value ){ pin::set( ); } template< class unsupported, class dummy = void > struct pin_out_from { }; public pin_out_archetype { static_assert( sizeof( unsupported ) == 0, . . . ); }; static template< static public }; { void init(){

pin::init(); } class pin > struct pin_out_from < pin, typename pin::has_pin_oc > : void set( bool value ){ pin::set( value ); } pin_out_archetype static template< static }; public { static static };

void init(){ pin::init(); } classset( pin bool > struct pin_out_from < value pin, typename pin::has_pin_in_out > : void value ){ pin::set( ); } pin_out_archetype void init(){ pin::init(); pin::direction_set_output(); } void set( bool value ){ pin::set( value ); } Objects? No Thanks! - 39 invert< . . . > Dont say it in a comment decorator namespace target { typedef . . . pin_a0;

} typedef target::pin_a0 alarm_led; // the alarm LED pin is active low constexpr bool alarm_led_active = false; int main(){ alarm_led::set( ! alarm_led_active ); if( . . . ){ alarm_led::set( alarm_led_active ); } } Say it in the code namespace target { typedef . . . pin_a0; } typedef invert< target::pin_a0 > alarm_led; int main(){ alarm_led::set( false ); if( . . . ){ alarm_led::set( true ); } } Objects? No Thanks! - 40

Pin invert< . . . > template template< class unsupported, class dummy = void > struct invert { static_assert( sizeof( unsupported ) == 0, ". . ." ); }; template< class pin > struct invert< pin, typename pin::has_pin_in > : public pin_in_archetype { static void init(){ pin::init(); } static bool get(){ return ! pin::get(); } }; template< class pin > struct invert< pin, typename pin::has_pin_out > : public pin_out_archetype { static void init(){ pin::init(); } static void set( bool x ){ pin::set( ! x ); } }; template< class pin > struct invert< pin, typename pin::has_pin_in_out > : public pin_in_out_archetype { static void init(){ pin::init(); } static void direction_set_input(){ pin::direction_set_input(); } static void direction_set_output(){ pin::direction_set_output(); } static void set( bool x ){ pin::set( ! x ); } static bool get(){ return ! pin::get(); } }; template< class pin > struct invert< pin, typename pin::has_pin_oc > : public pin_oc_archetype { static void init(){ pin::init(); } static void set( bool x ){ pin::set( ! x ); } static bool get(){ return ! pin::get(); } };

Often: ZERO cost! Objects? No Thanks! - 41 Some more pin & port decorators // create the stated pin or port type from p pin_in_from< p > pin_out_from< p > pin_in_out_from< p > pin_oc_from< p > port_in_from< p > port_out_from< p > port_in_out_from< p > port_oc_from< p > // create a port of the stated type from pins port_in_from_pins< p, ... > port_out_from_pins< p, ... > port_in_out_from_pins< p, ... > // invert the value read from or written to p invert< p > // pin or port that writes to all pins or ports all< p, ... >

Objects? No Thanks! - 42 Using static class templates: consequences (1) Abstraction tool is the class template with only static contents (classes, methods, attributes) Composition is by template instantiation Method call syntax is class::method() instead of object.method() Header-only

Objects? No Thanks! - 43 Using static class templates: consequences (2) No objects (of such classes) are created No memory management, no dangling references Sharing of identical constructs is automatic No automatic construction: explicit init() calls Overhead can be zero Objects? No Thanks! - 44 Long term view A use case

Write library code for reading the temperature from an LM75 chip (I2C interface). Write it once and for all. What should be in this code? Getting the data bits from the LM75 (using I2C) Converting the data bits to a temperature Maybe detecting errors in the data bits (passing I2C errors along?) What should NOT be in this code? I/O pin handling I2C protocol Timing Conversion to the requested datatype (int, float, double, fixed-point, ) Conversion to the requested unit (Kelvin, Celcius, Fahrenheit, ) Floating point calls Objects? No Thanks! - 45 Next steps Identify and/or implement abstraction(s) for

Values (units, fixed-point) Timing (including multithreading) Error handling Handle parallel hierachies (mix with objects) Objects? No Thanks! - 46 Devirtualization? Compilers are starting to do devirtualization (as part of whole-program optimization). How would perfect devirtualization compare to the static-class-template approach? Objects + ideal devirtualization Static class templates Run-time allocation Compile/link time allocation Global, stack or heap allocation

Only global allocation Danger of dangling references No such danger Run-time flexibility Requires extra effort Sharing requires planning Sharing is automatic (prevention is tricky) Well-known syntax & style Unfamiliar syntax & style Objects? No Thanks! - 47 C++ language issues

Class templates and plain classes cant have the same name. The syntax for using static attributes of class templates can be horrible. A LOT of template and typename prefixes can be required to disambiguate (template parameter-) dependent names. C++0x11 has override for virtual methods, but there is no equivalent for static methods. Objects? No Thanks! - 48 Summary Current C++ libraries and programming practices are often not optimal for very small systems. Compile-time polymorphism using static class templates (no objects!) Can be as efficient as C macros.

Has an abstraction power comparable in power but very different in nature to classic run-timeobjects-based OO. There is a lot of interesting work to do to create C++ libraries that help programming very small systems. Objects? No Thanks! - 49

Recently Viewed Presentations

  • Sediment Transport by Water - Durham University

    Sediment Transport by Water - Durham University

    Sediment Transport by Water Theory Processes Rainsplash overland flow transport Rilling and gullying ... stress-strain reln more complicated large spatial variation morphology adjusted to extreme events Extreme events Do majority of work because: larger particle size transmission losses poor ...
  • Exploring Literary Genres - Michigan State University

    Exploring Literary Genres - Michigan State University

    Exploring Genres We use genres on a daily basis. Genres are just ways of classifying and organizing what we encounter. * Let's say you have to decide where to go for dinner. There are different types - or genres -...
  • Miss Viggianos Science Class Monday 11/18 Tuesday 11/19

    Miss Viggianos Science Class Monday 11/18 Tuesday 11/19

    Bingo & Challenge. HW: Study for Quiz tomorrow. Structure of Atoms. QUIZ! Intro to the Periodic Table "The Power of the Periodic Table" ... Color and label the Periodic Table ...
  • Chemistry for Changing Times, 11th edition John W.

    Chemistry for Changing Times, 11th edition John W.

    Chemistry for Changing Times, 11th edition John W. Hill and Doris K. Kolb Chapter 16 Food: Molecular Gastronomy James A. Noblet California State University
  • Prescription Drug Abuse EPI Profile Presentation

    Prescription Drug Abuse EPI Profile Presentation

    Arrest Rates, per 1,000 Population, for Possession and Sale/Manufacture of "Other Drugs" (Barbiturates and Benzedrine), Indiana and U.S. (Uniform Crime Reporting Program, 1999-2007) Source: National Archive of Criminal Justice Data, Inter-university Consortium for Political and Social Research, University of Michigan,...
  • CHARACTERISTICS OF DERIVATIVES - Cengage Learning

    CHARACTERISTICS OF DERIVATIVES - Cengage Learning

    The buy or sell price is referred to as the strike price or exercise price A call option allows the holder to buy an underlying whereas a put option allows the holder to sell an underlying The holder of an...
  • Russia and the Republics Most of Russian cities

    Russia and the Republics Most of Russian cities

    Architecture Music Tchaikovsky The Nutcracker Swan Lake Sports Ice Hockey "Miracle" Basketball Tennis Maria Sharapova Anna Kournikova Current Issues & Events Demographic Changes: Low birthrates among Russians and high birthrates among Muslim populations are changing several nations.
  • Major League Baseball

    Major League Baseball

    No. of Wins for 2007. Boston 96 New York 94 Toronto 83 Baltimore 69 Tampa Bay 66