Review On Embedded C

Download as pdf or txt
Download as pdf or txt
You are on page 1of 37

CSE 448: Embedded

Operating Systems:
Lecture 3
Dr. Karim Emara
Computer Systems Department
Faculty of Computer and Information Sciences
Ain Shams University
2
Agenda
Embedded C
1. Variables
2. Data Type Qualifiers
3. Type Specifier
4. Storage Class and Scope
5. Type Casting
6. Arrays and Pointer Arithmetic
7. Typedefs and Macros
8. Bitwise Operations
3
Variables
Variables must be declared before used
May be initialized when declared
Has a data type which determines
Allocation size
Instructions used to handle performed operations

Standard Type Specifiers:


Integers: char (1), short (2), int (2 or 4), long (4)
Real numbers: float (4), double (8)
4
Type Specifiers
Integer variables can specified by: signed (default)
or unsigned

C99 Standard defined compiler-independent type


specifiers for integers:
int8_t, uint8_t
int16_t, uint16_t
int32_t, uint32_t
int64_t, uint64_t
You should include <stdint.h> to use these types
5
Pointers
Pointer is a variable that stores the address of
another variable
Usually, pointer type = variable type
Example:
int var = 10;
int * pvar = &var; pvar 0x20001000 0x20002000

// var = 10
// pvar = 0x20001000
var 10 0x20001000
// &var = 0x20001000
// *pvar = 10
// &pvar = 0x20002000
6
Const Qualifier
Variables can be qualified by const or volatile
const tells the compiler this variable will never be
modified after initialization
Examples:
int intnc = 5; //can be changed
const int intc1 = 50; //can NOT be changed
int const intc2 = 10; //can NOT be changed
const int * pint1 = &intc1;//const variable, non-const
/pointer
int * const pint2 = &intnc;//non-const variable, const
//pointer
const int * const pint3 = &intnc; //variable & pointer
// are const
7
Const Qualifier
int var1 = 10, var2 = 20; *pvar = 5; //OK
const int varc = 10;
var1 = var2 = 5; //OK int * const pcvar = &var1;
varc = 5; //Error *pcvar = 5; //OK
pcvar = &var2; //Error
const int * pvarc = &var1;
var1 = 5; //OK const int * const pcvarc =
&var1;
*pvarc = 5; //Error
*pcvarc = 5; //Error
pcvarc = &var2; //Error
int * pvar = (int*)&varc;
varc = 5; //Error
8
Const Qualifier
We usually use const:
Place data in Flash ROM rather than SRAM
( but must be declared global)
Pass arrays to functions that should not be changed
char *strcat(char *s1, const char *s2);
9
Volatile Qualifier
A variable qualified by volatile means that its
value can be changed outside the program
(e.g., external device)
In practice, volatile makes the compiler not to
optimize the code and
place this variable in memory (rather than a register)
read it from memory every time its referenced
10
Volatile Qualifier
How this code is compiled?
int a, b, c = 5;
a = c;
b = c;
volatile int x, y, z = 5;
x = z;
y = z;
11
Volatile Qualifier
int a, b, c = 5;
MOVS r1, #0x05 ; c r1
a = c;
MOV r2, r1 ; a r2
b = c;
MOV r3, r1 ; b r3

volatile int x, y, z = 5;
MOVS r0, #0x05
STR r0, [sp, #0x00]
x = z; z sp
LDR r0, [sp, #0x00] y
STR r0, [sp, #0x08]
x
y = z;
LDR r0, [sp, #0x00]
STR r0, [sp, #0x04]
12
Volatile Qualifier
We usually use volatile in the following cases:
Memory-mapped peripheral registers
#define GPIO_PORTF_DATA_R (*((volatile uint32_t
*)0x400253FC))
Global variables modified by an ISR
volatile char trigger_rcvd = 0;
void ISR() {
trigger_rcvd = 1;
}
int main() {
while (trigger_rcvd == 0);
// now, trigger occured }
13
Const volatile variables
Can a variable be both Volatile and Const?!
Yes, it means it wont be changed by the code
but by an external event
14
Scope and lifetime
Variables have
Scope which determines where the variable would
be available in the code (e.g., file scope, block
scope)
Lifetime which indicates how long it would exist/be
allocated (e.g., program lifetime, local within block,

Those attributes are determined by the storage


class.
15
Storage class
4 storage classes:
auto: default for local variables
Scope: block
Lifetime: from definition to the block end
Example: auto int x;
register: <Not guaranteed>
Scope: block
Lifetime: from definition to the block end
Example: register int x;
16
Storage class
extern: declared here, defined elsewhere
Scope: multiple files
Lifetime: program lifetime
Example: extern int x;

static: keeps local variables allocated


Scope: local scope file if global/function if local
variable
Lifetime: program lifetime
17
Static storage
int counter() {
static int count = 0;
return count++;
// count will remain allocated after function return
// but is not accessible outside the function
}
int main() {
int x;
for (int i = 0; i < 10; i++)
x = counter();
//count = 1; Error: count undefined
}
18
Typecasting
Typecasting is converting an expression of a
given type into another type
Compare results with/without casting for this
statement:
int x = 3, y = 6;
float avg = (float) (x + y) / 2;
//avg = 4 or 4.5 ?
Typecasting can be implicit or explicit
19
Typecasting
Implicit casting is done with compatible data types
(e.g., standard data types)
However, implicit casting will truncate values if
casting from large to small types

Explicit casting is required for data types that the


compiler does not know how to convert them.
const int varc = 5;
int * pvar = &varc; //Error
// cannot cast (const int*) --> (int *)
20
Typecasting
Explicit casting required to treat a variable as
another type
Example
uint32_t x = 0x10203040;
uint8_t * p8 = (uint8_t *)&x;
//p8[0] = 0x40, p8[1] = 0x30, p8[2] = 0x20,
uint16_t * p16 = (uint16_t *)&x;
//p16[0] = 0x3040, p16[1] = 0x1020
21
Arrays and Pointer Arithmetic
Array is a collection of variables with a single name which
are referenced using subscript
short data[3] = {1,2,3}; //5 16-bit integers
char string[20]; // 20 8-bit characters
short d2[10][5]; // 50 16-bit integers
There is no checking on array bounds in C
In fact, array name can be considered as a const pointer for
the first item
Array subscript is exactly the same as adding the index to
the pointer of 1st item
data[3] *(data +3)
Index here expresses on items not bytes (not like assembly)
22
Arrays and Pointer Arithmetic
short x, *pt, arr[5] = {10,20,30,40,50};

x = arr[0]; // x = item_0
x = *arr; // x = item_0
pt = arr; // pt points to the array now
pt = &arr[0]; // equivalent to the above statement
x = arr[3]; // x = item_3 (4th item)
x = *(arr + 3); // x = item_3
x = *(pt + 3); // x = item_3
x = *pt + 3; // x = item_0 + 3
23
Pointer to pointer
Pointer can point to a pointer
int x = 10; ppvar 0x20002000 0x20002500

int *pvar = &x;


pvar 0x20001000 0x20002000
int **ppvar = &pvar;

Pointer to pointer is important


in multidimensional arrays var 10 0x20001000
24
Pointer to pointer
25
Pointer to function
To make it more complicated, a pointer can
point to a function

Example: int(*fptr)(int, int);


Here, fptr can point to any function takes to
2 integers as parameters and return an integer
26
Pointer to function
int findmin(int x, int y) {
if (x < y) return x;
else return y;
}
int findmax(int x, int y) {
if (x > y) return x;
else return y;
}
int main() {
int(*fptr)(int, int);
int x;
fptr = findmax; // let fptr finds the max
x = fptr(10, 20); // x = 20

fptr = findmin; // now, let fptr finds the min


x = fptr(10, 20); // x = 10
}
27
Typedef and Macros
Typedef allows programmers to introduce an
alias for types declared somewhere else.
Example:
typedef volatile int * vintp;
typedef int iblock[100];
int main() {
vintp x; //volatile int * x;
iblock arr; //int arr[100];
}
28
Typedef and Macros
Macros define constant values or expressions
that are replaced in the code by the pre-
processor before compilation.
Examples:
#define ARR_SIZE 10
#define PI 3.14

int arr[ARR_SIZE];
float circle_area = PI * radius * radius;
29
Typedef and Macros
Macros can even define expressions with parameters
#define MAX(x, y) ((x > y)? x: y)
#define MIN(x, y) ((x < y)? x: y)
int main() {
int x;
x = MAX(10, 20); // x = 20
x = MIN(10, 20); // x = 10
}
What if MIN and MAX are defined as functions instead
of macros.
Which is faster? Which is more flexible?
30
Typedef and Macros
Macros are efficient and flexible, but extra care
should be taken when defining them
#define MULT(x, y) ((x) (x * y)* (y))
int main() {
int x;
x = MULT(5, 4); //x = 20
x = MULT(4+2, 5+4); //x = 18, Why?
}
31
Bitwise operations
C-language allows performing bitwise operations on
variables
unsigned char a = 0xAA, b = 0x74, c;
c = a | b; // OR
c = a & b; // AND
c = a ^ b; // XOR
c = ~b; // NOT
c = a << 1; // right-shift *2
c = a << 2; // right-shift *4
c = b >> 1; // logical left-shift /2
c = b >> 3; // logical left-shift /8
32
Read-Modify-Write
Bitwise operators allow performing read-
modify-write operations in a single C
statement.
For example, to write 1 to bit 3 of Port A
without affecting other bits, you can use OR
masking (e.g. GPIO_PORTA_DATA_R |= 0x8;)
General formula to modify bit x in R:
Set OR R |= (1<<x)
Reset AND R &= ~ (1<<x)
Toggle XOR R ^= (1<<x)
33
Read-Modify-Write
Important: this operation is not safe with
interrupts or multi-threaded program.
GPIO_PORTA_DATA_R |= 0x8; is converted to
LDR r0,[pc,#16] ; r0 =0x400043FC
LDR r0,[r0] ; READ
What if an interrupt
ORR r0,r0,#0x08 ; MODIFY is triggered here
whose an ISR
MOV r1,#0x40004000 modifies Port A??

STR r0,[r1,#0x3FC]; WRITE


34
Read-Modify-Write
To overcome this problem, either use bit-
banding addresses or masked addresses of
GPIODATA
See datasheet p. 654 and 662
35
Quiz
Next Monday 16/10/2017
36
References
Textbook sections:
None

Recommended: Valvano and Yerraballi,


Embedded Software in C for an ARM Cortex
M, 2015
http://users.ece.utexas.edu/~valvano/embed/toc
1.htm
37
Thank You
Questions?

You might also like