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

C programming for embedded

microcontroller systems.

Assumes experience with assembly language programming.


R. Lopez Ph. D.
8/19/2021
Embedded Toolchain

➢ A toolchain is the set of software tools which allow


a program to run on an embedded system
➢ Host machine is the machine running the toolchain
➢ Target machine is the embedded system where the
program will execute
• Host has more computational power then target
➢ We are using the GNU toolchain
• Free, open source, many features
Cross-Compiler

➢ A compiler which generates code for a platform


different from the one it executes on
• Executes on host, generates code for target
➢ Generates an object file (.o)
➢ Contains machine instructions
➢ References are virtual
• Absolute addresses are not yet available
• Labels are used instead
Cross-Compiler Example
ABBOTT.c COSTELLO.c
int idunno; int whosonfirst(int x)
… {
whosonfirst(idunno) …
… }

Cross- compiler Cross- compiler

ABBOTT.o COSTELLO.o
… … Idunno, whosonfirst
MOVE R1, (idunno) …
CALL whosonfirst whosonfirst:
… …
Unknown addresses
Linker

➢ Combines multiple object files


➢ References are relative to the start of the executable
➢ Executable is relocatable
➢ Typically need an operating system to handle
relocation
Linker Example
ABBOTT.o COSTELLO.o
… …
MOVE R1, (idunno) whosonfirst:
CALL whosonfirst MOVE R5, R1
… …

Linker

HAHA.exe

MOVE R1, 2388 ➢ Functions are merged
CALL 1547
… ➢ Relative addresses used
1547 MOVE R5, R1

2388 (value of idunno)
Linker/Locator

➢ Links executables and identifies absolute physical


addresses on the target
➢ Locating obviates the need for an operating system
➢ Needs memory map information
• Select type of memory to be used (Flash, SRAM, …)
• Select location in memory to avoid important data (stack,
etc.)
• Often provided manually
Segments

➢ Data in an executable is typically divided into segments


➢ Type of memory is determined by the segment
➢ Instruction Segment - non-volatile storage
➢ Constant Strings – non-volatile storage
➢ Uninitialized Data – volatile storage
➢ Initialized Data – non-volatile and volatile
• Need to record initial values and allow for changes
AVR GNU Toolchain

➢ Cross-Compiler: avr-gcc
➢ Linker/Locator: avr-ld
➢ Cross-Assembler: avr-as
➢ Programmer: avrdude

➢ All can be invoked via Atmel Studio 6


Introduction to C
Intended use and underlying philosophy
1 C is a low-level language
---suitable language for systems programming
2 C is a small language
---relies on a “library” of standard functions
3 C is a permissive language
---it assumes that you know what you’re doing, so it allows
you a wider degree of latitude than many languages. It
doesn’t mandate the detailed error-checking found in
other language
Introduction to C
Strengths:
+ Efficiency: intended for applications where assembly language
had traditionally been used.
+ Portability: hasn’t splintered into incompatible dialects; small
and easily written
+ Power: large collection of data types and operators
+ Flexibility: not only for system but also for embedded system
commercial data processing
+ Standard library

+ Integration with UNIX


Introduction to C
Weaknesses:

+ error-prone

+ difficult to understand

+ difficult to modify
Similarities of C to java
/* Comments */
Variable declarations
if / else statements
for loops
while loops
function definitions (like methods)
Main function starts program
Differences between C and java
C does not have objects
There are “struct”ures
C is a functional programming language
C allows pointer manipulation
Input / Output with C
Output with printf function
Input with scanf function
C Fundamentals
First program

#include <stdio.h>
main()
{
printf(“To C, or not to C: that is the question”);
}
C Fundamentals
Compiling and Linking
Preprocessing: the program is given to a preprocessor,
which obeys commands that begin with #(directives)
add things to the program and make modifications

Compiling: modified program→compiler→object


code
Linking: add library functions to yield a complete
executable program
C Fundamentals
Compiler

% cc –o pun pun.c
% gcc –Wall –o pun pun.c
C Fundamentals
Keywords

auto double int struct


break else long switch
case enum register typedef
char extern return union
const float short unsigned
continue for signed void
default goto sizeof volatile
do if static while
Basic C program structure
Microcontroller “header file”
Keil MDK-ARM and Arduino provides a derivative-specific“header file” for each microcontroller, which defines
memory addresses and symbolic labels for CPU and peripheral function register addresses.
C compiler data types
C compiler data type
C program
Every C program starts its execution from main( ) function and we do
call other userdefined or standard library functions inside our main( )
function. We do write all our programs also inside the main( )
Every C Statements terminates with a semicolon ‘ ; ‘
printf( ) is the standard library function we use to print something into
the console.
Typical Embedded C Program
#include <stdio.h>

main() {
// initialization code
while (1) {
// main code
}
}

➢#include is a compiler directive to include (concatenate)


another file
➢main is the function where execution starts
Let’s Revise C Programming
C programming Language was introduced in the year
of 1972 by Dennis Ritchie of AT&T Bell Laboratories.

Let’s start our first program, the traditional Hello World!..


Program

/*Program to Print Hello World*/


#include<stdio.h>

void main( )
{
printf(“Hello World!..”);

}
Here the things given inside /* */ are called
comments which will be ignored by the compiler
during compilation time
When we write the pre-processor directive
#include<stdio.h> our pre-processor will also
include the header file stdio.h which contains the
defenitions for standard input output functions.
C Syntax Basics
➢Comments: single line //, multiline /* … */
➢Semicolon used to terminate all statements
➢# indicates a compiler directive (include, define, etc.)
➢Brackets { … } group lines of code for execution
➢Blankspace between lines is not important in C
•Still need to separate tokens

int a, b, c;
int a,b,c;a=b+c; inta,b,c;a=b+c;
a = b + c;

correct correct incorrect (inta)


stdio.h
So if we include stdio.h in our program, we will be able to use those
standard functions in our program.
Similary there are also many standard and user defined header files
and if we include them in our program we will be able to use the
functions defined int that in our program.
Variables

➢All variables’ types must be declared


•Memory space requirements known statically
•Type checking can be performed at compile-time
➢Numerical Types: int, float, double
➢Other types: char, void
➢Type qualifiers: short, long, unsigned, signed, const
•Specify alternate sizes, constrain use modes
Variables

➢All variables’ types must be declared


•Memory space requirements known statically
•Type checking can be performed at compile-time
➢Numerical Types: int, float, double
➢Other types: char, void
➢Type qualifiers: short, long, unsigned, signed, const
•Specify alternate sizes, constrain use modes
Data Types
char, int, float, double
long int (long), short int (short),
long double
signed char, signed int
unsigned char, unsigned int
1234L is long integer
1234 is integer
12.34 is float
12.34L is long float
Variable Type
C has the following simple data types:
Variable Type
Java has the following simple data types:
Basic Types
Type (16 bit) Smallest Value Largest Value

short int -32,768(-215) 32,767(215-1)

unsigned short int 0 65,535(216-1)

Int -32,768 32,767

unsigned int 0 65,535

long int -2,147,483,648(-231) 2,147,483,648(231-1)

unsigned long int 0 4,294,967,295


Basic Types
Type (32 bit) Smallest Value Largest Value

short int -32,768(-215) 32,767(215-1)

unsigned short int 0 65,535(216-1)

Int -2,147,483,648(-231) 2,147,483,648(231-1)

unsigned int 0 4,294,967,295

long int -2,147,483,648(-231) 2,147,483,648(231-1)

unsigned long int 0 4,294,967,295


Reading and Writing Integers
unsigned int u;
scanf(“%u”, &u); /* reads u in base 10 */
printf(“%u”, u); /* writes u in base 10 */
scanf(“%o”, &u); /* reads u in base 8 */
printf(“%o”, u); /* writes u in base 8 */
scanf(“%x”, &u); /* reads u in base 16 */
printf(“%x”, u); /* writes u in base 16*/
short int x;
scanf(“%hd”, &x);
printf(“%hd”, x);

long int x;
scanf(“%ld”, &x);
printf(“%ld”, x);
Floating Types
float single-precision floating-point
double double-precision floating-point
long double extended-precision floating-point

Type Smallest Largest Value Precision


Positive Value
float 1.17*10-38 3.40*1038 6 digits

double 2.22*10-308 1.79*10308 15 digits

double x; long double x;


scanf(“%lf”, &x); scanf(“%Lf”, &x);
printf(“%lf”, x); printf(“%Lf”, x);
Constant/literal values
Program variables
Variable arrays
Automatic variables
Automatic variable example
Static variables
Static variable example
C statement types
Basic Data Types

• int is used to define integer numbers.


• Eg :int x =6;
• float is used to define floating point numbers.
• Eg: float y = 3.231;
• double is used to define BIG floating point numbers. It reserves twice
the storage for the number. On PCs this is likely to be 8 bytes.
• Eg: double z = 234.2376546;
Character Variables
• char defines characters and they are usually enclosed in a single
quotes and they could hold onle a single character values.
• Eg: char newChar = ‘A’;
• For storing strings, we use array of characters and they are being
terminated by null character ‘\0’.
• Eg: char name = {‘R’, ‘a’, ‘m’, ‘\0’};
Character Types
char ch;
int i;
i = ‘a’; /* i is now 97 */
ch = 65; /* ch is now ‘A’ */
ch = ch + 1; /* ch is now ‘B’ */
ch++; /* ch is now ‘C’ */

if(‘a’ <= ch && ch <= ‘z’)

for(ch = ‘A’; ch <= ‘Z’; ch++)


Char Type
‘a‘, ‘\t’, ‘\n’, ‘\0’, etc. are character
constants
strings: character arrays
− (see <string.h> for string functions)
− "I am a string"
− always null (‘\0’) terminated.
− 'x' is different from "x"
Type Conversion
narrower types are converted into wider
types
− f + i int i converted to
characters <---> integers
<ctype.h> library contains
conversion functions, e.g:
− tolower(c) isdigit(c) etc.
Boolean values:
− true : >= 1 false: 0
Type Conversion

long double Unsigned long int

long int
double
unsigned int

float int
Type Conversion
char c;
short int s;
int i;
unsigned int u;
long int l;
unsigned long int ul;
float f;
double d;
long double ld;
i = i + c; /* c is converted to int */
i = i + s; /* s is converted to int */
u = u +i; /* i is converted to unsigned int */
l = l + u; /* u is converted to long int */
ul =ul + l; /* l is converted to unsigned long int */
f = f + ul; /* ul is converted to float */
d = d + f; /* f is converted to double */
ld = ld + d; /* d is converted to long double */
Casting
( type-name ) expression
float f, frac_part;
frac_part = f – (int) f;

float quotient;
int dividend, divisor;
quotient = (float) dividend / divisor;

short int i;
int j = 1000;
i = j * j; /* WRONG */
Basic Operators in C:
•Arithmetic Operators A=10, B=20

Operat
Description Example
or
+ Adds two operands A + B will give 30
- Subtracts second operand from the first A - B will give -10
* Multiply both operands A * B will give 200
/ Divide numerator by denumerator B / A will give 2
% Modulus Operator and remainder of B % A will give 0
after an integer division
++ Increment operator, increases integer A++ will give 11
value by one
-- Decrement operator, decreases integer A-- will give 9
value by one
•Logical / Relational Operators:

Operat
Description Example
or
== Checks if the value of two operands is equal or (A == B) is not true.
not, if yes then condition becomes true.
!= Checks if the value of two operands is equal or (A != B) is true.
not, if values are not equal then condition
becomes true.
> Checks if the value of left operand is greater than (A > B) is not true.
the value of right operand, if yes then condition
becomes true.
< Checks if the value of left operand is less than the (A < B) is true.
value of right operand, if yes then condition
becomes true.
>= Checks if the value of left operand is greater than (A >= B) is not true.
or equal to the value of right operand, if yes then
condition becomes true.
Logical / Relational Operators:
<= Checks if the value of left operand is less than or equal to the value of (A <= B) is true.
right operand, if yes then condition becomes true.
&&
Called Logical AND operator. If both the (A && B) is true.
operands are non-zero then then condition
becomes true.
||
Called Logical OR Operator. If any of the two (A || B) is true.
operands is non-zero then then condition
becomes true.
!
Called Logical NOT Operator. Use to reverses !(A && B) is false.
the logical state of its operand. If a condition
is true then Logical NOT operator will make
false.
• Logical Operators
• A logical operator operated between two relational or logical
expressions and returns a logical value.

• && - Logical AND
• || - Logical OR
•! - Logical Negation / NOT
Bitwise Operators
Bitwise operator works on bits and performs bit by bit operation.
Assume if A = 60; and B = 13; Now in binary format they will be as follows:
A = 0011 1100
B = 0000 1101
-----------------
A&B = 0000 1100 – Bitwise ANDing
A|B = 0011 1101 – Bitwise ORing
A^B = 0011 0001 – Bitwise XORing
~A = 1100 0011 – Bitwise Negation operator
<< - Left shift operator
>> - Right Shift Operator
NB: Please make yourself very clear about bitwise operators as we use them
much frequently while programming the microcontrollers.
sizeof( ) – operator is used to get the size (in bytes) which a variable or a data
type takes in memory.
Type Definitions
typedef int BOOL
BOOL flag; /* same as int flag; */

typedef short int Int16


typedef long int Int32
typedef unsigned char Byte

typedef struct {int age; char *name} person;


person people;
Variable Declaration
➢Static allocation vs. Dynamic allocation
➢Static dedicates fixed space on the stack
• int i;
➢Dynamic (malloc) allocates from the heap at runtime
• ptr = malloc(32);
➢Type sizes depend on the architecture
•On x86, int is 32 bits
•On ATmega2560, int is 16 bits
•char is always 8 bits
Volatile Variables
➢The value of a volatile variable may change at any time, not
just at an explicit assignment
➢Also, may be read at any time
➢Compiler optimizations are not applied to volatile variables
for (i=0; i<10000; i++);

➢ An optimizing compiler would delete this loop


• i is not used anywhere in the code

i = 1; … i = 1;

➢ If i is not modified in between, the second assignment is


removed
Volatile Variables

➢When can variables be used without an explicit assignment?

1. Memory-mapped peripheral registers

2. Global variables modified by an interrupt service routine

3. Global variables accessed by other processors


Volatile Example
➢periph is the mapped address of the peripheral status info
➢*periph is assigned by peripheral directly
.
.
while (*periph != 1); // wait until data transfer
. // is complete
.

➢Compiled code will move memory contents to a


register
➢Memory will only be moved once because *periph
does not change
Base Representation

➢Base 10 is default
➢Base can be specified with a prefix before the number
➢Binary is 0b, Hexadecimal is 0x
Ex. char x = 0b00110011;
char x = 0x33;
➢Binary is useful to show each bit value
➢Hex is compact and easy to convert to binary
➢1 hex digit = 4 binary digits
Types of Statements

➢Assignment – =
➢Relational - <, >, ==, !=
➢Control Flow – if, for, while, do, switch
➢Arithmetic Operations - +, -, *, /, %
➢Logical Operations - &&, ||, !
➢Bitwise Logical Operations - &, |, ^
Logical Operators

➢These operators accept binary input and produce binary output


&&, ||, !

➢Non-binary inputs are cast to binary values

int a=1, b=0; c=56; d=-1, res;

res = a && b; // res = 0


res = a || b; // res = 1
res = c && d; // res = 1
Arithmetic Operations C Examples
Bit-parallel logical operators
Bit set/reset/complement/test
Bit examples for input/output
Example of μC register address definitions in STM32Lxx.h
(read this header file to view other peripheral functions)
Example of μC register address definitions in STM32Lxx.h
(read this header file to view other peripheral functions)
Example: I/O port bits
(using bottom half of GPIOB)
Shift operators
C control structures
C Review:
• If Statement: If there are no braces the next
If(condition is true) statement is the only statement
{ under the condition
Do whatever here…
}
Else if (another condition is true)
{
Do whatever here…
}
:
.
Else
{
Do a default operation
}
Simple if statement:
if(condition)
{
--Statements--
}
IF-THEN structure
Relational Operators
Boolean operators
Common error
IF-THEN-ELSE structure
• If –Else Statements
if(condition)
{
--Statements--
}
else
{
--Statements--
}
• If-Else-If Ladder
if(condition1)
{
--Statements--
}
else if(condition2)
{
--Statements--
}
else
{
--Statements--
}
IF-THEN-ELSE HCS12
assembly language vs C example
Ambiguous ELSE association
Multiple ELSE-IF structure
int i = 10; int j = 15; int k = 15; int m = 0;
if( i < j && j < k) =>
if( i != j || k < j) =>
if( j<= k || i > k) =>
if( j == k && m) =>
if(i) =>
if(m || j && i ) =>

8/30/2021
int i = 10; int j = 15; int k = 15; int m = 0;
if( i < j && j < k) => false
if( i != j || k < j) => true
if( j<= k || i > k) => true
if( j == k && m) => false
if(i) => true
if(m || j && i ) => true

Did you get the correct answers?

8/30/2021
Control Structures:
Sequential Control Structure
Eg: Usual programs in which we execute statements
one after the other.

Selection Control Structure


If statements in which a condition is being checked
and if it is true certain set of statements will get
executed.
SWITCH statement
WHILE loop structure
WHILE loop example: C vs. HCS12 Assembly Language
DO-WHILE loop structure
DO-WHILE example
WHILE examples
WHILE example
Break statement:
If we place a break statement inside a loop
after checking a condition and if it goes right, the
control will come out of the loop.
Eg:
for(int i = i; i<=10 ; i++)
{ /*Printing Multiplication Table of 5 */
printf(“%d x 5 = %d”, i, i*5);
if(i == 5)
break;
}
/*Here the loop will print only till 25 and later on i
becomes 5 and it breaks the loop*/
Continue Statement:
If we place a continue statement inside a loop after
checking a condition and if it goes right, the control
leave rest of the loop body, update the loop variable
and then continue the loop
for(int i = i; i<=10 ; i++)
{ /*Printing Multiplication Table of 5 */
printf(“%d x 5 = %d”, i, i*5);
if(i == 5)
break;
}/*Here the loop will not print 5*5 */
Iteration / Looping

For Loop
for(initialisation; condition ; updation)
{
--Loop Body--
}
Eg:
for(int i = i; i<=10 ; i++)
{ /*Printing Multiplication Table of 5 */
printf(“%d x 5 = %d”, i, i*5);
}
FOR loop structure
FOR loop structure
FOR structure example
FOR structure example
C functions
Functions
Functions are one of the most commonly used features in the
C Programming language. It helps users to separate blocks
of codes which could be reused again and again.
A program using functions may look something like this:
#include<stdio.h>
int myFunction(int , int);
void main( )
{
---------
---------
}

int myFunction(int x, int y)


{
int z;
z = (x+y)*x;
return z;
}
C functions
Function definition
Function arguments
My Function(int , int)

Here the line int myFunction(int , int); is called


function prototyping or declaration where we do tells
the compiler that a function with a name myFunction
exists and it takes two integer arguments. We need to
add this if we define the function just after the main( )

After the main we have defined the function


myFunction and we have given the function body.
Function
The general syntax of defining a function is:
<return-type> <function-name>(<parameter-list>)
{
--Function Body--
}

Return-type is the data type of value returned by a function to the


called program.
If a function does not return a value, we do give its return type as void.
int factorial(int x)
{
if(x == 1 || x ==0)
return 1;
else
return (x * factorial(x -1) );
}

• This is an example of a recursive function which does call


itself. This is a powerful programming technique but it is
least preferred in the embedded programming as it takes
a lot of space in the system stack and memory is a main
constraint in the Embedded Systems.
Example –pass by value
Example –pass by reference
Example –receive serial data bytes
Pointers
Pointer is the most beautiful (ugliest) part of C, but also brings most trouble to C
programmers. Over 90% bugs in the C programs come from pointers.
“The International Obfuscated C Code Contest ”
(http://www.ioccc.org/)

What is a pointer?
A pointer is a variable which contains the address in memory of another variable.

In C we have a specific type for pointers.

8/30/2021
Declaring a pointer variable
int * pointer;
char * name;
How to obtain the address of a variable?
int x = 0x2233;
pointer = &x;
where & is called address of operator.

How to get the value of the variable indicated by the


pointer?
int y = *pointer;
8/30/2021
What happens in the memory?
Suppose the address of variable x is 0x5200 in the above
example, so the value of the variable pointer is 0x5200.

X pointer
0x5200

33 22 00 00

0x5200 0x5203

8/30/2021
swap the value of two variables

8/30/2021
Why is the left one not working?

swap x, y
x, y, a, b are
all local
variables
main a, b

call swap(a, b) in main

8/30/2021
Why is the right one working?

8/30/2021
Pointers and Arrays
Pointers and arrays are very closely linked in C.
Array elements arranged in consecutive memory
locations

Accessing array elements using pointers


int ids[50];
int * p = &ids[0];
p[i] <=> ids[i]

Pointers and Strings


A string can be represented by a char * pointer.

8/30/2021
Books recommended
The C Programming Language, Brian Kernighan and Dennis Ritchie.
Second edition. Prentice-Hall, 1988. (C Bible)
The C++ Programming Language, Bjarne Stroustrup. Third edition.
Addison-Wesley, 1997. (C++ Bible)
Advanced Programming in the UNIX Environment, W. Richard Stevens,
Addison-Wesley, 1992. (APUE)

8/30/2021
Some on-line C tutorials

http://www.cprogramming.com/tutorial/c-tutorial.html
http://www.physics.drexel.edu/courses/Comp_Phys/General/C_basics/
http://www.iu.hio.no/~mark/CTutorial/CTutorial.html
http://www2.its.strath.ac.uk/courses/c/

You might also like