ID A20C: Using “C” for Embedded Design What to know as you take the plunge into “C” BNS Solutions Vin D’Agostino Principal 14 October 2010 Version: 1.1 Renesas Technology and Solution Portfolio Microcontrollers & Microprocessors #1 Market share worldwide * ASIC, ASSP & Memory Advanced and proven technologies Solutions for Innovation Analog and Power Devices #1 Market share in low-voltage MOSFET** * MCU: 31% revenue basis from Gartner "Semiconductor Applications Worldwide Annual Market Share: Database" 25 March 2010 ** Power MOSFET: 17.1% on unit basis from Marketing Eye 2009 (17.1% on unit basis). Renesas Technology and Solution Portfolio Microcontrollers & Microprocessors #1 Market share worldwide * Solutions for Innovation ASIC, ASSP & Memory Advanced and proven technologies Analog and Power Devices #1 Market share in low-voltage MOSFET** * MCU: 31% revenue basis from Gartner "Semiconductor Applications Worldwide Annual Market Share: Database" 25 March 2010 ** Power MOSFET: 17.1% on unit basis from Marketing Eye 2009 (17.1% on unit basis). 3 Agenda A quick Journey into Embedded C Setting up Projects in HEW Managing the System and the Solution Layer Drawing Documentation Conclusions A quick Journey into Embedded C 5 Why C? Why not assy? Why not C++? C is not a magic bullet: there is nothing you can do in C that you can’t do in assy, but most likely won’t C “encourages” you to write structured code Structured code is inherently more Maintainable Reusable Documentable C “modules” can be written for one processor family and reused, mostly without major modification, on another family C gives you the advantages of a higher level language without the burden of much overhead Flexible preprocessor directives can be used for conditional inclusion and code placement Real library of public domain algorithms –but– be careful! 6 A brief C overview Two books The C Primer Plus, Sams (ISBN-13: 978-0672326967) The C Programming Language, K&R (ISBN: 0-13-110362-8 ) History Bell Labs Designed for writing OS’s and compilers 7 Code always starts at “main()” Some small initialization code is automatically generated Pre-processor scan “manages” compilation process Compiles to re-locatable code Links to absolute memory space Extensible language Common myths about C Code written in C is always significantly larger than in assy Code written in C always runs slower than in assy C code does not run well on processors with small RAM space C compilers are expensive Embedded C code is not transportable between hardware platforms C is a “write only” language: who can read that mess? C makes it harder to get to the hardware than assy 8 Why is writing C for small system different? Code for small systems must take memory usage (RAM & ROM), machine cycles, and library usage into account There is typically no real “API” that is written to – the application addresses hardware directly Often, there is no OS or scheduler – the application itself is the OS Often the understanding of physical movement of bits can result in more compact and responsive code Reusable “modules” are inherently more granular and focused e.g. Multiple versions of “readA2D()” one for each processor family Header files may have 1 or 2 lines of code 9 Why is writing C for small system different? Debugging has it’s own quirks, hardware interaction Interrupt handling can get “interesting” when 1 line of C becomes 20 lines of assy main() procedure typically never terminates Why use local variables in main()? What happens if it DOES terminate What calls main()? 10 Setting up Projects in HEW 11 Structuring the project All global variables in a single file to be managed appropriately Liberal use of header files for maintaining literal values and compile “switch” conditions All source files in a single directory – unless there is real need to subdivide (common files, external sources, etc) Make sure that the tools are set up properly Use “sessions” and “configurations” within HEW to manage what is compiled when, and how Place all ISR code in a single file, calling functions as appropriate Divide the code by the hardware peripherals you will be utilizing Place all hardware interaction code in a single file, or file hardware specific C & H files 12 Files: What goes where? “globals.c” for all global variables and constants “extern.h” a parallel file to globals.c used to “expose” each source file to the global variables/constants “main.c” or “<projectName>.c” holds “main() procedure <peripheralType>.c used to hold code that processes peripheral information e.g. “keyboard.c” e.g. “serial.c” parallel named header files (e.g. “keyboard.h”) used to hold compilation switch values #define constant definitions Data structures All code that interfaces with hardware in a separate file “HAL.c” (If you choose the “file per peripheral” structure, 2 C files, one for “algorithmic” code and one for hardware.) 13 Let’s look at some code… 14 Global variable are NOT evil Global variables are used to link mainline code with ISRs Global variables can reduce stack size and execution time Global variables can be used to house cross-procedure values that would cost time and space to pass Global variables can be used instead of local variables in main() to reduce the size of the stack [don’t forget, main() never terminates, so those variables are always there!] Global variables can be a more convenient place to hold status flags Just, for heaven’s sake, name them well! 15 Managing the System and the Solution 16 Interrupts and mainline code Rule # 1: Do as little as possible in interrupts Rule # 2: Rule # 1 can be broken Rule # 3: Set ISR priorities appropriately What What What What has to happen, no matter what? interrupt handler can be interrupted? is the frequency of interrupts? is the interrupt processing time? Make sure that interrupts using global variables actually have access to the whole value What does main() look like? Only function calls? Giant switch statement? Inline code? 17 Laying out the code design Divide the task into a minimum of 4 layers: Application (top layer) Processing, filters, and drivers (layer 2) Hardware Abstraction Layer (layer 1) Hardware layer (layer 0) Write a “throwaway” main.c file, or include (inline) a CodeTest.c” file Start with layer 1 and “expose” the upper layers to the hardware, but in an abstracted way. This will give the code in layer 2 maximum reusability Move to writing isr code Write code in layer 2 to expose all needed information for “application level” decisions Write application code, calling only layer 2 code and using global variables 18 Layer drawings Can aid in overall organization of code and thoughts Can support “top-down design” “bottom up implementation” Can help highlight areas where development can be divided amongst colleagues Can show logical test interfaces in code Can be used to show hardware/firmware interaction Convenient documentation tool 19 Example Layer drawing… 20 Procedure performance How are procedures affected by code structure? Loops and tests switch vs. if-then-else Syntax of literals Intermediate value casting Use of logical vs. arithmetic operators Values of denominators Order of operation – don’t assume left to right with communitive operators/operations How are procedures affected by variable declaration? Source and destination variables and types Global vs. stack Intermediate variable optimization 21 Functions or procedures? Functions return values… but… Procedures can take the resultant variable as a parameter Values can also be global variables Functions are more easily transportable… usually Functions return a single value (which can also be a pointer, a structure, etc.) Decisions are based on stack size, execution speed, and overall code design Consider function/procedure tables with pointers to make state machines more easily changed, and typically smaller Function/procedure based state machines can run faster than interrupts 22 “That’s real hardware ya got there, buddy…” Direct manipulation of registers, bits, pins Memory is hardware, too – use logical operators (and, or, shift, etc.) to save code space Write bit masks in a way that makes logical sense and can be “self documenting processFlags |= KEYBOARD_TIMER_EXPIRED; processFlags &= ~KEYBOARD_TIMER_EXPIRED; Observe rollover issues when processing 16 bit hardware registers Don’t “wait” for register flags unless you have to We live in an analog world, and sometimes it ain’t pretty… Hardware filtering may not be enough Debugging can be tough if you hit a breakpoint with 10A flowing 23 printf() IS evil printf and sprintf are pieces of general code not typically optimized for small systems Write your own, knowing that you (typically) have a limited number of things to say Use a “debug dump” for tracing critical values during execution LCD module and LCD peripheral code can be more easily written to focus on what you need, and will be “lighter” An “encapsulated” packeted protocol can be much more efficient, and writing the code on the PC side is a breeze 24 Let’s look at some code… 25 What library routines are you REALLY using? Look at variables Check code size every compile (I like to scratch the last value on a pad next to my computer) Look at literals: 10 is different than 10. and 0x10 can be different than 0x0010 What advanced arithmetic/trigonometric functions are you using? Are you processing strings? Do you really need floating point? (Fred * 1000) / 256 is the same as Fred * 3.906 (Fred * 1000) >> 8 is even better All these things can include libraries that you hadn’t intended 26 To optimize or not to optimize? That is the question Optimized code can change more severely from toolchain rev to toolchain rev Optimizing for speed usually increases size Optimizing for size usually decreases speed Optimization can reduce RAM footprint Precompiled code will typically not be re-optimized Try different combinations of optimization levels Properly written, appropriately optimized code can be smaller than assy code you’d write on your own, and still be readable 27 Can variable declarations help code efficiency? “volatile” keyword Structures and unions “static” keyword Code size for variable types What libraries are pulled in? Does “casting” help or hurt? Pointers 28 Documentation 29 Flowcharting: Nassi & Schneidermann, not songwriters Structured flowcharting Code flow always enters from the top Code flow always exits from the bottom Limited number of code structure types Sequential statement Loop – test at top Loop – test at bottom Conditional if-then-else Switch – multiple choice Statements embed into a graphic path Great documentation tool Code can be written (almost) directly from chart Let’s look at one… 30 Commenting Variable, procedure/function name, macros can have very descriptive names to make much of the code self documenting Many companies have coding standards; if they cover the C language, try to use them Each piece of code should at least have a header Each file should at least have a header Break up parameters one line at a time; add comments on each line about the parameter 31 How does all this fit with Design flow? Big topic, too big to fully cover here, but… Waterfall N-S flowcharting and layer diagram done first as a result of spec Reviewed with design team and “product manager” Hardware implementation proven first Documentation done as code is implemented, bottom to top Agile/Iterative Hardware can be done in first or second sprint Some code can be proven on a dev kit or similar platform before HW is up Enough of the hardware specific code needs to be up and running in one way or another to start implementing stories Code and hardware development from initial platform can be developed in sprints as any code development 32 Conclusions C can be used to write small footprint efficient code for small platforms C can help manage global variables to minimize risk C can make highly optimized code on the assy level readable C can allow you to generate reusable code from a processor, algorithm, and peripheral perspective C, and the associated structured documentation tools, can increase efficiency when working as a team C techniques can actually augment understanding of the firmware/hardware interface Good practice naming conventions and style can produce “self documenting” code 33 Contact Info: Vin D’Agostino BNS Solutions vindag@bnssolutions.com +1.508.668.6132 Thank You