360 likes | 469 Views
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 *.
E N D
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 shareworldwide * SolutionsforInnovation Analog andPower Devices#1 Market sharein low-voltageMOSFET** ASIC, ASSP& MemoryAdvanced and proven technologies * 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 shareworldwide * SolutionsforInnovation Analog andPower Devices#1 Market sharein low-voltageMOSFET** ASIC, ASSP& MemoryAdvanced and proven technologies * 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
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!
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 • 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
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
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()?
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
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.)
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!
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 has to happen, no matter what? • What interrupt handler can be interrupted? • What is the frequency of interrupts? • What 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?
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
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
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
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
“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
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
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
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
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
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…
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
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
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
Questions? Contact Info: Vin D’Agostino BNS Solutions vindag@bnssolutions.com +1.508.668.6132