




























































































Study with the several resources on Docsity
Earn points by helping other students or get them with a premium plan
Prepare for your exams
Study with the several resources on Docsity
Earn points to download
Earn points by helping other students or get them with a premium plan
Community
Ask the community for help and clear up your study doubts
Discover the best universities in your country according to Docsity users
Free resources
Download our free guides on studying techniques, anxiety management strategies, and thesis advice from Docsity tutors
Lecture notes on C programming, pointers, constants and defines, tasks and schedulers, embedded system hardware and I/O, and interrupts. The notes are from a course offered by the Department of Electrical Engineering at the University of Washington in April 2009. The notes cover topics such as C program structure, including programs in multiple files and include files, and pointer arithmetic. The document could be useful as study notes or lecture notes for a university student studying electrical engineering or computer science.
Typology: Lecture notes
1 / 101
This page cannot be seen from the preview
Don't miss anything!
Embedded: Special purpose computing devices. Computers that are embedded or hidden inside something else. Examples: Xerox machine controller, Automotive Anti-lock braking system, Airliner autopilot, MP3 Player, DVD player, TiVo Box, CelPhone.
Microcomputer: A computer you can buy for $10 - $1000. Almost all of the same software and hardware issues we will study have been around since the 1960’s. The only thing different is the cost of the hardware. All of the following had essentially the exact same software environment to what we are studying in this class:
Era Technology Cost 1960’s Mainframe $1M 1970’s Minicomputer $100k 1980’s PC’s $5k 1990’s Cellphone $ 2000’s Microcontroller $
Systems: From “The Random House Dictionary”
A C program is typically written in multiple files. Simpler editing Helps modularity and multiple authors. File: main.c main () { ... code ... }
fcn1 () { ... code ... }
File: functions.c
fnc2 () { ... code ... }
fcn3 () { ... code ... }
... etc ...
Execution starts with first line of main(). All functions (except main()) require a function prototype in any file in which they will be called or defined. All functions are visible from any file (but prototype must be supplied in the file).
... windows - specific code ...
... linux - specific code ...
(draw your own graphic)
2.3 Building a C program
For each “.c” file:
Then: “Link” all “.o” files, and library files, to create “executable” binary file.
2.4 Variable Scope
2.5 Function Scope
int szint = sizeof(myInt); int szflt = sizeof(myFloat);
// Assume intPtr has the value 0x // and floatPtr == 0x // and szint = 4, szflt = 8 (bytes)
printf("intPtr = %d\n", (int)intPtr); printf("intPtr+1 = %d\n", (int)intPtr+1); printf("fltPtr = %d\n", (int)fltPtr); printf("fltPtr++ = %d\n", (int)fltPtr++ );
Consider
int *pa; // (assume (int)pa == 0x3000) *pa = 0x000B; *(pa++) = 0x0010; *(pa+1) = 0x00C0;
What does memory look like? What are the values of
*pa + 1 == ?? (int)pa == ??
Name Addr 3000
(Lewis, Section 3.6) Consider the original IBM-PC 80 col x 40 rows, display buffer
This is the graphics hardware that generates the clunky screen that you use to configure your BIOS. addr col 1 col 2 col 3 row 1 B8000 ch cl ch cl ... row 2 B80A0 ch cl ... ... ch ... ...
where ch is a char display character, and cl is a char which encodes the color of that character position.
#define DISP_BUFFER 0xB int row, col; char disp_char; char *p; // Let’s display "A" in row 4, col 20 disp_char = ’A’; row = 4; // for example ... col = 20; // " "
p = (char *) (DISP_BUFFER + 2 (80row + col)) *p = disp_char;
Complete this example: write code to set the byte which controls the color of the character A we just displayed. Assume the color byte should be assigned the value COLOR BYTE. The color byte has 2 4-bit fields which set the background color (16 possible colors) and the character color (16 possible colors).
An array is an ordered set of memory elements. For example, int j[3] sets up memory for three integers known as j[0], j[1], j[2]. Graphically, if
int a[5]=0; // array of 5 ints // each int is 2 bytes
Element name a[0] a[1] a[2] a[3] a[4] Address 3000 3002 3004 3006 3008
When you declare an array such as
int a[5];
Enough storage is allocated for 5 integers (typically 5×32 bits or 40 bytes). But you should not count on any initial value. To initialize the array use one of two methods:
Modify the scheme in Lewis, sec 3.6, so that we can address display characters and display colors each in a separate row/column array.
3.2 Generic (void) Pointers
Sometimes we want a pointer which is not locked to a specific type. It can potentially point to anything.
void *name ; // declare a generic pointer called name
Examples
void* myGenericPtr; int t, *ip, myvalue = 3; myGenericPtr = &myvalue; // OK t = *myGenericPtr; // NO!!
//*****************
ip = nyGenericPtr; t = *ip; // OK!!
If a pointer has the value NULL, it points to nothing. NULL is a predefined constant in <stddef.h> or use #define NULL 0 NULL is illegal to dereference. NULL can be tested for:
int i,*ip = NULL;
[...]
if(ip == NULL) { // I haven’t defined ip yet } else { // OK, now I can use it! i = *ip;}
C can have pointers to functions.
type (* functionpointer)(arg list)
Examples
int(*IntFuncPtr)(); \ IntFuncPtr is a pointer to a function with \ no arguments which returns an int
double(*doubleFuncPtr)(int arg1, char arg2) \ doubleFuncPtr is a pointer to a function with \ an int and a char arg which returns a double.
Assignment to function pointers:
int (* IFP)(int x) = NULL; // empty function pointer int realfunction( int x); // an actual function
IFP = &realfunction; IFP = realfunction; // can skip &
Dereferencing function pointers:
(*IFP)(5) // call function realfunction with arg 5
IFP(5) // can also use function pointer just like // original function name
3.3 Pointer Arithmetic
A powerful feature of pointers is the ability to compute with them like integers. However only some operations are allowed with pointers. Allowed:
Not Allowed:
We will often need to specify the content of memory very precisely.
Entering binary numbers can wear out the 1 and 0 keys on your computer! HEX is a good shorthand for binary since each HEX character maps to a specific bit pattern.
bits HEX Octal 0000 0 0 0001 1 1 0010 2 2 ... ... ... 0111 7 7 1000 8 10 1001 9 11 1010 A 12 1011 B 13 ... ... ... 1111 F 17
Hex Place value: To convert 0xD2FB to decimal:
D 2 F B 212 28 24 20 4096 256 16 1
Octal can also be used and is easier to memorize because there are only 8 symbols (0-7). (^1) B. Kernigan and D. Ritchie, “The C Programming Language,,” 2nd Edition, Prentice Hall, 1988. Daniel W. Lewis, Fundamentals of Embedded Software, Where C and Assembly Meet, Prentice Hall, 2002.
However, to fill a byte of memory requires 2.5 octal characters since each character only encodes 3 bits. For example, HEX 9A = Binary 1011010 = Octal 132
It is very important to use symbolic constants (#define’s ) for all your numeric constants. Here are the main reasons:
Example and Exercise
// Constants #define EXAMPLE_CONST_D 1234 ; /* DECIMAL value / #define EXAMPLE_CONST_H 0x4D2 ; / HEX value / #define EXAMPLE_CONST_O 02322 ; / OCTAL value */
int x = EXAMPLE_CONST_D; int y = EXAMPLE_CONST_H; int z = EXAMPLE_CONST_O;
// test yourself here: (which of these print?) if (x == y) printf ("Hello there ... \n"); else {};
if (y == 1234) printf ("What’s up doc?? \n"); else {};
if (z == 2322) printf ("The Rain in Spain ... \n"); else {};
if (z = 2322) printf ("Falls mainly on the plains.\n"); else {};
Example 2
Suppose you are going to control a CD-ROM drive and you want to open and close the drive door. The bit to open and close the drawer is the 4th bit in a register located at address 0x2DA. Let’s say that to set that bit we use the function
IO_Register_Set([addr],[value])
where [addr] is the bus address of the I/O register you want to manipulate and [value] is the bit pattern you want to put there. It is “technically” correct to use the following code:
/* Use of bitwise logical operators */
#define Bit_Zero 0x #define Bit_One 0x #define Bit_Two 0x #define Bit_Three 0x #define Bit_Four 0x #define Bit_Five 0x #define Bit_Six 0x
// etc etc etc ..
int x = 0x0B; // x = [... 0 0 0 0 1 0 1 1]
int y = 011; // y = [... 0 0 0 0 1 0 0 1]
int z = x << 2; // z = [... 0 0 1 0 1 1 0 0]
int z1 = y & Bit_Three; // z1 = [... 0 0 0 0 1 0 0 0]
int z2 = z | Bit_Four; // z2 = [... 0 0 1 1 1 1 0 0]
4.3 In-class Exercise:
Convert 0x1A to decimal: __________
Convert 0xA2 to decimal: __________
Convert 020 to Hex: _____________________
Convert 0x20 to Octal: _____________________
/* Give the binary value of the least significant 8 bits of the following values: */
int aa = 0xC5; // aa = [ ]
int ab = 017 + 1; // ab = [ ]
int a = x | y; // a = [ ]
int b = Bit_Two | Bit_Five | Bit_Seven; // b = [ ]
int c = ~((z | Bit_Zero) << 1); // c = [ ]
int d = !(z1 | Bit_Two); // d = [ ]