Download presentation
Presentation is loading. Please wait.
1
Handling multiple input signals
2
Midterm question Light sensor is in front of the door
Light signs on light sensor If person blocking light – light sensor output is low -- Active low logic Output of light sensor connected to PF5 Program stops “immediately” when owner pushes and releases a button. Button connected to PF6 line Show the count of the people on the LCD using WriteLCD( int count). +5V 10k resistor PF6 GROUND GROUND
3
Design component Key part of the design – Neither action must block the other action Light sensor If high – nobody has ever blocked the sensor, or somebody has blocked the sensor at moved on If low – somebody is still blocking the sensor Must count “1 person enter or leave” as the signal goes from low to high Button If high – owner has not pressed the button or else has pressed the button and released it. If low – is pressing the button – people can still be entering and leaving store. Must stop the program as the signal goes from low to high
4
Approach #1 – Superloop approach based on Lab. 1 ideas
While (loop is not stopped) { Read GPIO Flags 4 possible things possible At least 2 true at the same time Light sensor PF 5 is high Light sensor PF 5 is low Button PF 6 is high Button PF 6 is low We want to take action – on the “edge of the signal”. We don’t want to take action on the “level of the signal” }
5
Code now looks like this
int count = 0; int stop = 0; While (stop != 1) { if PF5 went from low to high count++ if PF6 went from low to high stop = 1; WriteLCD(count); }
6
if PF5 went from low to high count++
How do we answer this question? If PF5 was high before and high now – do nothing If PF5 was low before and low now – do nothing If PF5 was high before and low now – do nothing If PF5 was low before and high now – ACT
7
One solution for the code
int count = 0; int stop = 0; #define PF5Mask 0x20 int oldPF5state = 0; int Midterm(void) { InitAllInterFaces( ); oldPF5State = ReadGPIOASM( ) & PF5Mask ; While (stop != 1) { int newPF5State = ReadGPIOASM( ) & PF5Mask ; If PF5 was high before and high now – do nothing If PF5 was low before and low now – do nothing If PF5 was high before and low now – do nothing If PF5 was low before and high now – ACT if ( (oldPF5State == 0) && (newPF5State == PF5Mask) ) count++; WriteLCD(count); oldPF5State = newPF5State You write the other code for the button } return count;
8
Big problem to solve when translating into assembly code
We are using WriteLCD( ) as part of our code That function can destroy any values we have stored in R0, R1, R2 and R3 Means we can’t do count_R1, stop_R2, oldState_R3 etc. Same problem when we use ReadGPIOFlagsASM( ) from the Lab. 1 code Solution 1 – use memory to store count, stop etc Solution 2 – use “non-volatile” registers which we know will not be destroyed inside WriteLCD( )
9
Design the code
10
Fix the easy parts that are ALWAYS the same
11
Add the calls to the subroutines Note what registers are kept and what are destroyed
12
First part of the code Reading and storing old state
13
Now code the while loop
14
Calculate “newState” Note that PFMask_R1 has been destroyed by subroutine calls
15
Increment counter if needed Watch out for values destroyed by subroutine calls
16
There is a problem – design defect when we go to the next stage
17
Easiest Fix – do oldState = newState before P0 destroyed by subroutine call
18
Improved code That sort of code is the sort of code that would be generated by the “default” mode of the compiler – many saves to memory which the compiler “knows” will work The “optimizing compiler” first of all generates the same code as the “default” mode of the compiler Then the compiler tries to “registerize” the values rather than store them to memory This uses the non-volatile registers which must be saved at the start of this routine and recovered at the end of the routine
19
Optimized code with registerization
20
Optimized while loop
21
Final part of optimized code
22
Optimized code must be written carefully, but is often easier to write
23
Other ideas about subroutines calling subroutines
Handling some “C++” keywords when programming assembly code Programming “subroutines called by subroutines” Programming “extern” variables Programming “volatile” variables Understanding what I did when
24
Subroutine calling subroutine All void functions being used
File “bloodEnglishmanASM.asm” .extern _Fee__Fv; .extern _Fi__Fv; .extern _Fo__Fv; .section program; .global _Fum__Fv; _Fum__Fv: LINK 16; Stores RETS so can be used later CALL _Fee __Fv; Overwrites RETS CALL _Fi __Fv; Overwrites RETS CALL _Fo__Fv; Overwrites RETS UNLINK; Recover RTS _Fum__Fv.END: RTS File “bloodEnglishmanCPP.cpp” void Fee(void); void Fi(void); void Fo(void); void Fum(void); void Fum(void) { Fee( ); Fi( ); Fo( ); }
25
File “bloodEnglishmanCPP.cpp”
Subroutine “passing in“an int” in R0 calling another subroutine “passing out an int” in R0 – works by accident File “bloodEnglishmanASM.asm” .extern _Fee__Fi; .extern _Fi__Fi; .extern _Fo__Fi; .section program; .global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK 16; Stores RETS R0 += 6; // pass parameter in R0 // R0 is dead – value is no longer needed CALL _Fee __Fi; Overwrites RETS R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; Recover RETS UNLINK; _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6 + value); Fi(7); Fo(8); }
26
Subroutine “passing in“an int” in R0 calling another subroutine “passing out an int” in R0 DOES NOT work this time .extern _Fee__Fi; .extern _Fi__Fi; .extern _Fo__Fi; .section program; .global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK 16; Stores RETS R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; // Problem – can’t do this R0 destroyed R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; Recovers RETS UNLINK; _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); }
27
File “bloodEnglishmanCPP.cpp”
Solution using ENCM369 MIPS ideas Subroutine calling integer subroutine Save R0 to stack frame at start, recover it later .section program; .global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK (16 + 4); [FP + 20] = R0; SAVE INCOMING R0 R0 = 6; // pass parameter in R0 CALL _Fee __Fi; DESTROYS R0, R1, R2 R0 = 7; // pass parameter in R0 CALL _Fi __Fi; DESTROYS R0, R1, R2 R0 = [FP + 20]; // Recover R0 R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; // This unlink discards 20 _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); }
28
File “bloodEnglishmanCPP.cpp”
Subroutine calling integer subroutine (passing parameters) The way I remember the easiest and have the least trouble with.. DO BEFORE LINK .section program; .global _Fum__Fi; _Fum__Fi: // value passed in R0 [--SP] = R7; // R7 always saved by other routines – SAVE before LINK R7 = R0; // Save R0 to R7 LINK 16 R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = R7 // Recover R0 R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; R7 = [SP++]; // Recover R7 AFTER unlink _Fum__Fi.END: JUMP (P0); File “bloodEnglishmanCPP.cpp” void Fee(int); void Fi(int); void Fo(int); void Fum(int); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); }
29
Handling arrays in C /C++ and assmbly code
30
long int and extern long int arrays long int * and extern long int *
.extern _thumb; in C++ .extern _thumbPt; in C++ Means the following in assembly code .section L1_data; .global _plumb; .byte4 _plumb[5] = {1, 2, 3, 4, 5}; .global _pointers; .byte4 _pointers[5]; .section program; File “PutInHisThumb.cpp” extern long int thumb[10]; extern long int *thumbPt[10]; long int plumb[5] = {1, 2, 3, 4, 5}; long int *pointers[6]; long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] }
31
extern long int File “PutInHisThumb.cpp” extern long int thumb[10];
.extern _thumb; .section L1_data; .global _plumb; _ byte4 _plumb[5] = {1, 2, 3, 4, 5}; .section program; .global _Jack__FPl; // Pointer long _Jack__FPl: // pointer passed in R0 LINK 16; P0 = R0; // Use passed value as a pointer P1.L = _thumb; P1.H = _thumb; R0 = [P1 + (2 * 4)]; // LOAD P1.L = _plumb; P1.H = _plumb; R1= [P1 + (1 * 4)]; // LOAD R0 = R0 + R1; [P0 + (3 * 4)] = R0; // STORE P0 = [FP +4]; UNLINK; _ Jack__FPl .END:: JUMP (P0); File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] }
32
extern volatile long int
.extern _thumb; .section L1_data; .global plumb; _ byte4 _plumb[5] = {1, 2, 3, 4, 5}; .section program; .global _Jack__FPl; // Pointer long _Jack__FPl: // pointer passed in R0 LINK 16; P0 = R0; // Use passed value as a pointer // R0 is now dead – can reuse P1.L = _thumb; P1.H = _thumb; R0 = [P1 + (2 * 4)]; // LOAD P1.L = _plumb; P1.H = _plumb; R1= [P1 + (1 * 4)]; // LOAD R0 = R0 + R1; [P0 + (3 * 4)] = R0; // STORE P0 = [FP +4]; UNLINK; _Jack__FPl.END: JUMP (P0); File “PutInHisThumb.cpp” extern volatile long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] }
33
Issues with reading memory in loops
34
extern long int – optimized code generated by C++ -- NOT CORRECT
.extern _star; .extern _BlinkLight__Fv; .section program; .global _Wonderwhat__Fv; _Wonderwhat__Fv: LINK 16; P1.L = _star; P1.H = _star; R0 = [P1 + (2 * 4)]; // LOAD CC = R0 == 2; IF !CC JUMP DONE; LOOP: CALL _BlinkLight__Fv; JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } Either star[2] == 2, or it does not If star[2] == 2 then get an infinite loop otherwise BlinkLight( ) never called
35
extern volatile long int optimized code – STILL WRONG
.extern _star; // No volatile keyword in ASM .extern _BlinkLight__Fv; .section program; .global _Wonderwhat__Fv; _Wonderwhat__Fv: LINK 16; P1.L = _star; // Re-use as pointer P1.H = _star; LOOP: R0 = [P1 + (2 * 4)]; // KEEP LOADING // THIS CODES THE VOLATILITY CC = R0 == 2; // LOOP NEEDED IF !CC JUMP DONE; CALL _BlinkLight__Fv; DESTROYS P1 -- FIX JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern volatile long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } star[2] == 2 MAY START OFF BEING 2 But since star is “volatile” then some external action may change it. Loop needed in optimized code if “volatile” memory value GOOD IDEA – WILL NOT WORK AS P1 is destroyed during CALL BlinkLight
36
extern volatile long int optimized code -- CORRECT
.extern _star; .extern _BlinkLight__Fv; .section program; .global _Wonderwhat__Fv; _Wonderwhat__Fv: [--SP] = P5; // Save the non-volatile LINK 16; P5.L = _star; // Not destroyed P5.H = _star; LOOP: R0 = [P5 + (2 * 4)]; // KEEP LOADING // THIS CODES THE VOLATILITY CC = R0 == 2; // LOOP NEEDED IF !CC JUMP DONE; CALL _BlinkLight__Fv; KEEPS P5 JUMP LOOP; UNCHANGED DONE: P0 = [FP +4]; UNLINK; P5 = [SP++]; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern volatile long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } star[2] == 2 MAY START OFF BEING 2 But since star is “volatile” then some external action may change it. Loop needed in optimized code if “volatile” memory value
37
Understanding what I did
Will look at things in more detail later in class But here are some ideas of why we did what we did
38
LINK – what does it do? A correction – Processor Programming Reference 4:17
Does all the following in one instruction [--SP] = RETS; [--SP] = FP; FP = SP; SP SP – 16; LINK ( ) Does all the following in one instruction [--SP] = RETS; [--SP] = FP; FP = SP; SP SP – 200; (Space for an array) SP SP – 16;
39
UNLINK – what does it do? LINK 16 UNLINK
Unlink does all the following in one instruction SP = FP; FP = [SP++]; RETS = [SP++]; LINK ( ) UNLINK Unlink does all the following in one instruction SP = FP; FP = [SP++]; RETS = [SP++];
40
Subroutine calling subroutine All void functions
File “bloodEnglishmanASM.asm” .extern _Fee__Fv; defined elsewhere .extern _Fi__Fv; .extern _Fo__Fv; .section program; .global _Fum__Fv; _Fum__Fv: Since the other functions are coded “outside” or “external” to this file then we indicate that with the keyword .extern File “bloodEnglishmanCPP.cpp” void Fee(void); void Fi(void); void Fo(void); void Fum(void); void Fum(void) { }
41
Subroutine calling subroutine All void functions
File “bloodEnglishmanASM.asm” .extern _Fee__Fv; .extern _Fi__Fv; .extern _Fo__Fv; .section program; .global _Fum__Fv; // Not “private” _Fum__Fv: Since we want other functions (coded “outside” or “external” to this file) to be able to use Fum( ) coded in this file we must “globalize” (tell everybody) this functions name with the keyword .global File “bloodEnglishmanCPP.cpp” void Fee(void); void Fi(void); void Fo(void); void Fum(void); void Fum(void) { }
42
Subroutine calling subroutine All void functions
File “bloodEnglishmanASM.asm” .extern _Fee__Fv; .extern _Fi__Fv; .extern _Fo__Fv; .section program; .global _Fum__Fv; _Fum__Fv: LINK 16; // Save RETS to stack CALL _Fee __Fv; // Changes RETS CALL _Fi __Fv; // Changes RETS CALL _Fo__Fv; // Changes RETS P0 = [FP +4]; // Saved RETS into P0 UNLINK; // Saved RETS into RETS // and destroy (remove) stack frame _Fum__Fv.END: JUMP (P0); // Now equivalent to RTS Why this approach? Possibly more efficient because of the pipeline The LINK 16; operation saves this subroutine’s return address (stored in the “RETurn from Subroutine register” RETS) onto the stack. This allows the processor to use register RETS when it calls other subroutines – same was as the MIPS – different register name UNLINK restores (recovers, reads) RETS from the stack so we can exit this subroutine.
43
Subroutine calling subroutine All integer functions
Can’t overload on the basis of return value – C++ rule This is the “assembly code reason why void Foo(void) _Foo__Fv int Foo(void) _Foo__Fv Name mangle changes (Do not need to remember details in quizzes and exams – critical to get correct in labs) void Foo(void) _Foo__Fv int Foo(void) _Foo__Fv int Foo(int) _Foo__Fi int Foo(long int) _Foo__Fl int Foo(int *) _Foo__FPi Int Foo(long int *) _Foo_FPl
44
Subroutine calling subroutine All integer functions
.extern _Fee__Fi; .extern _Fi__Fi; .extern _Fo__Fi; .section program; .global _Fum__Fi; _Fum__Fi: // value passed in R0 LINK 16; // R0 incoming parameter is unsaved R0 = 6; // pass parameter in R0 CALL _Fee __Fi; Destroys R0, R1, P0, P1 R0 = 7; // pass parameter in R0 CALL _Fi __Fi; Destroys R0, R1, P0, P1 R0 += 8; // pass parameter in R0 – WRONG VALUE AS TRUE VALUE HAS BEEN DESTROYED CALL _Fo__Fi; P0 = [FP +4]; UNLINK; _Fum__Fi.END: JUMP (P0); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } ALWAYS pass the parameter to the subroutine in R0 – very similar to MIPS Must save the passed value (in R0), otherwise it will be destroyed when we call the other subroutines while we use R0 to pass the parameter
45
Subroutine calling subroutine All integer functions
.section program; .global _Fum__Fi; _Fum__Fi: // value passed in R0 [--SP] = R7; // Save volatile register R7 = R0; // Save passed value LINK 16; R0 = 6; // pass parameter in R0 CALL _Fee __Fi; R0 = 7; // pass parameter in R0 CALL _Fi __Fi; R0 = R7; // Recover passed value R0 += 8; // pass parameter in R0 CALL _Fo__Fi; P0 = [FP +4]; UNLINK; R7 = [SP++]; // Recover saved volatile register _Fum__Fi.END: JUMP (P0); void Fum(int value) { Fee(6); Fi(7); Fo(8 + value); } I always save a non-volatile register (R7) onto the stack -- and then save R0 into R7. Easier to remember and optimize ALWAYS pass the parameter to the subroutine in R0 – very similar to MIPS
46
This file is in a project by itself
This file is in a project by itself. It compiles but does not link or run! Why not? A project containing only the file “PutInHisThumb.cpp” will not link and run because Very common error All projects must have a main( ) in them If you receive a message – can’t link to _main – when you are doing the laboratory – then this is the problem. File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] }
47
These two files compile but does not link and run-- Why not?
File “main.cpp” extern long int thumb[10]; extern long int plumb[5] ; long int goodboy[10]; long int Jack(long int *goodboy) int main(void) { for (int count = 0; count < 10; count++) goodboy[count] = 0; Jack(goodboy); printf(“%d\n”, goodboy[3]); } File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] }
48
This does not link and run Why not?
DECLARED IN ANOTHER FILE DECLARED IN THIS FILE File “main.cpp” extern long int thumb[10]; extern long int plumb[5] ; long int goodboy[10]; File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} DECLARED IN ANOTHER FILE DECLARED IN THIS FILE IN NO FILE HAS MEMORY SPACE BEEN SET ASIDE FOR THE “THUMB” ARRAY
49
This does link and run -- because all arrays have been given “space”
File “main.cpp” long int thumb[10] = {2, 4, 6, 8, 10}; extern long int plumb[5] ; long int goodboy[10]; long int Jack(long int *goodboy) int main(void) { for (int count = 0; count < 10; count++) goodboy[count] = 0; Jack(goodboy); printf(“%d\n”, goodboy[3]); } File “PutInHisThumb.cpp” extern long int thumb[10]; long int plumb[5] = {1, 2, 3, 4, 5} long int Jack(long int *goodboy) long int Jack(long int *goodboy{ long int sum; goodboy[3] = thumb[2] + plumb[1] }
50
How can something in memory change like this
.extern _star; .extern _BlinkLight__Fv; .section program; .global _Wonderwhat__Fv; _Wonderwhat__Fv: LINK 16; P0 = R0; // Use passed value as a pointer P1.L = _thumb; P1.H = _thumb; LOOP: R0 = [P1 + (2 * 4)]; // KEEP LOADING CC = R0 == 2; // LOOP NEEDED IF !CC JUMP DONE; CALL _BlinkLight__Fv; JUMP LOOP; DONE: P0 = [FP +4]; UNLINK; _Wonderwhat__Fv .END: JUMP (P0); File “TwinkleTwinkle.cpp” extern volatile long int star[10]; void WonderWhat(void); void BlinkLight(void); void WonderWhat(void) { while (star[2] == 2) { BlinkLight( ); } star[2] == 2 MAY START OFF BEING 2 But since star is “volatile” then some external action may change it. Loop with repeated read needed in optimized code if “volatile” memory value
51
Example from Lab. 1 Audio talkthrough
Difference between subroutines and interrupts There is a main routine There is an “interrupt audio” routine. Every 1 / s the interrupt routine “interrupts” (temporarily halts) main( ), then runs itself, and then returns control to main Interrupts run under “external control” when “something happens” switch changes or voltage changes -- unexpected Subroutines run under “internal control” ONLY WHEN CALLED – NEVER UNEXPECTED
52
WORRY ABOUT WHAT EX_INTERRUPT_HANDLER( ) MEANS IN LAB. 2
Example from Lab. 1 Task 4 File “main.cpp” volatile boolean mute_on = FALSE; long int ReadSwitches(void); int main( ) InitializeSwitches( ); InitializeAudio( ); StartInterrupts( ); while (1) { int value = ReadSwitches( ); // If switch pressed // – turn off sound; if (value == 0x100) mute_on = TRUE; else mute_on = FALSE; } File “interruptservice.cpp” extern volatile boolean mute_on; void Process_DataASM(void); EX_INTERRUPT_HANDLER(Sport0_RX_ISR) { …….. /// Lots of good stuff Process_DataASM( ); // Make the sound occur …….. // Lots of more good stuff; } void Process_DataASM(void) { if (mute_on = = FALSE) MakeTheSound( ); WORRY ABOUT WHAT EX_INTERRUPT_HANDLER( ) MEANS IN LAB. 2
Similar presentations
© 2024 SlidePlayer.com Inc.
All rights reserved.