20
The right and wrong ways for constructing tasks for the Labs and Assignment

The right and wrong ways for constructing tasks for the Labs and Assignment

Embed Size (px)

Citation preview

Page 1: The right and wrong ways for constructing tasks for the Labs and Assignment

The right and wrong ways for constructing tasks for the Labs

and Assignment

Page 2: The right and wrong ways for constructing tasks for the Labs and Assignment

Assignment 1 – What I suggested

#define ULL unsigned long long int // Place in include / header file

void main(void) {

ULL currentCycleCount = ReadCycleCounter( ); ULL nextLED1ExecutionTime = currentCycleCount + ONE_SECOND ULL nextLED2ExecutionTime = currentCycleCount + TWO_SECONDS

while (1) { currentCycleCount = ReadCycleCounter( );

if (nextLED1ExecutionTime < currentCycleCount) { nextLED1ExecutionTime = nextLED1ExecutionTime + ONE_SECOND LED1Task( );

} if (nextLED2ExecutionTime < currentCycleCount) {

nextLED2ExecutionTime = nextLED2ExecutionTime + TWO_SECONDS LED2Task( ); }

}

2 /18

Page 3: The right and wrong ways for constructing tasks for the Labs and Assignment

Assignment 1 – What many did! Why is this bad programming?

ULL currentCycleCount = ReadCycleCounter( ); ULL nextLED1ExecutionTime = currentCycleCount + ONE_SECOND ULL nextLED2ExecutionTime = currentCycleCount + TWO_SECONDS

int led1 = 0; int led2 = 0;

while (1) { currentCycleCount = ReadCycleCounter( );

if (nextLED1ExecutionTime < currentCycleCount) { nextLED1ExecutionTime = nextLED1ExecutionTime + ONE_SECOND if (led1 == 0) {

My_LEDWrite(1, 1); // If off, turn on led1 = 1; } else { My_LedWrite(1, 0); // If on, turn off led1 = 0;

}

}

3 /18

Page 4: The right and wrong ways for constructing tasks for the Labs and Assignment

Bad programming because

Imagine what this code would look like with 15 tasks

Too complicated – all the detail is in one piece of code

Somebody reading / maintaining main( ) does not need all this detail. That person could be you in your internship position

SOLUTIONProfound Procrastination ProgrammingProper words – Abstraction – Hide details

4 /18

Page 5: The right and wrong ways for constructing tasks for the Labs and Assignment

Define CODE ERROR and CODE DEFECTEverybody is likely to make mistakes

Keep track of mistakes you makeIdentify the two most commonDo code review looking for those particular errors

Every project is made up of phasesIf you make a mistake and find it BEFORE moving

onto the next phase – CODE ERROR and EASY to find as the mistake is in last twenty lines or so

If you make a mistake and DON’T find it BEFORE moving onto the next phase – CODE DEFECT and HARD to find and fix

5 /18

Page 6: The right and wrong ways for constructing tasks for the Labs and Assignment

Assignment 1 – Why does this code contain a CODE DEFECT

#define ULL unsigned long long int // Place in include / header file

void main(void) {

ULL currentCycleCount = ReadCycleCounter( ); ULL nextLED1ExecutionTime = currentCycleCount + ONE_SECOND ULL nextLED2ExecutionTime = currentCycleCount + TWO_SECONDS

while (1) { currentCycleCount = ReadCycleCounter( );

if (nextLED1ExecutionTime < currentCycleCount) { nextLED1ExecutionTime = nextLED1ExecutionTime + ONE_SECOND LED1Task( );

} if (nextLED2ExecutionTime < currentCycleCount) {

nextLED2ExecutionTime = currentCycleCount + ONE_SECOND LED2Task( ); }

}

6 /18

Page 7: The right and wrong ways for constructing tasks for the Labs and Assignment

Define LIFE ERROR and LIFE DEFECTEverybody is likely to make mistakes

Keep track of mistakes you makeIdentify the two most commonDo life review looking for those particular errors

Every project is made up of phasesIf you make a mistake and find it BEFORE moving

onto the next phase – LIFE ERROR and EASY to find as the mistake is in last twenty minutes or so

If you make a mistake and DON’T find it BEFORE moving onto the next phase – LIFE DEFECT and HARD to fix

7 /18

Page 8: The right and wrong ways for constructing tasks for the Labs and Assignment

Define DESIGN ERROR and DESIGN DEFECTEverybody is likely to make mistakes

Keep track of mistakes you makeIdentify the two most commonDo design review looking for those particular errors

Every project is made up of phasesIf you make a mistake and find it BEFORE moving

onto the next phase – DESIGN ERROR and EASY to find as the mistake is in last twenty lines or so

If you make a mistake and DON’T find it BEFORE moving onto the next phase – DESIGN DEFECT and HARD to find and fix

8 /18

Page 9: The right and wrong ways for constructing tasks for the Labs and Assignment

Design and implementation of codevoid LED3_Task( ) // DESIGN

Uses Read LED( ) and WriteLED( ) from Lab. 1

if LED3 is on turn it off

if LED3 is off turn it on

}

WHY DOES THIS IMPLEMENTATION NOT WORK – DEFECT QUICKLY FOUND

void LED3_Task( ) {

bool LED3_on = true;

currentLED = ReadLED_ASM( );

if (LED3_on == true) // turn off LED 3

WriteLED_ASM(currentLED & 0x4); // 0x4 is magic number for LED 3 %0100

else

WriteLED_ASM(currentLED | 0x4); // 0x4 is magic number for LED 3 %0100

LED3_on = ! LED3_on

}04/21/23 TDD-Core Timer Library,

Copyright M. Smith, ECE, University of Calgary, Canada

9 / 28

Page 10: The right and wrong ways for constructing tasks for the Labs and Assignment

Design and implementation of codevoid LED3_Task( ) // DESIGN

Uses Read LED( ) and WriteLED( ) from Lab. 1

if LED3 is on turn it off

if LED3 is off turn it on

}

FIXED

void LED3_Task( ) {

static bool LED3_on = true; // Variable is a private permaneant variable (not on stack)

currentLED = ReadLED_ASM( );

if (LED3_on == true) // turn off LED 3

WriteLED_ASM(currentLED & 0x4); // 0x4 is magic number for LED 3 %0100

else

WriteLED_ASM(currentLED | 0x4); // 0x4 is magic number for LED 3 %0100

LED3_on = ! LED3_on

}04/21/23 TDD-Core Timer Library,

Copyright M. Smith, ECE, University of Calgary, Canada

10 / 28

Page 11: The right and wrong ways for constructing tasks for the Labs and Assignment

Design and implementation of codevoid LED3_Task( ) // DESIGN

Uses Read LED( ) and WriteLED( ) from Lab. 1

if LED3 is on turn it off

if LED3 is off turn it on

}

WHY DOES THIS IMPLEMENTATION MOST OF THE TIME

void LED3_Task( ) {

currentLED = ReadLED_ASM( );

int LED3_on = currentLED & 0x4; // Check if current LED is on

if (LED3_on == 1) // turn off LED 3

WriteLED_ASM(currentLED & 0x4); // 0x4 is magic number for LED 3 %0100

else

WriteLED_ASM(currentLED | 0x4); // 0x4 is magic number for LED 3 %0100

}04/21/23 TDD-Core Timer Library,

Copyright M. Smith, ECE, University of Calgary, Canada

11 / 28

Page 12: The right and wrong ways for constructing tasks for the Labs and Assignment

Why I don’t like this sort of codingvoid LED3_Task( ) {

static bool LED3_on = true; // Variable is a private permanent variable (not on stack)

currentLED = ReadLED_ASM( );

if (LED3_on == true) // turn off LED 3

WriteLED_ASM(currentLED & 0x4); // 0x4 is magic number for LED 3 %0100

else

WriteLED_ASM(currentLED | 0x4); // 0x4 is magic number for LED 3 %0100

LED3_on = ! LED3_on

}

// Main answer – not easy to generalize when the coding gets more complicated

// I want to see ‘STATES’

04/21/23 TDD-Core Timer Library, Copyright M. Smith, ECE, University of

Calgary, Canada

12 / 28

Page 13: The right and wrong ways for constructing tasks for the Labs and Assignment

Rewritten as Statesenum {UNKNOWN, LED_ON, LED_OFF}

void LED3_Task( ) {

static unsigned int LED3_state = LED_OFF; // Assume InitLED( ) turns LED3 offunsigned int LED3_nextState = UNKNOWN; // NOT static – very important

unsigned int currentLED = ReadLEDASM( );

switch (LED3_state ) {

case LED_ON: // Move from state ON to state OFF

WriteLED_ASM(currentLED & 0x4); // 0x4 is magic number for LED 3 %0100

LED3_nextState = LED_OFF;

break;

case LED_OFF: // Move from state ON to state OFF

WriteLED_ASM(currentLED | 0x4); // 0x4 is magic number for LED 3 %0100

LED3_nextState = LED_ON;

break;

default: SendErrorMessage(‘Should not get here\n”); }

LED3_state = LED3_nextState; // Update the state

}

04/21/23 TDD-Core Timer Library, Copyright M. Smith, ECE, University of

Calgary, Canada

13 / 28

Page 14: The right and wrong ways for constructing tasks for the Labs and Assignment

Is this – a state of being ‘too clever’?#define BEGIN_STATE case

#define END_STATE break

#define ERROR_STATE default

void LED3_Task( ) {

static unsigned int LED3_state = LED_OFF; // Assume InitLED( ) turns LED3 offunsigned int LED3_nextState = UNKNOWN; // NOT static – very important

unsigned int currentLED = ReadLEDASM( );

switch (LED3_state ) {

BEGIN_STATE: LED_ON: // Move from state ON to state OFF

WriteLED_ASM(currentLED & 0x4); // 0x4 is magic number for LED 3 %0100

LED3_nextState = LED_OFF;

END_STATE;

BEGIN_STATE: LED_OFF: // Move from state ON to state OFF

WriteLED_ASM(currentLED | 0x4); // 0x4 is magic number for LED 3 %0100

LED3_nextState = LED_ON;

END_STATE;

ERROR_STATE: SendErrorMessage(‘Should not get here\n”); }

LED3_state = LED3_nextState; // Update the state

}04/21/23 TDD-Core Timer Library,

Copyright M. Smith, ECE, University of Calgary, Canada

14 / 28

Page 15: The right and wrong ways for constructing tasks for the Labs and Assignment

Design defect – too much detailHide the detail behind an operating system

#define ULL unsigned long long int // Place in include / header file

void main(void) {

ULL currentCycleCount = ReadCycleCounter( ); ULL nextLED1ExecutionTime = currentCycleCount + ONE_SECOND ULL nextLED2ExecutionTime = currentCycleCount + TWO_SECONDS

while (1) { currentCycleCount = ReadCycleCounter( );

if (nextLED1ExecutionTime < currentCycleCount) { nextLED1ExecutionTime = nextLED1ExecutionTime + ONE_SECOND LED1Task( );

} if (nextLED2ExecutionTime < currentCycleCount) {

nextLED2ExecutionTime = nextLED2ExecutionTime + TWO_SECONDS LED2Task( ); }

}

15 /18

Page 16: The right and wrong ways for constructing tasks for the Labs and Assignment

Using a co-operative scheduler which is responsible for handling the timing#define ONE_SECOND (44100) // Audio interrupts / sec

#define TWO_SECONDS (ONE_SECOND)

#define NO_DELAY (0)

int main(int) {

TTCOS_511Init( );

TTCOS_AddTask(InitFlash_Task, NO_DELAY, RUN_ONCE);

TTCOS_AddTask(LED1Task, NO_DELAY, EVERY_SECOND);

TTCOS_AddTask(LED2Task, NO_DELAY, TWO_SECONDS);

TTCOS_Start( 10 + 5 ); // Allow 10 user (max 15) and 5 system threads

while (1) { // Super loop

TTCOS_GoToSleep( );TTCOS_DispatchTasks( ); // Run tasks if time delay

}

return 0;

}

04/21/23 TDD-Core Timer Library, Copyright M. Smith, ECE, University of

Calgary, Canada

16 / 28

Page 17: The right and wrong ways for constructing tasks for the Labs and Assignment

Rules for task

Two types of tasksPre-emptive –special, very, very time critical

E.g. Store audio sample every 1 / 44000Only pre-emptive task in our labs is ProcessData

Normal – not time criticalE.g. read switch presses – every 1/ 30 is fast enough

NO TASK CAN INCLUDE A WAITAll tasks must have this format

void Task(void)17 /18

Page 18: The right and wrong ways for constructing tasks for the Labs and Assignment

Write tasks that change LEDs with switch presses

void BadSwitchTask( ) {

unsigned int switch1 = ReadSwitchASM(1);while (switch1 == 0) { switch1 = ReadSwitchASM(1);}

WriteLED(1, 1); // Switch is pressed – LED on

while (switch1 == 1) { switch1 = ReadSwitchASM(1);}

WriteLED(1, 0); // Switch is released – LED off

}

// This task is said to BLOCK other tasks from running

18 /18

Page 19: The right and wrong ways for constructing tasks for the Labs and Assignment

Write tasks that change LEDs with switch pressesTTCOS_AddTask(BadSwitchTask, NO_DELAY; EVERY_SECOND / 30)

void BadSwitchTask(void ) {

unsigned int switch1 = ReadSwitchASM(1);while (switch1 == 0) { switch1 = ReadSwitchASM(1);}

WriteLED(1, 1); // Switch is pressed – LED on

while (switch1 == 1) { switch1 = ReadSwitchASM(1);}

WriteLED(1, 0); // Switch is released – LED off

}

// This task is said to BLOCK other tasks from running

19 /18

Page 20: The right and wrong ways for constructing tasks for the Labs and Assignment

Write tasks that change LEDs with switch presses – this code version does not blockenum {PRESSED, NOT_PRESSED}

void SwitchTask_NoWait(void ) {

static unsigned int currentSwitch1 = NOT_PRESSED;

unsigned int switch1 = ReadSwitchASM(1);

// Nothing has changed – so don’t wait

if ((switch1 == 0) && (currentSwitch1 = NOT_PRESSED) ) return;

if ((switch1 ==1) && (currentSwitch1 = PRESSED) ) return;

switch (currentSwitch1) {

case NOT_PRESSED:

WriteLED(1, 1); // Switch is pressed – LED on nextState = PRESSED;

break;

case PRESSED:

WriteLED(1, 0); // Switch is released – LED off nextState = NOT_PRESSED;

break;

}

currentSwitch1 = nextState ;

}

20 /18