CENG 447/547 Embedded and Real-Time Systems Review of C coding and Soft Eng Concepts
Recall (C-style coding syntax) ; - Indicate the end of an expression {} - Used to delineate when a sequence of elements are to be treated as a single block text - Double quotes for text string (single quotes for characters) // or /*...*/ - comments (use liberally!!!) Don't forget about reserved words (most editors will highlight a word if it's reserved)
C-Data types (on the AVR) Type Size (Bits) Range bool 1 0,1 char 8-128 to 127 unsigned char 8 0 to 255 signed char 8-128 to 127 int 16-32,768 to 32,767 short int 16-32,768 to 32,767 unsigned int 16 0 to 65,535 signed int 16-32,768 to 32,767 long int 32-2,147,483,648 to 2,147,483,648 unsigned long int 32 0 to 4,294,967,295 signed long int 32-2,147,483,648 to 2,147,483,648 float 32 +1.175e-38 to +3.402e38 double 32 +1.175e-38 to +3.402e38
Constants Numeric base: (You should recall how to convert to and from each) Decimal: (125) Binary: (0b01111101) Hex: (0x7D) Most frequently used. Octal: (0175) #define PORTA 0x01 const char PORTA = 0x01; Recall the difference between the two!!!
Enumeration We can use enum to initialize a list: enum{zero_val,one_val,two_val} zero_val = 0, one_val = 1,... To force an initial val we can use: enum{ten_val = 10,next1,next2,...} ten_val = 10, next1 = 11,...
Storage classes (AVR specific later) Auto: typical int value; Scope is local to declaration, uninitialized upon allocation. Static: typical static int value; Scope is local to function declaration but stored in global memory space! Retains its value upon function exit!!! Register: typical register char value; Similar to Auto (difference is that the compiler tries to use a register for storage rather than memory).
Type Casting Given: int x; char y; x = 12; y = (char)x + 3; //x is demoted to a char and then 3 is added x = (int)y; //y is promoted to an integer
Type Casting (cont.) MUST take caution!!! int z; int x = 150; char y = 63; z = (y * 10) + x; // What's WRONG???
Type Casting (cont.) MUST take caution!!! int z; int x = 150; char y = 63; z = (y * 10) + x; // What's WRONG??? (y * 10) is treated as a char but too large (8-bits). Therefore, it's truncated to 118 (0x76) rather than 630 (0x276)...BAD!!! It is up to YOU the programmer to watch for this as it's next to impossible to debug!!!!
Operators and Expressions Arithmetic: Multiply * Divide / Modulo % Addition + Subtraction - Bitwise: Compliment ~ Left Shift << Right Shift >> AND & Exclusive OR ^ OR
Operators and Expressions Logical: AND && OR Relational: Equality == Not Equal!= Less Than < Less Than or Equal <= Greater Than > Greater Than or Equal >=
Operators and Expression: Examples Let x = 5; and y = 2; Expression (x && y) ( x & y) ( x y ) ( x y ) True/False
Operators and Expression: Examples Let x = 5; and y = 2; Expression (x && y) TRUE ( x & y) ( x y ) ( x y ) True/False
Operators and Expression: Examples Let x = 5; and y = 2; Expression True/False (x && y) TRUE ( x & y) FALSE (why??) ( x y ) ( x y )
Operators and Expression: Examples Let x = 5; and y = 2; Expression True/False (x && y) TRUE ( x & y) FALSE (why??) ( x y ) TRUE ( x y )
Operators and Expression: Examples Let x = 5; and y = 2; Expression True/False (x && y) TRUE ( x & y) FALSE (why?? - think binary) ( x y ) TRUE ( x y ) TRUE (why??)
Conditionals if(expression) { functiontrue(); } else { functionfalse(); } Can replace with: expression? functiontrue() : functionfalse();
Control While and do while (recall the differences): while(expression) { //do something cool. } do { // do something cool. }while(expression);
Control (cont.) for: for(exp1; exp2; exp3) { } // do something cool. Note: for and while are interchangeable!
Control (cont.) Switch (can be used for state machines in embedded systems): switch(expression) { case C1: statement1; case C2: statement2; default: default_case; } Recall: execution falls through (how do we resolve this?)
Control (cont.) Switch (can be used for state machines in embedded systems): switch(expression) { case C1: statement1; break; case C2: statement2; break; default: default_case; }
Functions Recall: Prototype vs. Definition! Prototype: type function_name(type, type); Definition: type function_name(type param, type param) { // do cool stuff. return val; // if return type is not void. }
Functions (cont.) Scope: Recall that variable scope is local to a function! How do we modify a variable outside the scope its defined?
Functions (cont.) Scope: Recall that variable scope is local to a function! How do we modify a variable outside the scope its defined? Define the variable to be global in scope (not recommended if it can be avoided)
Functions (cont.) Scope: Recall that variable scope is local to a function! How do we modify a variable outside the scope its defined? Define the variable to be global in scope (not recommended if it can be avoided) Pass a variable by reference rather than by value. (this is a bit different in C vs. C++ as we will soon see.)
Functions (cont.) Recursion: Functions that call themselves! Ex: factorials, 5! = 1*2*3*4*5 = 5*4! = 5*4*3! = etc. int fact(int n) { if(n == 0) return 1; else return (n * fact(n - 1)); }
Pointers (not introduced in CSC150) char *p; // p is a pointer to a character. int *fp; // fp is a pointer to an int. Note: Neither p nor fp actually point to anything at this stage!!! char a, b; // a and b are characters. p = &a; // p now points to the address of a. To get the value p points to we must dereference. b = *p; // same as b = a;
Pointers (cont.) The dereference can appear on the left of the = also. char *p; // p is a pointer to a character. char a, b; // a and b are characters. p = &a; // p now points to the address of a. *p = b; // same as a = b; Note the differences!!!
Pointers and Embedded Systems Used to access peripheral devices! unsigned char *PORTB; PORTB = 0x01; // assign address of PORTB. Now we can write a value directly to the port. *PORTB = 0xFF; // set PORTB high; This effectively writes the value 0xFF to memory location 0x01 Macros have been defined for you in io.h (we will see soon)
Pointers to Pointers to Pointers... Recall we can have multiple pointers: int *p1; // pointer to an int int **p2; // pointer to a pointer to an int int ***p3; // pointer to a pointer to a pointer to an int Let: int i,j; p1 = &i; //p1 points to the address of i p2 = &p1; // p2 points to the pointer that points to the address of i p3 = &p2; //p3 points to the pointer that points to points to the pointer that points to the address of i, (you get the idea...)
Increment and Decrement of Pointers Let: int * ptr; long * lptr; ptr += 1; // moves the pointer to the next integer (2-bytes away recall how memory is layed out). lptr += 1; // moves the pointer to the next long integer (4-bytes away) Can also use: ptr++; lptr++;
More Pointer Examples (Things can get tricky) Declare: char c; char *p; c = *p++; //assign c the value pointed to by p and then increment the address p c = *++p; //increment the address p and then assign c the new value pointed to by p c = ++*p; //increment the value pointed to by p and assign it to c (this leaves p untouched) c = (*p)++; //assign to c the value pointed to by p and increment the value pointed to by p (again, leaves p untouched)
Pointers and Functions How to pass by reference in C (different than C++): First recall C++ version! void swap(int &a, int &b){ } int temp; temp = b; b = a; a = temp; int v1,v2; swap(v1,v2);// pass the address of v1,v2;
Pointers and Functions How to pass by reference in C (different than C++): Now, C version! void swap(int *a, int *b){ } int temp; temp = *b; *b = *a; *a = temp; int v1,v2; swap(&v1,&v2);// pass the address of v1,v2;
Pointers to Functions We can also assign pointers to functions (why/how does this work???): int add(int a, int b){ } return (a+b); int main(){ } int temp = 0; int (*fp)(int,int); //assign a function ptr. fp = add; //point to the function add. temp = (*fp)(4,4); //call add via ptr. return 0;
Recall: Arrays int digits[50]; char grades[5] = {'a','b','c','d','f'}; int exams[3][20]; // 3 x 20 array. char keypad[10][20][30]; // 10 x 20 x 30 array... int MyArray[300] = {}; // initialize to zero. Using malloc to create an array of n integers: int * p; p = (int*)malloc(n*sizeof(int));
Group variables: Structures struct TagName{ Type member1; Type member2; Type member3; } struct RobotState { int x; int x_dot; int theta; int theta_dot; } Usage: struct RobotState R1; R1.x = 7; R1.x_dot = 16; R1.theta = 20; R1.theta_dot = 10; Alternatively: R1 = {7, 16, 20,10};
Nesting Structures struct Location{ int x; int y; } struct Part{ char name[30]; long int sku; struct Location bin; }widget; //can define here Usage: x_loc = widget.bin.x; y_loc = widget.bin.y; Can also pass to functions and be returned from functions. Think of structures as user defined data types.
Embedded vs. Application Programming Biggest difference between application programming and embedded programming! Application: int main(int argc, char * argv[]) {// Your code here } return 0; // Exit status good!
Embedded vs. Application Programming Biggest difference between application programming and embedded programming! Embedded: int main() {// Initialization code here while(1) { //do something (maybe) }; return 1; // Exit = BAD } Look at:/hardware/arduino/cores/arduino