Upload
giles-carroll
View
214
Download
0
Embed Size (px)
Citation preview
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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