3 - Polling and Timing CMPE2003

Preview:

DESCRIPTION

.

Citation preview

E M B E D D E D S Y S T E M S D E S I G NC. A. Maynard (C) 2015!

Lecturer: Wei Wong1

REACTIVE SYSTEMS

Embedded Systems react to changes to their inputs to create new output values.!

New input values are obtained in two ways:!

Polling!

Interrupts

2

POLLING FOR INPUTC.A.Maynard ©2013-2014

3

POLLING FOR INPUT

Polling is one of the basic techniques for getting data into a system.!

The simplest process is a loop of execution where each possible source of data is checked and if there is new data the necessary code is executed to deal with the information.!

In an embedded system the loop continues to execute as long as the program is running. An infinite loop.

4

A PROGRAM FLOWCHART

5

THE POLLING PROCESS

If a new value is available from the input source then execute the required process.!

Go to the next input and repeat as necessary.!

After the last input perform any general processing required then go back and start again.!

The restart of the polling process MAY be subject to a time constraint which has not been shown in the flowchart.

6

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.

8

A SWITCH INPUT

Generally two functions required: // Initialise the interface void switchesInit(void) !// Get the value // Return true (and the value) if a new value has been found and false if there is no new value enum bool switchesGet(uc_8 *value)

enum bool provides an explicit boolean variable not provided in the definition of C. What does standard C use for this requirement?

9

REVISION OF C

uc_8 *valueis a pointer to an 8 bit unsigned character variable.

A pointer variable holds the address of a variable of the specified type.

10

A LED DISPLAY OUTPUT

Generally two functions required: // Initialise the interface void LEDsInit(void) !

// Output a new value to the interface enum bool LEDsPut(uc_8 value) // The more general solution returns a success or failure flag to the main program.

11

A SEVEN SEGMENT DISPLAY OUTPUT

Generally two functions required: // Initialise the interface void sevenSegInit(void) !// Output a new value to the interface enum bool sevenSegPut(uc_8 segID, uc_8 value) // The more general solution returns a success or failure flag to the main program.

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

Generally a global to specific naming sequence is considered the best.!

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:

Timer_0_Data, Timer_0_Overflow, and Timer_0_Capture. !

This convention quickly narrows variables to particular segments of the program.

15

CONVENTION CONTINUED:

Never assume that a verb must be first, as often seen when naming functions.

Open_Serial_Port and Close_Serial_Port These do a much poorer job of grouping variable names than the better alternative of Serial_Port_Open and Serial_Port_Close

16

WHERE TO FIND IT:

A Firmware Development Standard

Version 1.4, Updated May 2007

Ganssle Group publication... Free on the web

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

19

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.

INPUT 1 OPERATIONS!

// Get the switch input and display!

if( switchesGet(&value)) { temp = LEDsPut(value) }

Revision:!

& is the “address of” operator so the function is provided with the location of the returned variable (A pointer).

20

INPUT 2 OPERATIONS

!

// Get the keypad input and display!

if( keypadGet(&value)) { temp = sevenSegPut(segID, value) }

Background information:!

There are two seven segment displays on the clic3 board and the “segID” variable identifies which one to use.

21

KEYPAD INPUT

In the previous slide we have assumed that we have already defined:!

void keypadInit(void)!

enum bool keypadGet(uc_8 &value)

22

THE MAIN PROGRAM

void main (void) { uc_8 value; uc_8 segID = 0; enum bool temp;!

// System initialisation goes here Initialise();!

// Peripheral initialisation switchesInit(); LEDsInit(); keypadInit(); sevenSegInit(); // main loop goes here }

23

THE MAIN LOOP

// main loop while (true) { // Get the switch input and display if( switchesGet(&value)) { temp = LEDsPut(value); } // Get the keypad input and display if( keypadGet(&value)) { temp = sevenSegPut(segID,value); segID++; if (segID > 1) { segID = 0;} } // Anything else to be done }

24

WHAT HAVE WE DONE?

We have written the main polling program without any consideration of the details of each of the peripherals we are using. !

We only needed to define interface functions.!

“Separation of Concerns” has been applied.!

For some interfaces the functions may seem too complex for others they can hide a lot of complexity.

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 user’s expectation.

29

THE FIRST TIME

The first time the switchesGet function is executed it needs to retrieve a value and return it.!

The function needs to be able to recognise that this is the first execution.!

Normal variables in a function are created and destroyed each time the function is called but “static” variables can hold information between invocations.

30

THE FIRST TIME

Create and initialise a static variable.!

static enum bool first = true;!

In the execution start by testing the value of “first”:!

if(first) { first execution code and set............ first = false; }!

else { every other execution goes here }

31

REMEMBER THE VALUE

We need a static variable to remember the Switches value.!

static uc_8 old_Switches;!

The first time we read the switches, we save in old_Switches and return the value (and true).

32

REMEMBER THE VALUE

All other invocations read the Switches, compare with old_Switches........if they are the same simply return false.........(There is no new value to return).!

if they are different a switch has been operated so........save the new reading in old_Switches (for the next invocation), return the value and true.

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

Stubs are functional skeletons used to allow compilation of a system and execution but providing minimal if any actual functionality.!

In this case there is no keypad code only the return of an arbitrary value (3 in this case) as the new value.

38

SEVEN SEGMENT DISPLAY

// Initialise the Seven Segment Display interface!void sevenSegInit(void) { }

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

To turn on a segment the pin must be pulled down to!ground. A common anode configuration.

0 1 2 3 4 5 6 7 -> Bits

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

Modify the sevenSegPut function to limit output to the valid range of values and to return false if an attempt is made to display a value beyond the limit defined in the .h file.

44

A FINITE STATE MACHINE

!

http://www.eetimes.com/design/embedded/4008260/Using-finite-state-machines-to-design-software

45

SAMPLE CODEint 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 FUNCTIONSC.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

THE PROGRAM “CORE”

main (void) {!

ui_16 i, j; //unsigned int in a 16 bit variable!

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 showstoggling bit 7 of port P (asused last year)

52

ADDING THE TEST FUNCTIONS

for(i=0;i<10;i++) {!

TimeTestStart(&TT); // Start time measurement!

P4OUT ^= BIT3; // Exclusive OR bit 3 of PORT P4!

for(j=0;j<10;j++) {} // Something to time test!

P4OUT ^= BIT3; // Exclusive OR bit 3 of PORT P4!

TimeTestEnd(&TT); // End time measurement!

}53

SUPPORT CODE CONTD

static TimeTest TT = {0, 0, 65535, 0, 0, 0, 0};!

This is the initialisation of the structure that holds the timing data.!

In main we then can have!

ui_16 i, j; // from MISRA C

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 ; !/* Structure must be initialised as follows * { 0, 0, 65535, 0, 0, 0, 0}

56

THE STRUCTURE VALUES

The structure values returned: * Last starting TCNT. Not of value after execution stopped * Provides a count of the number of code executions .count * The minimum time execution in cycles and count: .min and .mincount * The maximum time execution in cycles and count: .max and .maxcount * The total time of all measurements: .totaltime * So average time is this .totaltime/.count

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

BEFORE MOVING ON!

You should understand the code to be tested.!

You need not understand the details of the timing functions at this stage but we will investigate the general use of structures (struct) and unions in C later.

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

GLOBAL AND LOCAL VARIABLES

Global variables are declared outside of all functions, accessible by all, and exist throughout the execution of the program.!

Local variables are declared inside functions and usually are stored on the stack (or sometimes in registers)

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

Review the available functionality.!

In particular:!

bitwise operations!

unary operations

64

FUNCTIONS

An independent body of code written to perform a specific task.!

main is the function called first BUT any initial conditions need to be established (not explicitly seen in many situations including embedded code)

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

Compiler directives: #include, #define, #undef. #line, #error and #pragma!

Conditional directives: #if, #ifdef, #ifndef, #else, #elif, and #endif

67

GUIDELINES

Guidelines are meant to be followed most of the time, !

and they are meant to be broken when you get better results by breaking them!!

Note: The right to break the rules is not given freely!!! The right is accompanied by the need for increased documentation and justification.

68

SPECIFIC GUIDELINES

“Guidelines for the use of the C Language in Vehicle Based Software”!

MISRA C!

There are 2 copies in the closed reserve in the library.!

The tests are built into the IAR embedded workbench software used in the laboratory.

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)!

IAR’s own library files do not necessarily follow the MISRA C rules.

70

THE MISRA C GUIDELINES 18TH RULE:

Numeric constants should be suffixed to indicate type,where an appropriate suffix is available.

Discuss the need for this rule and indicate why it is considered necessary. In ANSI C the suffixes available are f or F, l or L, u or U.

Example:

#define fred (273u)

71

MISRA C RULE 46 STATES:

The value of an expression shall be the same under any order of evaluation that the ANSI C standard permits.

Example:

c = 5;f = (c++)*c;

What is the resulting value for f?

72

Recommended