Transcript of C Programming for Embedded Systems. fig_06_00 Computer Layers Low-level hardware to high-level...
C Programming for
Embedded Systems
fig_06_00
Computer LayersLow-level hardware to high-level software(4GL: “domain-specific”, report-driven, e.g.)
fig_06_01
From source code to executable program:Compilation:
Preprocessing step:
fig_06_03
Compiling or assembling:
fig_06_04
The entire process:
fig_06_05
Example files in the process:
fig_06_06
Important features of embedded code:
Performance
Robustness (response to failures)
Ease of change
Style—simple, understandable
example: flag = x != 0 && ! y/x < 0 how is this evaluated?
in embedded systems: use parentheses!!!!!!!
C integral types:
char
short
int
long
(signed or unsigned)
fig_06_08
Unsigned integer—range and format
fig_06_10
Signed integer (1’s complement)—range & form
fig_06_12
Numbers in memory—sign in most sig “nibble”
fig_06_14
Character data
fig_06_15
Floating point data
fig_06_16
Exponent: “excess notation”
fig_06_17
Example program:
fig_06_18
Variable designations and visibility: scope
fig_06_20
Storage classes
fig_06_21
Example:
fig_06_22
Separate compilations:
fig_06_23
Makefiles: example
Bitwise Operators
Pointers
Functions
Structs
Interrupts
(in C)
table_07_00
Bitwise operators: useful for dealing with signals of different widths;NOTE: these are LOGICAL operators and variables are declared UNSIGNED—why?(example: homework 1, problem 1)
Example of c program—”portShadow” mirrors what is on port;Note use of parentheses to guarantee order of bitlevel operations (even if we are using default order)
fig_07_02
Using shift operators (remember these are logical):
fig_07_03
Redoing the previous problem with shifts:
fig_07_04
Getting data from the port:
fig_07_05
Using bitlevel operations for arithmetic;Are there any problems with this approach?
C: on signed data, left shift undefined if overflow occurs, right shift is implementation-dependent;Java: all integers are signed
fig_07_06
Can use shifts for slightly more complex multiplies and divides;More complex operations (e.g., with 3 1’s in multiplier or divider) are probably not efficient
fig_07_07
Pointers: example data
fig_07_09
Example instruction:
fig_07_10
Example 2 of Instruction execution
fig_07_11
Example: what is output?
fig_07_12a
Pointer arithmetic—not for beginners!
fig_07_12b
Pointer arithmetic: additional examples
fig_07_13
Constant pointers:
fig_07_14
Using constants and constant pointers:
fig_07_14
Note: pointers can be “generic” or NULL:
Generic:Type void: pointer can point to a variable of any type
example: 7.3, p. 265
NULL:Pointer needs to be assigned a valid address before dereferencing, otherwise hard-to-find bugs can occur
Address 0 is not acceptable
Solution: use null pointer address, (void*) 0
fig_07_15
C functions:
fig_07_16
Example:
fig_07_17
Function call: note order of parameters on stack
fig_07_18
Using stack to return result:
Function body in memory:
fig_07_20
Pass by value (default in c):
fig_07_21
Pass by reference:
fig_07_22
Information hiding: static qualifier prevents visibility outside this file (even to linker):
fig_07_23
Function documentation: template for header
fig_07_24
We can also define pointers to functions:
Dereferencing methods:
fig_07_26
Example:
fig_07_27
Example 2:
fig_07_28
Pointing to add:
fig_07_29
Pointing to subtract: pointer does not know functionality, only address
fig_07_31
User-defined data structure: struct
fig_07_30
User-defined data structure: struct
Example:
fig_07_34
Can also define a type and use it repeatedly:
fig_07_35
Syntax for using struct:
fig_07_36
Example: define a rectangle
fig_07_37
One struct using another:
fig_07_38
C code for this example:
fig_07_39
Defining the rectangle type:
fig_07_40
Using point and rectangle definitions:
fig_07_41
Rectangle functions:
fig_07_42
Example program:
fig_07_43
Example: passing a struct to a function:
fig_07_44
Interrupt service routines: ISR—needs to be SHORT and SIMPLE
fig_07_45
How an interrupt occurs:
Interrupt may be disabled under certain conditions
fig_07_46
Enable / disable control mechanisms:
Global
Maskingmethod 1: use prioritiesmethod 2: use mask register
(bitwise masks)
Note: interrupts are transient, if we choose to ignore one we may not be able to service it later