19

Click here to load reader

C for Microcontrollers

Embed Size (px)

Citation preview

Page 1: C for Microcontrollers

‘C’ for Microcontrollers,Just Being Efficient

Lloyd Moore, President

[email protected]

Seattle Robotics Society 9/15/2012

Page 2: C for Microcontrollers

Agenda

Microcontroller ResourcesKnowing Your Environment Memory UsageCode StructureOptimizationSummary

Page 3: C for Microcontrollers

Disclaimer

Some microcontroller techniques necessarily need to trade one benefit for another – typically lower resource usage for maintainability

Point of this presentation is to point out various techniques that can be used as needed

Use these suggestions when necessary Feel free to suggest better solutions as we go

along

Page 4: C for Microcontrollers

Microcontroller Resources

EVERYTHING resides on one die inside one package: RAM, Flash, Processor, I/O

Cost is a MAJOR design consideration Typical costs are $0.25 to $25 each (1000’s)

RAM: 16 BYTES to 256K Bytes typical Flash/ROM: 384 BYTES to 1M Byte Clock Speed: 4MHz to 175MHz typical

Much lower for battery saving modes (32KHz) Bus is 8, 16, or 32 bits wide Have dedicated peripherals (MAC, Phys, etc)

Page 5: C for Microcontrollers

Power Consumption

Microcontrollers typically used in battery operated devices

Power requirements can be EXTREMELY tightEnergy harvesting applicationsLong term battery installations (remote

controls, hard to reach devices, etc.)EVERY instruction executed consumes

power, even if you have the time and memory!

Page 6: C for Microcontrollers

Know Your Environment

Traditionally we ignore hardware detailsNeed to tailor code to hardware

availableSpecialized hardware MUCH more efficient

Compilers typically have extensions Interrupt – specifies code as being ISRMemory model – may handle banked

memory and/or simultaneous access banksMultiple data pointers / address generators

Debugger may use some resources

Page 7: C for Microcontrollers

Memory Usage

Put constant data into program memory (Flash/ROM) Alignment / padding issues

Typically NOT an issue, non-aligned access ok Avoid dynamic memory allocation, even if available

Take extra space and processing time Memory fragmentation a big issue

Use and reuse static buffers Reduces variable passing overhead Allows for smaller / faster code due to reduced indirections Does bring back over write bugs if not done carefully More reliable for mission critical systems

Use the appropriate variable type Don’t use int and double for everything!! Affects processing time as well as storage

Page 8: C for Microcontrollers

C99 Datatypes – inttypes.h

int8_t, int16_t, int32_t, int64_tuint8_t, uint16_t, uint32_t, uint_64_t

Avoids the ambiguity of int and uint when moving code between processors of different native size

Makes code more portable and upgradable over time

Page 9: C for Microcontrollers

Char vs. Int Increment on 8051

char cX;cX++;

000A 900000 MOV DPTR,#cX000D E0 MOVX A,@DPTR000E 04 INC A000F F0 MOVX @DPTR,A

6 Bytes of Flash 4 Instruction cycles

int iX;iX++;

0000 900000 MOV DPTR,#iX0003 E4 CLR A0004 75F001 MOV B,#01H0007 120000 LCALL ?C?IILDX

10 Bytes of Flash + subroutine overhead

Many more than 4 instruction cycles with a LCALL

Page 10: C for Microcontrollers

Code Structure

Count down instead of up Saves a subtraction on all processors Decrement-jump-not-zero style instruction on some

processors

Pointers vs. array notation Generally better using pointers

Bit Shifting May not always generate what you think May or may not have barrel shifter hardware May or may not have logical vs. arithmetic shifts

Page 11: C for Microcontrollers

Shifting Example on 8051

cX = cX << 3;

0006 33 RLC A0007 33 RLC A0008 33 RLC A0009 54F8 ANL A,#0F8H

Constants turn into seperate statements

Variables turn into loops

Both of these can be one instruction with a barrel shifter

cA = 3;cX = cX << cA;

000B 900000 MOV DPTR,#cA000E E0 MOVX A,@DPTR000F FE MOV R6,A0010 EF MOV A,R70011 A806 MOV R0,AR60013 08 INC R00014 8002 SJMP ?C00050016 ?C0004:0016 C3 CLR C0017 33 RLC A0018 ?C00050018 D8FC DJNZ R0,?C0004

Page 12: C for Microcontrollers

Indexed Array vs Pointer on M8C

ucMode = g_Channels[uc_Channel].ucMode;

01DC 52FC mov A,[X-4] 01DE 5300 mov [__r1],A 01E0 5000 mov A,0 01E2 08 push A 01E3 5100 mov A,[__r1] 01E5 08 push A 01E6 5000 mov A,0 01E8 08 push A 01E9 5007 mov A,7 01EB 08 push A 01EC 7C0000 xcall __mul16 01EF 38FC add SP,-4 01F1 5F0000 mov [__r1],[__rX] 01F4 5F0000 mov [__r0],[__rY] 01F7 060000 add[__r1],<_g_Channels 01FA 0E0000 adc[__r0],>_g_Channels 01FD 3E00 mvi A,[__r1] 01FF 5403 mov [X+3],A

ucMode = pChannel->ucMode;

01ED 5201 mov A,[X+1] 01EF 5300 mov [__r1],A 01F1 3E00 mvi A,[__r1] 01F3 5405 mov [X+5],A

Does the same thing Saves 29 bytes of memory AND a

call to a 16 bit multiplication routine! Pointer version will be at least 4x

faster to execute as well, maybe 10x Most compilers not this bad – but you

do find some!

Page 13: C for Microcontrollers

More Code Structure

Actual parameters typically passed in registers if available Keep function parameters to less than 3 May also be passed on stack or special parameter area May be more efficient to pass pointer to struct

Global variables While generally frowned upon for most code can be very

helpful here Typically ends up being a direct access

Read assembly code for critical areas Know which optimizations are present

Small compilers do not always have common optimizations Inline, loop unrolling, loop invariant, pointer conversion

Page 14: C for Microcontrollers

Switch Statement Implementation

Switch statements can be implemented in various ways Sequential compares In line table look up for case block Special function with look up table

Specific implementation can also vary based case clauses Clean sequence (1, 2, 3, 4, 5) Gaps in sequence (1, 10, 30, 255) Ordering of sequence (5, 4, 1, 2, 3)

Knowing which method gets implemented is critical to optimizing!

Page 15: C for Microcontrollers

Switch Statement Example

switch(cA){

case 0:cX = 4;break;

case 1:cX = 10;break;

case 2:cX = 30;break;

default:cX = 0;break;

}

0006 900000 MOV DPTR,#cA0009 E0 MOVX A,@DPTR000A FF MOV R7,A000B EF MOV A,R7000C 120000 LCALL ?C?CCASE000F 0000 DW ?C00030011 00 DB 00H0012 0000 DW ?C00020014 01 DB 01H0015 0000 DW ?C00040017 02 DB 02H0018 0000 DW 00H001A 0000 DW ?C0005

001C ?C0002:001C 900000 MOV DPTR,#cX001F 7404 MOV A,#04H0021 F0 MOVX @DPTR,A0022 8015 SJMP ?C0006

...More blocks follow for each case

Page 16: C for Microcontrollers

Optimization Process

Step 0 – Before coding anything, think about risk points and prototype unknowns!!! Use available dedicated hardware

Step 1 – Get it working!! Fast but wrong is of no use to anyone Optimization will typically reduce readability

Step 2 – Profile to know where to optimize Usually only one or two routines are critical You need to have specific performance metrics to

target

Page 17: C for Microcontrollers

Optimization Process

Step 3 – Let the tools do as much as they canTurn off debugging! Select the correct memory modelSelect the correct optimization level

Step 4 – Do it manuallyRead the generated code! Might be able to

make a simple code or structure change.Last – think about assembly coding

Page 18: C for Microcontrollers

Summary

Microcontrollers are a resource constrained environment

Be familiar with the hardware in your microcontroller

Be familiar with your compiler options and how it translates your code

For time or space critical code look at the assembly listing from time to time

Page 19: C for Microcontrollers

Questions?