Embedded Systems C programming. Reference Data definition and storage const int a=43; unsigned int...

Post on 04-Jan-2016

251 views 0 download

Tags:

Transcript of Embedded Systems C programming. Reference Data definition and storage const int a=43; unsigned int...

Embedded Systems

C programming

Reference

Data definition and storage

const int a=43;

unsigned int b=66;unsigned int c;

int main(void){ static int d; ……}

.text.text.data.data

.bss.bss

.rodata.rodata

RAM ROM

the file *.lds give detailed address of

each data block

Keyword: const

• Unchanging Value const int five = 5; const double pi = 3.141593;

• Cannot Write a const Data Object const double pi = 3.141593; pi = 3.2;

Keyword: volatile•Value May be Changed Outside Current Program•Exchange data with an external device int check_iobuf(void) { volatile int iobuf; int val; while (iobuf == 0) { } val = iobuf; iobuf = 0; return(val); }

if iobuf had not been declared volatile, the compiler would notice that nothing happens inside the loop and thus eliminate the loop

Const + volatile

• An input-only buffer for an external device could be declared as const volatile (or volatile const) to make sure the compiler knows that the variable should not be changed (because it is input-only) and that its value may be altered by external processes

Constant

• readability

• Easily update a const used in several pace in the codes

• Easily update several related parameters in the program

Constant Rule (1)

• a Clear name#define WIDTH 320#define MAX_VALUE 100const float PI = 3.14159;

“const” or “#define” ?

• const has data type while Macro doesn’t– Compiler has type check for const but not for

Macro

• Most debugger can show value of const but not Macro

Keyword: inline

void data_process(){…inc(p);…

}

void data_process(){…inc(p);…

}

void data_process(){

(*a)++; …

}

inline int inc (int *a) { (*a)++; }

inline int inc (int *a) { (*a)++; }

put them to header file

Macro as a Function

#define abs(x) (((x)>=0)?(x) : -(x))

#define max(a,b) ((a)>(b)?(a) : (b))

#define abs(x) x>0?x:-x

abs(a-b); // abs(a-b) a-b>0?a-b:-a-b

Note the usage of ()

inline function vs. Macro

• inline function has input data type, can be checked by compiler

• Compiler cannot check input data type in Macro

#define ABS(x) (((x)>=0)?(x) : -(x))

inline double ABS(double x){ return (x>=0)?x : -x; }

• inline function can reduce () used in Macro

inline function vs. Macro

• inline function execute inputted expression once, while Macro may run several times

 // Macro #define unsafe(i)  ((i)>=0?(i):-(i))  // Inline inline int safe(int i) {return i>=0?i:-i; }  int f() {……}  void userCode(int x) {   int ans;    ans = unsafe(x++);   // Error, Execute x++ twice   ans = unsafe(f());   // Error, f() invoked twice    ans = safe(x++);     // correct   ans = safe(f());     // correct }

Calculate Array Size

User can know the length of array by ending NULL

int MyData[] = { 7, // Number of element in array

3, 4, 5, 6, 7, 0, 1 };

Calculate Array Size

#define ARRAY_SIZE 20

double a[ARRAY_SIZE]={…};

void main (){ int c; for (c=0; c<ARRAY_SIZE; c++) {…}}

Using Macro to Calculate Array Size

Keyword Register

int fac(int n){   register int i,f=1;

   for(i=1;i<=n;i++)      f=f*i;

   return(f);}

Fast, but only a suggestion to the compiler, and maybe

ignored by the compiler

Bit Filed in C

struct packed_struct { unsigned int f1:1; unsigned int f2:1; unsigned int f3:1; unsigned int f4:1; unsigned int type:4; unsigned int byte_int:8; } pack;

pack.type = 7; // accept value <=15

f1 f2 f3 f4 type byte_int

Struct & Alignment

struct data{

u8 c;u32 d;u8 e;

};

sizeof(data)? 12

Struct & Alignment

struct data{

u8 c;u8 e;u32 d;

};

sizeof (data)? 8

Data Pack and Alignment

typedef struct {          u8  p[3]; u32  v; } test;

sizeof(test) ?

p[0]

v

p[1] p[2] v

empty

v

emptyp[0] p[1] p[2]

struct … {…} __attribute__ ((packed));

gcc -fpack-struct …

Typedef & Data Type• unsigned int• short int• unsigned long • char

typedef signed char s8;typedef signed short s16;typedef signed long s32;

typedef unsigned char u8;typedef unsigned short u16;typedef unsigned long u32;

C Memory Types• Static

Global variable, static variableAllocate memory at compile stage

• StackLocal variable within a function(de-allocated automatically after return of the function)

• Heap (Dynamically allocated)allocated by malloc or newdeleted by free deletebe care of the memory leakage problem

Memory Access Error• Check memory allocation resulkt

if(p==NULL) …;

• initialize memory before usememset(ptr, 0, 200);

• Out of boundary errorchar str[] = “Hello”;char *str1 = malloc(strlen(str));strcpy(str1, str); strcat(str1, str);

• For/wile loop variable used in memory access

Memory Access Error (cont.)• Forget to release allocated memory (pointer)

• malloc free• Use deleted pointer

Malloc/Free Debugint count=0;

void *my_malloc(int size){ void *p; if (size<=0) return 0; // error() p=malloc(size); if (p!=NULL) count++; return p;}

void my_free(void *p){ if (p==NULL) return; // error(); free (p); count--;}

Memory Region

struct mem_region_t a[REGION_NUM];void my_malloc(int size, int id){ void *p=malloc(size); if (!p) return; add_pointer(a[id],p); return p;}void my_free(void *p, int id){ void *p=del_pointer(a[id], p); if (p) free p;}void my_free_all(int id){ void *p; while(p=get_1st_pointer(a[id])) free p; }

a[]

region_ID

Resource Allocation method

(use of List)

Free NodeList

Block

Block

Block

Block

Block

User Data List 1

Block

Block

Block

User Data List 2

Block

Block

Pointers in Function Call

void Func(void){ char *p = (char *) malloc(100); }

Remember to free it after the function call

void Func1(void){ char p[100]; …;} No need to free it manually

Pointer Access Example

int *x;*x=100;

char* get_hello_str(){

char abc[]=“hello”; … return abc;}

char* get_str(){

char abc[32]; … return abc;}

char* get_hello_ptr(){

char *abc=“hello”; … return abc;}

x pointer to where?

abc only existed in te stack of get_str(), and it is desyoried after

function return

“hello” is stored in the stack of function get_hello_str(), which is released when function is returned

“hello” is in const torage area, not released or deleted

Memory Example (1)char *ptr1 = NULL;char *ptr2 = NULL;

void Func() { if ((ptr1 = (char*)malloc(100)) = = NULL) { printf(“Out of memory!\n”); return; } if ((ptr2 = (char*)malloc(500)) = = NULL) { printf(“Out of memory!\n”); free(ptr1); return; } … free(ptr1); free(ptr2);}

// remember to delete the 1st point

Memory Example (2)char *ptr = NULL;

void Init() { ptr = NULL; …}

int main() { Init(); …; GetMemory(); …; FreeMemory();

…}

void FreeMemory(){ if (ptr != NULL) { free(ptr); ptr = NULL; } else printf(“Error!\n”); }

void GetMemory(){ if (ptr = = NULL) { ptr = (char*)malloc(100); } else printf(“Error!\n”); }

initialize before access

check before release

reset after release

check before reuse

“goto” Clause

• may skip important object construction, variable initialization codes

goto state;String s1, s2; // skippedint sum = 0; // skipped…state:…

{ … { … { … goto error; } }}error: …

“switch” Clause

• don’t forget break for each case

• Don’t forget default branch• Default is a label?

void func(){ switch (m) { … default: … } switch (n) { … default1: … }}

Assert•Only valid in debug version , check invalid conditionsvoid *memcpy(void *To, const void *From, size_t size){ assert((To != NULL) && (From != NULL)); byte *To = (byte *) To; byte *From = (byte *) From; while(size -- > 0 ) *To ++ = *From ++ ; return To;}

•Note, the error is in the caller function instead of memcpy

IO Port Access

#define PORT_X (*((volatile u8 *)0x10001004))

#define PORT_BASE 0xF021C000#define PORT_A0 (*((volatile U32 *)(PORTA_BASE+0x04)))#define PORT_A1 (*((volatile U32 *)(PORTA_BASE+0x08)))

char s=PORT_X;PORT_X=0xff;PORT_A0=0x24000006;

different hardware may have different device base address

Bit Operation

• Set bitport |= 1<<12;port |= FLAG_RUN;

• Reset bitport &= ~(1<<12);port &= ~ FLAG_RUN;

• Test Bitwhile (!(port & FLAG_READY));if (port & FLAG_READY) …;

Write a Small Printf Function

• printf()“%s”, “%d” and “%x”

#include <stdarg.h>

int my_printf(const char *fmt, ...)int my_printf(const char *fmt, ...){ const char *s; int d; char buf[16]; va_listap; va_start(ap, fmt); while (*fmt) { if (*fmt != '%') { putchar(*fmt++); continue; } switch (*++fmt) { case 's': s = va_arg(ap,const char*); for (;*s;s++) putchar(*s); break; case 'd': d = va_arg(ap, int); itoa(d,buf,10); for (s=buf;*s;s++) putchar(*s); break; /* Add other specifiers here... */ default: putchar(*fmt); break; } fmt++; } va_end(ap); return 1; /* Dummy return value */}

Write a Small Printf Function (1)

#include <stdarg.h>intprintf(const char *fmt, ...){ … va_listap; va_start(ap, fmt); while (*fmt) { if (*fmt != '%') {…} switch (*++fmt) { case 's': s = va_arg(ap, const char *); … case 'd': … default: putchar(*fmt); break; } fmt++; } va_end(ap); …}

……

……

Style of Head File/**************************************** File description(ver, Author) ** ... ****************************************/

#ifndef MY_MUDOLE_H // prevent repeation#define MY_MUDOLE_H#include <stdio.h> // standard header...#include “MY_Header.h” // user defined header...typdef ... // data types...extern ... // global variable3...void Func(...); // global function...#endif // MY_MUDOLE_H

Example of including head file

#include “B.h”#include “B.h”

#define OK 1void func(void);#define OK 1void func(void);

A.h

B.h

#include “A.h”#include “B.h”…

#include “A.h”#include “B.h”…

code.c

void func(void);#define OK 1void func(void);#define OK 1…

void func(void);#define OK 1void func(void);#define OK 1…

re-define xxx error

Example of including head filecont.

#include “B.h”...#include “B.h”...

#ifndef __B_H__#define __B_H__

void func(void);

#endif // __B_H__

#ifndef __B_H__#define __B_H__

void func(void);

#endif // __B_H__

A.h

B.h

// __B_H__ is not defined#include “A.h”// __B_H__ is defined now

// will skip contents of B.h since // __B_H__ is already defined#include “B.h”

// __B_H__ is not defined#include “A.h”// __B_H__ is defined now

// will skip contents of B.h since // __B_H__ is already defined#include “B.h”

code.c

Comments#if 0

int GetValue(int Flag){ char *pBuffer = GetBuffer(); /* The Flag indicates whether the pointer should be adjusted */ if (Flag) return (*pBuffer) else // Adjust the reading point return *(pBuffer+1); }

#endif

Comments for several lines below

Comments for 1 lines on the left

int func(void){ /* debug_codes(); if (error==1) { printf(…); /*error=0;*/ } */}

Note /* … */ cannot nest

Math optimization

a*2^n // a<<n a*16 // a<<4

a/2^n // a>>n a/32 // a>>5

a%2^n // a&(2^n-1)a%8 // a&0x07

3/2 // 3>>1

r0*5 // r0<<2 + r0, mov r1,r0,r0,lsl #2

most of constant calculation can be recognized

and optimized by compiler

automatically

Fixed Point Arithmetic (1)

• Q16.16

Integer Fraction

16-bit 16-bit

Fixed Point Arithmetic (2)•Add add r0, r1, r2

•Sub sub r0, r1, r2

•Mulsmull r1,r2,x,ymovs r1,r1,lsr #16adc r0,r1,r2,lsl #16

r2[31:0] r1[31:0]

r2[15:0]r1[31:16

]r0[31:0]

00…00r1[31:16

]r2[15:0] 00…00

Fixed Point Arithmetic (3) ldr r1, dividend ldr r2, divider

mov r9,#0x10000 clz r3,r1 @how many 0 in the head of r1 clz r4,r2 subs r4,r4,r3 @r4-r3 movgt r2,r2,lsl r4 movgt r9,r9,lsl r4 @r9<<=r4 rsblt r4,r4,#0 @r4=-r4 if r4<0 movlt r1,r1,lsl r4 movlt r9,r9,lsr r4 @r9>>=r4

loop: subs r3,r1,r2 addhs r0,r0,r9 @r3>=0: r0+=r9, hs/cs is unsigned >=@note that must used unsigned compare@because r1 may overflow to bigger than 0x80000000 when <<1 movhi r1,r3,lsl #1 @r3> 0: r1=r3<<1, hi unsigned > movlo r1,r1,lsl #1 @r3< 0: r1<<=1, lo/cc is unsigned < beq finish @r3= 0: end movs r9,r9,lsr #1 @r3<>0: r9>>=1 bne loop @r9<>0: loop @it means that @if r1>r2: r0+=r9, r1=(r1-r2)<<1,r9>>=1 @if r1=r2: r0+=r9, go finish @if r1<r2: r1=r1<<1,r9>>=1

clz r4,r2 @find how many 0 in the head of r2loop: subs r3,r1,r2 addhs r0,r0,r9 @r3>=0: r0+=r9, hs/cs is unsigned >=

beq finish @r3= 0: end clzhi r5,r3 subhi r5,r5,r4 @r5=r5-r4,then should lsl r3 for r5 bit movhi r1,r3,lsl r5 @r3> 0: r1=r3<<r5, hi unsigned > movlo r1,r1,lsl #1 @r3< 0: r1<<=1, lo/cc is unsigned < movs r9,r9,lsr r5 @r3<>0: r9>>=r5 bne loop @r9> 0: loop @it means that @if r1>r2: r0+=r9, r1=(r1-r2)<<n,r9>>=n @if r1=r2: r0+=r9, go finish @if r1<r2: r1=r1<<1,r9>>=1

clz r4,r2 @find how many 0 in the head of r2loop: subs r3,r1,r2 movlo r9,r9,lsr #1 @r1<r2: r9>>=1 rsblos r3,r2,r1,lsl #1@r1<r2: r3=(r1<<1)-r2 and then the compare result must be >=0 @so the next few instruction omit compare condition > or >= add r0,r0,r9 @r3>=0: r0+=r9, hs/cs is unsigned >=

beq finish @r3= 0: end clz r5,r3 @compare result must be >=0, so omit hi(>) sub r5,r5,r4 @r5=r5-r4,then should lsl r3 for r5 bit, r5 must >=1 mov r1,r3,lsl r5 @r3> 0: r1=r3<<r5, then r1 and r2's clz is equal movs r9,r9,lsr r5 @r3<>0: r9>>=r5 bne loop @r9> 0: loop