Sie sind auf Seite 1von 31

Embedded-C Language

Vu Trong

ESRC

Contents
Overview Embedded-C language Tip-n-Tricks for Embedded-C Language Small Test

ESRC

1. Overview
C Language
1. Environment In a Complex OS: Windows, Linux,

Embedded-C Language
In a Simple OS: uCLinux, Nios, Microblaze Standalone: microprocessors, bootloader Lower power Must be more efficient Must be optimized Hard to code, optimize code manually
3

2. Power consumption 3. Performance

Higher power Non-requirement of performance Maybe not need to be optimized Easy to program with many IDE, automatically optimize
ESRC

4. Programming

1. Overview
In general, a embedded programming must balance all requests below in order to meet them:
Execution Speed Object Efficiency
RAM size: variables and stack ROM size: program size

ESRC

1. Overview
In order to create efficient codes, it is important to understand the data structure characteristics:
Storage class Type qualifier Data type Pointer, array, and structure

ESRC

2. Data Structure
2.1. Storage Class
Automatic variable Register variable Static variable Global variable

ESRC

2. Data Structure
2.1. Storage Class
Automatic variable Local variable:
Be automatically created at the beginning of a code block {...} and destroyed when exits its own block Be allocated in stack or register (optimized by compiler)
void main() { int a = 0; A and B int b = 0; for(a=0; a<10; a++) { int x = a >> 2; b += x; } } A and B

A and B and X

ESRC

2. Data Structure
2.1. Storage Class
Register variable
Some automatic variables can be synthesized as register variable Put keyword register before declaration of a variable to force it to be a register variable Example:
void main() { int x = 0; printf(%08x\n, &x); for (x=1; x<10; x++) { printf(%i\n,x); } } Varibale x will be allocated in main memory at a real address, eg: 0xABCD
ESRC

void main() {

register int x;
printf(%08x\n, &x); // error for (x=1; x<10; x++) { printf(%i\n,x); }
} Varibale x will be allocated in a register in CPU, so x has no address. 8

2. Data Structure
2.1. Storage Class
Static variable:
When a variable is declared with static, a memory is permanently allocated, and not released until the program terminates Initialized value is used only at the first time that variable is called and must be a valid value Example:
void load_var(int y) { static int x = 2; x = x + y; printf("%i\n",x); }
load_var(3); load_var(6); load_var(20); >> x = ?
ESRC

void load_var(int y) { int x = 2; x = x + y; printf("%i\n",x); }


load_var(3); load_var(6); load_var(20); >> x = ? 9

Global Variable:
Declared outside of the function, exits from the start to the end of the program To be available to all functions of the program Can be referenced from another file by using keyword extern Example:
[scancode.h] int KeyPressed; int KeyCode(); // a global variable

[main.c] extern int KeyPressed; // reference to a global variable int Flags; void main() { extern int KeyPressed; // reference to a global variable // initialize global variable KeyPressed = 0; Flags = 0x00; } 10

ESRC

2. Data Structure
2.1. Storage Class
Choice of Variables:
Static and Global are used as flags which presents the state of modules or the program Static and Global variables are also used when there is the data to be transferred among many modules and the data transfer with arguments is complex Example:
struct __flag{ int isKeyPressed; int isRotating; } Flags void scanKey() { Flags.isKeyPressed=TRUE;}; void task1(){ if(Flags.isKeyPressed){ Flags.isRotating = TRUE;} }
ESRC

11

2. Data Structure
2.2. Type Qualifier
A type qualifier specifies a special nature of data type, playing an important action in the embedded program.
const type qualifier volatile type qualifier

ESRC

12

2. Data Structure 2.2. Type Qualifier


constant variable:
Its value cannot be changed by operations Placed into ROM Note: when declaring a pointer with const , you must be careful with constant pointer and pointer to a constant variable (see chapter: Pointer)

ESRC

13

2. Data Structure 2.2. Type Qualifier


Volatile variable:
The value of volatile variable can be changed without explicit operations in the program, that means, its value can be changed outside of the program: input devices, shared memories. Compiler doesnot optimize volatile variables Example:
int A; A = input(); // input = 2 B = C + D; A = input(); // input = 3 // same instruction with above one -> deleted with optimization B = A; // B = 2, not 3 volatile int A; A = input(); // input = 2 B = C + D; A = input(); // input = 3 // same instruction with above one but not be deleted B = A; // B = 3, not 2

Be usually used to declare pointer to an input or memory region:


define input (*(volatile int *) 0xABCD) volatile int * shared_memory = (int *) 0xABCD;
ESRC

14

2. Data Structure 2.3. Data types


Some rules when choosing data types:
When you want to directly access a variable, if its data and a general register have same length, the program becomes efficient
Register: 32-bit good data types: int32

In particular, if the value does not need to be negative, an unsigned type is advantageous
unsigned int i; for(i=0; i<100; i++) {}

When you want to handle a certain number of data, consider to use an array or a structure
int a1, a2, a3, a4; int a[4]; struct _aX{
int int int int a1; a2; a3; a4;

} aX;
ESRC

15

Pointer:

2. Data Structure 2.3. Data types

Its value stores an address, not a real value. This address points to a real value in other memory region Use & to get address of a variable (exception: register variable)
Int a; Int *ptr = &a;

when pointer class is different to variable class, pointer will point to a smaller/bigger memory region started by start memory of that variable
int A[] = {1024,14}; char *p = A; printf(%d, *p);
ESRC

16

3. Tips-n-Tricks
Array uses a pointer
/* program 1 */ int data[100]; int sum(void) { int i, sum; for(i=0, sum=0; i<100; i++) sum += data[i]; return sum; } Slow: - multiply I with 4 - add i*4 to base address of data - get value at address p+i*4 - add data[i] to sum - increase i by 1 - compare i with 100 /* program 2: recommended */ int data[100]; int sum(void) { int *p, sum, *pend; pend = data+100; for(p=data,sum=0; p<pend; p++) sum += *p; return sum; } Quick: - get value at address p - add to sum - increase p by 1 - compare p with pend

ESRC

17

3. Tips-n-Tricks
Use a structure
/* program 1 */ #define ON 1 #define OFF 0 // use 3 vars: wasting 3*31 bits /* if use char class: reduce performance */ int power_status; int motor_status; int light_status; void main() { // power on power_status = ON; // if not motor on if(motor_status = OFF) { // turn off light light_status = OFF; } } /* program 2: recommeneded */ #define ON 1 #define OFF 0 union __status{ int power_status:2; int motor_status:1; int light_status:3; } status; // 3-bit -> char class void main() { status.power_status=ON; // if not motor on if(!(status.motor_status)) { // turn off light status.light_status=OFF; } } ESRC

18

3. Tips-n-Tricks
Use a bit-field
/* program 1 */ #define ON 1 #define OFF 0 // use 3 vars: wasting 3*31 bits /* if use char class: reduce performance */ int power_status; int motor_status; int light_status; void main() { // power on power_status = ON; // if not motor on if(motor_status = OFF) { // turn off light light_status = OFF; } } /* program 2: recommeneded */ #define POWER_ON 0x1 #define MOTOR_ON 0x2 #define LIGHT_ON 0x4

int status;
void main() { // status |= POWER_ON;//power on // if not motor on if(!(status & MOTOR_ON)) { // turn off light status &= ~LIGHT_ON; } }
ESRC

19

3. Tips-n-Tricks
Pointer with const keyword:
Pointer to a constant variable
int table[] = {0, 1, 2}; const int *p; // p is pointer pointed to constant intege var p = &table[1]; // assignment to the pointer is enable p++; // change of pointer value is enable *p = 10; // indirect change to data is disable

a constant pointer
int table[] = {0, 1, 2}; int * const q = &table[0]; /* q is a constant pointer to int and must be initialized */ *q = 10; // indirect change of data is enable q = &table[1]; // assignment to the pointer is disable q++; // change of pointer value is disable

ESRC

20

3. Tips-n-Tricks
Declare an I/O port
reference by pointer
#define PORT_INP ((const volatile int *) 0xABCD) #define PORT_OUT ((volatile int *) 0xDCBA) *PORT_OUT = *PORT_IN

using a dedecated access funtion


#define input(add) (*(const volatile int *)(add)) #define output(add,data) (*((volatile int *)(add))=(int)(data)) output(0xDCBA,input(0xABCD));

reference similar to variable


#define PORT_INP (*(const volatile int *) 0xABCD) #define PORT_OUT (*(volatile int *) 0xDCBA) PORT_OUT = PORT_IN
ESRC

21

3. Tips-n-Tricks
Interrupt Program
Make interrupt service routine (ISR) short as far as possible Interrupt and main programs must not share the data with one another as far as possible, if data shared, main program only references the data ISR should return a flag of explicit status in some cases, you should disable interrupt while processing this interrrupt

ESRC

22

3. Tips-n-Tricks
Interrupt program structure
/* flags */ struct __flags{ int device1; int device2; } Flags; #ISR1 void isr1(){ Flags.device = TRUE;} #ISR2 void isr2(){ Flags.device = TRUE;} void main() { /* initialize global status */ Flags.device1 = Flags.device2 = FALSE; /* while loop */ while(TRUE){ if(Flags.device1){Flags.device1 = FALSE; // do something here}; if(Flags.device2){Flags.device2 = FALSE; // do something here}; // do something here } }
ESRC

23

3. Tips-n-Tricks
Using a function-like macro, be careful about the followings:
Function-like macro is nothing but writing codes directly Its difficult to forecast the side effects of macro Funtion is slow but make size of the program small, but functionlike macro is fast, followed by a larger program size Example:
#define abs(x) ((x) >= 0 ? (x) : -(x)) z = 1; x = abs(z++); x = ((z++) >= 0? (z++) : -(z++)); // x = ?? int abs2(int x){return x >= 0 ? x : -x;} x = abs2(z++); z++ is calculated before be transferred into abs2(). x = abs2(2) = 2;
ESRC

24

3. Tips-n-Tricks
Using shift operator instead of multiplication
int int y = y = y; x; x*4; x/8; y = x << 2; y = x >> 3;

y = x * 100; y = x / 124;
y = x * 100; y = x / 124;

??? ???
y = x << 6 + x << 5 + x << 2; y = x >> 6 + x >> 5 + x >> 4 + x >> 3 + x >> 2;

Be careful with range of data type

ESRC

25

3. Tips-n-Tricks
Common Subexpression Elimination
/* program 1a */ int x, y, z; void sub(void) { int a, b; a = x + y + z; b = x + y + z + 10; return f(a,b); } /* program 2a*/ int x, y, z; void sub(void) { int a, b; a = x + y + z; b = a + 10; return f(a,b); }

/* program 1b*/ void sub(void) { int a, b, c, d; a = b; d = a + c; }

/* program 2b*/ void sub(void) { int a, b, c, d; d = b + c; }

ESRC

26

3. Tips-n-Tricks
in-loop invariant displacement
/* program 1 */ int x; int sub(int a, int b) { int c = 0; while(x) { x = f1(); c += a*b; } return c; } /* program 2 */ int x; int sub(int a, int b) { int c = 0; int t = a*b; while(x) { x = f1(); c += t; } return c; }

ESRC

27

3. Tips-n-Tricks
Constant Folding
#define FLAG_A 0x01 #define FLAG_B 0x02 unsigned int status; status &= ~(FLAG_A | FLAG_B);

~(FLAG_A | FLAG_B) is not calculated when executing, it is calculated as 0xFFFC when compiler compiled it

ESRC

28

3. Tips-n-Tricks
Switch case optimization
#define ON 1 #define OFF 0 #define WHITE 0 #define YELLOW 1 #define RED 2 #define GREEN 3 #defein BLACK 4 unsigned int Cflag; void set(unsigned int data){ swicth(data){ case WHITE: Cflag = OFF; break; case YELLOW: Cflag = ON; break; case RED: Cflag = ON; break; case GREEN: Cflag = ON; break; case BLACK: Cflag = OFF; break; // cover all unmatch cases default: Cflag = OFF; break; } #define ON 1 #define OFF 0 const static unsigned int flag[] = {OFF, ON, ON, ON, OFF}; unsigned int Cflag; void set(unsiged int data) { Cflag = flag[data]; } /* must be sure that data is not out of range of flag dimension */

ESRC

29

3. Tips-n-Tricks

QUESTION?

ESRC

30

4. Small TEST
Write a function which calculates the checksum of an array of byte by adding them together. int checksum(<array of bytes>,[length]); Check your function with a string, an array from 0 to 9 and fix bug if you found them

ESRC

31

Das könnte Ihnen auch gefallen