57
TKT-3500 Microcontroller systems Lec 2b Programming with C Teemu Laukkarinen Department of Computer Systems Tampere University of Technology Fall 2011 Copyright Tampere University of Technology Department of Computer Systems

TKT-3500 Microcontroller systems · B.W. Kernigham, Programming in C: A Tutorial, [online] ... Inside functions, C only allows presenting new

  • Upload
    lytu

  • View
    223

  • Download
    3

Embed Size (px)

Citation preview

TKT-3500

Microcontroller

systems

Lec 2b – Programming with C

Teemu Laukkarinen

Department of Computer Systems

Tampere University of Technology

Fall 2011

Copyright Tampere University of Technology Department of Computer Systems

#2/55

Sources

Original slides by Erno Salminen B.W. Kernigham, D.M. Ritchie, The C

programming language, Prenctice Hall PTR, 2nd ed. 1988.

B.W. Kernigham, Programming in C: A Tutorial, [online] http://www.lysator.liu.se/c/bwk-tutor.html

S. Holmes, C Programming, [online] http://www2.its.strath.ac.uk/courses/c/

Wikipedia

Thanks also to Heikki Orsila, Mauri Kuorilehto, and Teemu Laukkarinen

Copyright Tampere University of Technology Department of Computer Systems

#3/55

Contents

Introduction

Functions and basic data types

Pointers, arrays, strings, structures

Part 2:

Placement in memory

Macros

Interrupts handlers

Compilation and linking

Call conventions

Copyright Tampere University of Technology Department of Computer Systems

#4/55

C programming language

General-purpose, compiled, block structured,

procedural, imperative computer

programming language

Based on B language

Developed in 1972

by Dennis Ritchie at the Bell Telephone

Laboratories for use with the Unix operating

system

See also:

http://www.lysator.liu.se/c/bwk-tutor.html

http://www2.its.strath.ac.uk/courses/c/

Copyright Tampere University of Technology Department of Computer Systems

#5/55 Copyright Tampere University of Technology Department of Computer Systems

#6/55

D

Erlang

Smalltalk

[DedaSys LLC , Programming Language Popularity,

http://www.langpop.com/widget/]

Popularity of programing languages

Results based on searches in Yahoo, Craigs list, Amazon, Freshmeat,

Google code, and Del.icio.us

Copyright Tampere University of Technology Department of Computer Systems

#7/55

The first C program

#include <stdio.h>

void main(int argc, char *argv[])

{

/* Comments are added like this */

printf(“Hello world\n");

}

Every C program contains a function named main printf is a library function which will format and print output on

the terminal (not necessarily available on embedded systems)

#include <stdio.h> allows its usage

Curly brackets group statements together e.g. in function or loop

grouping is known as a compound statement or a block

C is case sensitive A lower and upper case letter (z and Z) are two separate letters

However, white spaces are removed (if not in quotes)

Copyright Tampere University of Technology Department of Computer Systems

#8/55

Code blocks

Inside functions, C only allows presenting new

variables in the beginning of code blocks

This is different than in C++

This is not true of the new C99 standard, though

For the backwards compatibility sake, put them to the

beginning

void example_f(void)

{

int x; /* good */

x = 0;

int y; /* bad */

if (x == 0) {

int z; /* good, a new code block inside if () */

Copyright Tampere University of Technology Department of Computer Systems

#9/55

Functions

Sometimes called subroutines or procedures

Encapsulates a block of instructions that can be used (called) more than once Easier design, maintenance, and debugging

Takes usually fixed number of input parameters

Return at most one value

int add (int a, int b) {

int c = a + b;

return c;

}

Copyright Tampere University of Technology Department of Computer Systems

#10/55

Local and global variables

Function may define local variables c in prev example

Other functions cannot access them – limited scope

However, they can be accessed via pointers

Functions may have locals with identical names without conflicts

Mem is allocated for them dynamically from the stackduring function call and released upon return

On the other hand, global variables are visible to one or several modules Declared outside any function

Initialized to zero before entering main()

A global variable is constantly in the same memory address

Copyright Tampere University of Technology Department of Computer Systems

#11/55

Control statements

Conditional execution:

if-then-else: basic branching

switch-case: multi-way decision, often 1 out of N

continue: starts next loop iteration

break: exits from switch or loop

goto: jump to certain address/label

Loops:

for: repeat for known num of iterations

while: repeat as long as condition holds

do-while: as while, but interate at least once

Copyright Tampere University of Technology Department of Computer Systems

#12/55

Control statements – True/false

If, switch, for, while, and do-while perform a

test

Body is executed only if test return logical ”true”

if (a == 5) {}; /* equality */

if (a != 0) {}; /* inequality */

for (a=0; a<5; a++){} /* a is 0,1,2,3,4*/

while (a) {... a--; ..} /* until a==0 */

Note! Zero is considered ”false” whereas all other

values are ”true”

Value 5 is true but its inverse, ~5, is also true

Copyright Tampere University of Technology Department of Computer Systems

#13/55

Flowcharts

Flowcharts are simple graphical representations of program steps Visualize the actions and conditions

Especially good for assembly programming

Not too suitable for interrupts

ConditionT

Case #1

F

Condition

T

Case #2

F

...T

...

F

ConditionT

Case #N

F

Selection (switch)

ConditionF

Loop Task

T

Repetition (do..while)

ConditionT

Loop Task

F

Selection (while)

First task

Next task

Task sequence

ConditionT F

Task #1 Task #2

Selection (if..then.else)

Copyright Tampere University of Technology Department of Computer Systems

#14/55

Data types

Copyright Tampere University of Technology Department of Computer Systems

#15/55

Data types

Data type defines allowed operations and

defines size of allocated memory

Data type is given when defining variables: int freespace;

when defining function’s return value: int main()

when defining function’s parameters: int foo (int a)

Value range of a data type depends on the used processor and compiler! int may be 8,16, 32, 36 bits, or any other size

Creates many problems when porting programs

4 basic data types: char, int, float, anddouble

Copyright Tampere University of Technology Department of Computer Systems

#16/55

Data types - integer

int – integer number

int answer = 42;

int b = answer / 5; /* == 8 */

int c = answer / 50 * 2;/* == 0*/

Most common data type in C

Reflects natural size of integers on the host

machine

E.g. 16 bits in PIC, 32 bits in ARM

Size modifiers presented later

”Natural size” aims to fast execution

Copyright Tampere University of Technology Department of Computer Systems

#17/55

Data types – char

char – character

Pronounced [ka-rak-tər], not [za-rak-ter]

A small integer, at least 8 bits 28=256 distinct values, enough to store western

alphabets (ASCII)

Type is not restricted to alphabets by any means!

char initial = „E‟, char grade = 4;

Standard does not specify signedness Use signed char or unsigned char when

sign is relevant

In most CPUs, smallest unit of memory access is 1 byte which usually equals 1 char

Copyright Tampere University of Technology Department of Computer Systems

#18/55

Data types – float, double

float – floating point (single precision) float temperature = 37.2;

double – floating point (double precision)

Larger value range

Floating-point ALU takes large silicon area Floating point types are usually not available as

native types on embedded systems

a) Adopt fixed-point arithmetic

b) Emulated with SW, when performance is not important Simpler than fixed point programming

Takes tens to hundreds of cycles per FP operation

Copyright Tampere University of Technology Department of Computer Systems

#19/55

Data types – void, enum

void – not really a data type

Used to denote that function does not return any value, void foo() {… return;}

Used also with pointers

enum – enumeration

Used for integer constants

enum command_id {

send = 1;

receive = 2;

abort = 4;

}

Compilers may support non-standard types also E.g. with microcontrollers!

Copyright Tampere University of Technology Department of Computer Systems

#20/55

Data type modifiers

Modifiers signed and unsigned

Define how the bit representation of a number is

interpreted and handled. Very useful.

char’s type depends on compiler, but modifier forces the

range of 8-bit char [-128, 127] or [0, 255]

int is signed by default

Modifiers short and long

Used storage space (=value range) :

char ≤ short int ≤ int ≤ long int

float ≤ double ≤ long double

The standard does not require that any of these sizes are

necessarily different

Sometimes these affect, but not always! Avoid.

Copyright Tampere University of Technology Department of Computer Systems

#21/55

Libraries stdint.h and limits.h

With #include <stdint.h> you can use

portable data types

int8_t is always 8 bits

int16_t, int32_t, int64_t similarly

intptr_t always the size of address space

allows arithmetic and bit operations on

addresses, for example to make zeros of LSBs

int may be too small for that on some platforms

(usually 64-bit systems)

With #include <limits.h> you can see

minimum/maximum values of data types

Copyright Tampere University of Technology Department of Computer Systems

#22/55

Sizeof()

Built-in operator returns the amount of

memory (number of characters/bytes) needed

for

a type

a variable

Hence sizeof(char) == 1

Needed, e.g., in dynamic memory allocation with malloc()

int a;

sizeof(int) == 2;

sizeof (a) == 2;Copyright Tampere University of Technology Department of Computer Systems

#23/55

Data type qualifiers - const

const - constant

The const qualifier is used to tell C that the

variable value can not change after

initialization

const float pi = 3.14159;

pi = 3.14; /* Aargh! Error*/

Also ensures that function does not modify its

parameters

int foo (const int *ptr) {...}

Especially with pointer parameters

Copyright Tampere University of Technology Department of Computer Systems

#24/55

Data type qualifiers – const/#define

Another way is the preprocessor command #define

which has the advantage that it does not use any storage

#define pi 3.14159

All occurrences of string pi are replaced with

immediate value 3.14159 before compilation

Simple string replacement may cause problems unless you

use parentheses

#define kekki pi + 1

... float a = 2 * kekki; /* 2 * pi + 1 */

Note, with π you should really use #include

<math.h> and then use constaint M_PI

Copyright Tampere University of Technology Department of Computer Systems

#25/55

Data type qualifiers - volatile

volatile - subject to rapid or unexpected change

Tells the compiler that the value of a variable is volatile, which means

Access to it will always generate a load or store operation on the underlying memory space

Compiler will not generate a code that tries to remember the old value in a register (read:

compiler will not try to optimize use of that variable; read2: compiler will not assume anything

about the value of that variable)

Used in peripheral accesses

volatile int *hw_data_reg = 0xFF50;

while (*hw_data_reg == 0) {...

Also used on variables modified in interrupts and read on normal code (very very

dangerous…)

Note, volatile is a potential sign of bug

Wherever you use volatile, you are potentially making an atomicity, mutual exclusion or

synchronization error, since the access to a volatile variable is not atomic operation!

Inline assembler, processor or compiler specific knowledge is often needed in these cases

DO NOT use on variables shared between threads (without synchronization,

however, correct synchronization makes volatile useless, self-study more

http://kernel.org/doc/Documentation/volatile-considered-harmful.txt )

Note 2, forgetting volatile from variables changed by the HW will also cause

serious and hard to find bugs, which appear randomly

Copyright Tampere University of Technology Department of Computer Systems

#26/55

Data type storage classes - extern

Storage class provides information about variable’s location and visibility

extern – external variable or function

When using global variables, extern directive can be put to a “header” file to announce existence of a given global variable to other code modules File foo.h presents the integer to other modules:

#ifndef _FOO_H_

#define _FOO_H_

extern int myinteger;

#endif

File foo.c declares the variable, i.e. reserves space for it:#include “foo.h”

int myinteger;

File bar.c can use myinteger:#include “foo.h”

... myinteger += 1;

Copyright Tampere University of Technology Department of Computer Systems

#27/55

Data type storage classes – static, register

static variables As a local variable, static variable retains its value even after the

control is transferred to the calling function

It is really a global variable with limited visibility Dangerous! Use global variables instead.

void count_usages(void) {

static int callcount = 0; /* initial value zero */

callcount++;

printf(“foo has been called %d times\n”, callcount);

}

When used as a global variable, a static variable is only visible inside the code module

register

Compiler tries to keep such variable in the CPU’s register for faster access

Do not use unless you’re very certain. Nothing is guaranteed.

Copyright Tampere University of Technology Department of Computer Systems

#28/55

Bit manipulation

Copyright Tampere University of Technology Department of Computer Systems

#29/55

Purpose

Bit manipulation differs from regular artihmetics behavior of which depends on the data types (char, int...)

One may manipulate individual bits of any data type Set certain bit(s) to 1

Clear certain bit(s) to 0

Complement certain bit(s)

These are logical operations

Remember: ALU = arithemetic-logic unit

Useful for handling control registers

reading status registers

using general purpose input/output pins

Combine larger data values from 8 bit pieces Typical on embedded systems: 32bit or so variables are transferred on

8bit pieces through a serial interface

Copyright Tampere University of Technology Department of Computer Systems

#30/55

Reese, chap4_logctrl.pdf, slide 5-

Copyright Tampere University of Technology Department of Computer Systems

#31/55 Copyright Tampere University of Technology Department of Computer Systems

#32/55 Copyright Tampere University of Technology Department of Computer Systems

#33/55 Copyright Tampere University of Technology Department of Computer Systems

#34/55

Combine two 8bit to 16bit (and vise

versa)

uint16_t target = 0;

uint8_t byte_hi = 0xFF;

uint8_t byte_low = 0xAA;

target = byte_hi; // target == 0x00FF

target <<= 8; // target == 0xFF00

target |= byte_low; // target == 0xFFAA

// NOTE: some compilers can be stupid (or wise?)

// and require to work that operands are the same

// size, then

target |= (uint16_t) byte_low;

// or even

target |= (0x00FF & (uint16_t) byte_low);

uint16_t source = 0xFFAA;

uint8_t byte_hi;

uint8_t byte_low;

byte_hi = (target >>8); // byte_hi == 0xFF

byte_low = target; // byte_low == 0xAA

// works on most compilers, might require type

// conversion to compile without warnings

#35/55

Pointers, arrays, strings, structures

Copyright Tampere University of Technology Department of Computer Systems

#36/55

Pointers

A pointer in C is the address of something address of a variable or function

Whereas variable name is an alias of memory address

The unary operator `&' is used to produce the address of an object, if it has one.

1000x54

0x55 0x54

memoryaddress

0x56 ...

variable

a

b

int a, *b;

a = 100;

b = &a;

...

b has the address of variable a

NOTE: DO NOT INITIALIZE POINTERS

ANR VARIABLES ON SAME TIME!

Copyright Tampere University of Technology Department of Computer Systems

#37/55

Pointers (2)

Revised example

int a, *b, c;

a = 100;

b = &a;

c = *b;

b is now a pointer

*b means the value pointed to by b

This in-direct access is known as dereferencing

Works both ways

*b = 7;

1000x54

0x55 0x54

memoryaddress

0x56 100

variable

a

*b

c

...

1000x54

0x55 0x54

0x56 100

a

*b

c

...

7

Copyright Tampere University of Technology Department of Computer Systems

#38/55

Pointers (3)

Most frequent uses of pointers in C are 1. For computing addresses of data

2. Passing an address of a memory area to a function

3. Passing an address to a variable whose value is changed in a function that is called

4. Accessing memory-mapped registers of HW

Pointers can also be declared as void pointers

They can't be dereferenced without explicit casting

int x;

float f;

void *p = &x; // p points to integer x

*(int*)p = 2; // dereferencing p

p = &r; // p points to float r

*(float*)p = 1.1;

Copyright Tampere University of Technology Department of Computer Systems

#39/55

Arrays

Arrays are often visible as pointer-like objects in C

Denoted with brackets []

Example: Compute a sum of value in a table until a

zero value is reached:

int table[] = {1, 2, 3, 0};

int i;

int sum = 0;

for (i = 0; table[i] != 0; i++){

sum += table[i];

printf(“sum is %d\n”, sum);

}

Copyright Tampere University of Technology Department of Computer Systems

#40/55

Arrays (2)

Arrays are defined by 1. type (mandatory), and

2. optional size, or

3. optional initializerint table[5]; /* non-initialized array of 5 int */

int values[] = {1, 2, 3}; /* array of 3 initialized int */

int *p = values; /* p points to the 1st int of array */

/* same as int *p = &values[0] */

values[1] = 4; /* update to {1,4,3} */

p[1] = 5; /* update to {1,5,3} */

p += 1; /* or p++, p points now to 2nd int */

*p = 6; /* update to {1,6,3} */

/* Do not mix ptr arithmetics and indexing*/

Copyright Tampere University of Technology Department of Computer Systems

#41/55

Arrays (3)

NOTE! p++ increases actual value of p by sizeof(dereferenced type)

Similarly with indexing

Note that there’s no implicit index checking! Possible buffer overflow

int *iptrchar *cptr

0xde

0xad

0xbe

0xef

7 0...

bit index

0x01

0x23

0x45

0x67...

...

0x0

0x4

iptr[1]

iptr[0]cptr = (char*) iptr

cptr[1]

cptr[2]

byte addr

(Pointers *iptr and *ctpr are actually in

the same mem as arrays. They are

drawn separately for clarity.)

memory

Copyright Tampere University of Technology Department of Computer Systems

#42/55

Arrays (4)

Global arrays are initialized to zero by default

Local arrays are unitialized without explicit initialization

sizeof(table) is the size of memory

occupied by the table (five integers in bytes)

memset(table, 0, sizeof(table));

fills the table with zeroes

Warning: sizeof(p) is now just the space

occupied by the pointer

E.g. sizeof(p) == 4 on 32-bit architectures

Copyright Tampere University of Technology Department of Computer Systems

#43/55

Strings

Strings are a common special case of arrays

Strings are char arrays that are terminated with a

zero

Strings can be explicitly initialized with double quotes “”:

char text[] = “hello, world!”;

printf(“%s\n”, text);

Total length of text[] is actually 14 characters =13

alphabets and terminating zero

h e l l o , w o r l d ! 0x0mem contents

0x5

00

0x5

04

0x5

08

0x5

0b

mem addr

Symbol text means simply the start

address 0x500

Copyright Tampere University of Technology Department of Computer Systems

#44/55

Strings (2)

C has a number of string function, use #include <string.h> to use them

strcpy() – copy a string

strcat() – concatenate two stringschar text[256] = “Hello, “;

strcat(text, “world!”);

printf(“%s\n”, text); /* Prints “Hello, world!” */

strlen() – return the length of a string

strlen(“foo”) == 3

To find more about any standard C function, login to proffa and type: man

function_name -> e.g. man strcpyCopyright Tampere University of Technology Department of Computer Systems

#45/55

Strings (3)

As a special case:

char *text = “hello, world!”

is a string constant

The content of this string may not be written to

However, string constants can be used anywhere, so

we can easily copy given strings to any char arrays:char *text = malloc(32); /* allocate 32 bytes */

if (text == NULL)

return; /* allocation failed */

strcpy(text, “hello, world!”); /* init text with constant */

text[0] = „H‟; /* capitalize first letter */

printf(“%s\n”, text);

NULL is used to denote a zero valued pointer to

distinguish it from a zero valued integer

Copyright Tampere University of Technology Department of Computer Systems

#46/55

Structures

A structure is a collection of one or more

variables, possibly of different types, grouped

together into a single convenient package

struct vector {

float x;

float y;

float z;

}; /* Note, definition terminated with ; */

struct vector origo = {0, 0, 0};

Copyright Tampere University of Technology Department of Computer Systems

#47/55

Structures (2)

Structures

can be passed as arguments to functions, or

can be returned from a function, and

the semantics are that of memory copying, unless pointers are passed

Structures can be initialized like arrays, but

they are more convenient to use:

struct user {

char *name;

int age;

};

Copyright Tampere University of Technology Department of Computer Systems

#48/55

Structures (3)

struct user admin = {“Aulis

Kaakko”, 35};

Note, any modern C compiler allowsstruct user admin = {.name = “Aulis Kaakko”, .age = 35};

One need not know all elements or their order

Omitted elements are reserved as zeros in mem struct user admin = {.name = “Bubi”}; /* age becomes 0*/

printf(“User name/age: %s/%d\n”,

admin.name, admin.age);

Copyright Tampere University of Technology Department of Computer Systems

#49/55

Structures (4)

Arrays of structures are of course possible:

struct vector axes[3] =

{{1, 0, 0}, {0, 1, 0}, {0, 0, 1}};

sizeof(axes) == 36 /* == 3 * 3 * 4 */

Elements of the structure

are placed in memory in the same order as they

are presented in the structure

but the space between the elements is

compiler/arch dependent

Copyright Tampere University of Technology Department of Computer Systems

#50/55

Structures (5)

Natural alignment of microprocessors often

causes padding between elements,

e.g. a char can be accessed from any address,

but an integer can only be accessed from addresses divisible by sizeof(int))

Space occupied by a structure is not the sum

of its element sizes:

sizeof(struct {char c; int d;}) == 8,

on many 32-bit archs

d

c

something else

...

struct

8 7..031

Copyright Tampere University of Technology Department of Computer Systems

#51/55

Structures (6)

When you have a structure in the embedded world (and even in the desktop world):

IF YOU DO NOT KNOW THE SIZE OF THE STRUCTURE, PASS IT AS A POINTER TO FUNCTIONS

Otherwise the structure is reserved from the (software) stack and it may consume huge amount of stack memory

struct huge {

uint8_t stupid_table[1024];

};

void huge_stack_consumption(struct huge take_all_you_can_parameter); // NO!

void stack_consumption_of_a_pointer(struct huge* small_consumption); // YES!

void stack_consumption_of_a_pointer(struct huge const* small_consumption); // EVEN BETTER!

// NOTE: here we denoted that stuff behind small_consumption pointer should not be modified

// following will enforce only pointer to be unaltered (which is stupid on function parameters)

void foobar(int *const ptr); // cannot say: ”ptr = 0;”, but can say ”*ptr = 0;”

// and last, this will not allow modifing the struct nor the pointer

void foobar(int const * const ptr); // cannot say: ”ptr = 0; *ptr = 0”

#52/55

PIC-specific considerations

Copyright Tampere University of Technology Department of Computer Systems

#53/55 Copyright Tampere University of Technology Department of Computer Systems

#54/55 Copyright Tampere University of Technology Department of Computer Systems

#55/55 Copyright Tampere University of Technology Department of Computer Systems

#56/55

However after power off RAM contents lost

-> Use EEPROM: safer but more time consuming and space constrainedCopyright Tampere University of Technology Department of Computer Systems

#57/55

Common Wisdom

"C makes it easy to shoot yourself in the foot.

C++ makes it harder, but when you do, it blows

away your whole leg.“ --- Bjarne Stroustrup,

creator of C++

C++:han on todella ”onnistunut” oliokieli (Luennoijan

mielipide )

Everyone knows that debugging is twice as hard

as writing a program in the first place. So if

you're as clever as you can be when you write it,

how will you ever debug it? --- Brian Kernighan

Controlling complexity is the essence of

computer programming. --- Brian Kernighan