Professional Documents
Culture Documents
REACTIVE SYSTEMS
A PROGRAM
FLOWCHART
A GENERIC INPUT
Initialise a port/subsystem so that it is ready to
return input values.!
Check if a new value is available and process that
value as required.!
What variable type should be used for an input?!
Unless there are specific characteristics associated
with the data an unsigned variable of the required
number of bits is the best choice.
7
SEPARATION OF
CONCERNS
A Software Engineering philosophy.!
Separate initialisation from use!
Separate information about the existence of a new value from
the value itself.!
Historically in C this was not done and the major C software
libraries reflect that original philosophy.!
Separate the user from details of the interface requirements.!
For the next lab you need to understand the TimeTest.h
file so that you can use the functions but you do not (in
principle) need to understand the details of the functional
implementations provided.
A SWITCH INPUT
Generally two functions required:
// Initialise the interface
void switchesInit(void)
!
REVISION OF C
uc_8 *value
is a pointer to an 8 bit unsigned character variable.
A pointer variable holds the address of a variable of
the specified type.
10
A SEVEN SEGMENT
DISPLAY OUTPUT
Generally two functions required:
// Initialise the interface
void sevenSegInit(void)
!
12
MORE PHILOSOPHY
Use an Object-Operation sequence
in your naming convention.!
This has advantages in
development environments which
actively provide the available
functions as you type.
13
VARIABLE NAMING
Example:!
! Variable and function names are defined with the first
words being descriptive of broad ideas, and later words
narrowing down to specifics. For instance:
Universe_Galaxy_System_Planet.
14
THE CONVENTION:
15
CONVENTION
CONTINUED:
16
17
PRAGMATICS
As mentioned before, there is no boolean variable built into C
so we introduce an enumerated variable to support this
requirement. !
See the clic3.h header file.!
/* Ensure that flags(Boolean variables) can only be true or
false */!
enum bool {false,true};!
This is compatible with the classic C usage that zero is false
and non zero true.
18
A PROGRAM
FLOWCHART REVISITED
The diamond represents !
a decision about whether !
there is a new input or not.!
Our drivers return the !
information for that test.!
Often we do not need to!
save that information !
simply act on it.
19
INPUT 1 OPERATIONS
!
Revision:!
& is the address of operator so the
function is provided with the location of
the returned variable (A pointer).
20
INPUT 2 OPERATIONS
!
Background information:!
There are two seven segment displays on the
clic3 board and the segID variable
identifies which one to use.
21
KEYPAD INPUT
22
main (void) {
value;
segID = 0;
bool temp;!
// Peripheral initialisation
switchesInit();
LEDsInit();
keypadInit();
sevenSegInit();
23
24
25
SEPARATION OF
CONCERNS
The writer of the main code makes the basic
assumption that when an interface is asked for a new
value only genuinely changed values will be returned
and flagged as true.!
In the previous code only displays are updated BUT in
general a significant amount of computation may
depend on only receiving new (updated) values.!
The writer of the library code should take this
expectation into consideration when writing the code.
26
SWITCHES
void switchesInit(void) { }!
// The switchesGet function returns true if a new
value has been found.!
// Simplest version assumes there is always a new
value.!!
enum bool switchesGet(uc_8 &value) {!
!*value = Switches;!
!return true;!
}
27
SWITCHES LEGACY
HARDWARE SUPPORT
enum bool switchesGet(uc_8 *value) {!
BusAddress = SwitchesAddr;!
BusRead();!
*value = BusData;!
return true;!
}
28
IS THE INTERFACE
VALID?
Every time that switchesGet is executed it will return
a value claimed to be new.!
In reality this is very unlikely.!
We need to change the internal functionality of
switchesGet to match the users expectation.
29
31
32
33
LEDS
void LEDsInit(void) { }!
// LEDsPut returns true if a new value can be
stored in the interface!
// As there is no way for the system to know just
return true.!
enum bool LEDsPut(uc_8 value) {!
!Leds = value;!
!return true;!
}
34
LEDS LEGACY
HARDWARE SUPPORT
enum bool LEDsPut(uc_8 value) {!
BusAddress = LedsAddr;!
BusData = value;!
BusWrite();!
return true;!
}
35
LEDS FUNCTIONALITY
As there is no hardware readback capability for the
LEDs interface a default true return is valid.!
Should a new hardware interface with readback be
implemented for the LEDs in the future the interface
code remains valid but new internal code for the
function will need to be created.!
This is a good approach to interface function design.
36
KEYPAD STUB
// Get a new value from the keypad if there is
one otherwise return false!
// Returns true if a new value has been found!
enum bool keypadGet(uc_8 &value) {!
!*value = 3; // Random choice for a stub return!
!return true;!
}
37
STUBS
38
SEVEN SEGMENT
DISPLAY
39
7 SEGMENT CONTD.
// Send a new value to the selected display and
return true otherwise return false if this could not
be achieved. DispID chooses the display (o or 1).
value is the selector for what is to be displayed.!
enum bool sevenSegPut(uc_8 DispID,uc_8 value) {!
!if(DispID) { Seg1 = LookupSeg[value]; }!
!else { Seg2 = LookupSeg[value]; }!
!return true; !
}
40
7 SEGMENT DISPLAY
0 1 2 3 4 5 6 7 -> Bits
To turn on a segment the pin must be pulled down to!
ground. A common anode configuration.
To show a 0 all segments must be at zero except g!
%0100 0000 or 0x40
41
7 SEGMENT CONTD.
const uc_8 LookupSeg[MaxSegs]=
{0x040, 0x079, 0x024, 0x030, 0x019, 0x012, 0x002, 0x078,
0x000, 0x018, 0x008, 0x003, 0x046, 0x021, 0x006, 0x00E,!
0x027, 0x009, 0x07B, 0x060, 0x047, 0x023, 0x00C, 0x02F,
0x041, 0x011, 0x03F, 0x07F};!
/* Beyond index 0x0F (for the hex character "F")!
the values represent the characters:
c , H , i , J , L , o , P , r , U , Y , - , blank!
With hexadecimal indices
10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 1A, 1B
42
*/
7 SEGMENT CONTD.
Is the return value of true appropriate for the code?!
There is no readback of output so for a valid display
value then true is appropriate.!
What if the value is beyond the maximum value
allowed?!
An appropriate thing to do is not to update the
display and to return false.
43
EXERCISE
44
A FINITE STATE
MACHINE
http://www.eetimes.com/design/embedded/4008260/Using-finite-state-machines-to-design-software
45
SAMPLE CODE
int main(void)!
{ enum states { before, inside, after} state;!
int c;!
state = before;!
for(;;) {!
switch(state) {!
case before:!
if(c == '\n') { putchar('\n');!
} else if(c != ' ') {!
putchar(c);!
state = inside;!
}!
break;!
case inside:!
switch(c) {!
case ' ': state = after; break;!
case '\n':!
putchar('\n');!
state = before;!
break;!
default:
putchar(c);!
}!
break;!
case after:!
if(c == '\n') {!
putchar('\n');!
state = before;!
}!
}!
}!
}
46
TIMING FUNCTIONS
C.A.Maynard 2012-2014
47
TIMING IN EMBEDDED
SYSTEMS
Timing of execution is one of the critical aspects of
embedded system design when compared to
desktop programming.!
The laboratory will introduce timing techniques in a
simple program environment.!
An empty for loop will be timed.!
You are provided with comprehensive notes to
execute the measurements in the lab sheet.
48
TIMING EXECUTION
It is often necessary to find out how long things take to
execute in an embedded system. How do we find this
out?!
There are three common ways with different attributes:
1.To determine execution time of a function run it in the
simulator and note the cycle counts before and after.
With this information and the system clock rate the
execution time can be determined. Often this execution
time is not fixed so execution with worst case paths
through the code and associated data needs to be
done.
49
TIMING EXECUTION
2.Activate an output pin at the beginning of execution of the
code and clear it at the end. Using repeated execution the
time can then be measured on a CRO and the jitter in this
time represents the variation in execution if variable data is
being provided to the code. There will be some tolerance in
the value due to the time taken to execute the output pin
changing code.!
3.Using predefined functions to capture the time of execution
and compensate for their own execution times (which should
be as short as possible). These can collect average and
extreme execution times (minimum and maximum) into a
structure for subsequent evaluation.
50
for(i=0;i<10;i++) {!
for(j=0;j<10;j++) {} // Something to time test!
}!
}
51
THE TEST
FUNCTIONS
TimeTestStart(&TT);!
TimeTestEnd(&TT);
Port 4 bit 3 toggle!
(NOTE the flowchart shows
toggling bit 7 of port P (as
used last year)
52
54
STRUCTURES IN C
A struct in C is a structured type that aggregates a fixed
set of labelled objects, possibly of different types, into a
single object.
A struct declaration consists of a list of fields,
each of which can have any type. The total storage
required for a struct object is the sum of the
storage requirements of all the fields, plus any
internal padding.!
55
THE STRUCTURE
typedef struct {
ui_16 oldtcnt;
ui_16 count;
ui_16 min;
ui_16 mincount;
ui_16 max;
ui_16 maxcount;
ui_32 totaltime;
} TimeTest ;
!
57
ACCESSING THE
MEMBERS OF THE STRUCT
There are two ways to access the members
(component parts of the structure)!
/* Define a variable t of type TimeTest */!
TimeTest t;!
t.mincount = 23; //Place the value 23 in the timetest
structure under the mincount label.!
t->mincount = 23; // An alternative way of writing
it.
58
59
C - W H AT D O W E N E E D T O K N O W ?
60
C - A SYSTEMS DESIGN
LANGUAGE
The designers of C wanted to give themselves
sufficient flexibility to use it for almost anything from
system drivers through to user applications.!
They were very successful and that is why C is still in
use.!
What particular aspects are important for embedded
systems design?..........Revision
61
62
STORAGE KEYWORDS
extern: declared and defined in another code file.!
auto: the default type generally on the stack!
static: similar to auto but stored at specified locations in RAM (not on the stack).
Very good for functions needing to remember aspects of their execution.!
register: asks the compiler to use a processor register if possible for overall
efficiency of execution. !
const: a variable that does not change so usually in ROM!
volatile: locations which can be changed outside of the main program execution
such as input ports or through interrupt routines
63
OPERATORS
64
FUNCTIONS
65
HEADER FILES
C has preconstructed libraries which are accessed by
#include <header.h>!
You can add your own header files by
#include myheader.h!
By default your own files need to be in the same
folder as your main.c file. There are ways of changing
this but generally run with the default.
66
CONDITIONAL
COMPILATION DIRECTIVES
67
GUIDELINES
68
SPECIFIC GUIDELINES
MISRA C!
69
MISRA C
The MISRA C rules and guidelines should be followed as much
as possible.!
In this unit an attempt will be made to consistently follow
them BUT you will find places where there are deviations and
sometimes where comments are made to say this breaks the
guidelines but that should be expected.!
In particular the MISRA C rules will be followed except 109
and 110. (Investigate these rules)!
IARs own library files do not necessarily follow the MISRA
C rules.
70
Example:
71
MISRA C RULE 46
STATES:
Example:
c = 5;
f = (c++)*c;
72