Upload
hillary-terry
View
228
Download
0
Embed Size (px)
Citation preview
Handling multiple input signals
Version #2 – co-operative scheduler
Version #3 – pre-emptive scheduler
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).
10k resistor
+5V
GROUND
PF6
GROUND
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
Approach #1 – Superloop approach based on Lab. 1 ideasWhile (loop is not stopped) {
Read GPIO Flags
4 possible things possible
At least 2 true at the same time1. Light sensor PF 5 is high
2. Light sensor PF 5 is low
3. Button PF 6 is high
4. 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”
}
One solution for the codeint 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;
}
Using Lab. 2 ideasCo-operative SchedulerTTCOS_Init_Scheduler( ); // Assume Ticks occur every 1 ms – which is faster than people move or
press buttons
TTCOS_Add_Task(InitInterfaces, 0, 0)
TTCOS_Add_Task(WriteToLCD, 50, 100); // Update LCD every 1/10 second – faster than the eye
// These tasks ONLY work if no task waits, and no task causes an interrupt
TTCOS_Add_Task(Count_People, 5, 10); // Worry about people moving
TTCOS_Add_Task(CheckButton, 6, 10); // Worry about the button being pressed
TTCOS_Add_Task(Stop_System, 7, 10); // Do we need to stop the system
TTCOS_Star_Scheduler( );
While (1) {
TTCOS_GoToSleep( );
TTCOS_DispatchTasks( );
}
Using Lab. 2 ideasCo-operative Schedulerint count_G = 0;
int stop_G = 0;
int oldState_G = 0;
void InitInterfaces(void) {
InitAllInterfaces( );
oldState_G = ReadGPIO( ) & PEOPLEMASK;
}
void WriteToLCD(void) { WriteLCD(count_G); 50, 100); }
void Count_People(void) {
int newstate = ReadGPIO( ) & PEOPLEMASK;
if ( (oldstate == 0) && (newState == PEOPLEMASK) ) count_G++;
oldState = newState;
}
void StopSystem(void) {
static systemStopped = 0;
if (systemStopped == 1) return;
if (stop_G == 1) { TTCOS_Stop(WriteToLCD); TTCOS_Stop(CountPeople); TTCOS_Stop(CheckButton)
systemStopped = 1;
}
}
FINAL EXAM HINT
You write the code forCheckButton( )and convert into assembly code
Using Lab. 2 ideasEvent Driven Using Interrupts
InitAllInterfaces( );
SetUpPFInterrupts( );
StartPFInterrupts( );
while (1) {
/* Wait for interrupts to occur in the background */
idle( ); -- Low power mode
}
void InitAllInterfaces(void) { InitLEDs( );
InitLCDScreen( );
// Init GPIO using C/C++*pFIO_DIR = 0; // Do properly with AND and OR
*pFIO_MASKA_D = 0; // All interrupts off – channel 1*pFIO_MASKB_D = 0; // All Interrupts off – channel 2
*pFIO_POLAR = 0;
*pFIO_EDGE = 0; // Will become very important*pFIO_BOTH = 0; // Will become important
*pFIO_INEN = 0x0600; need PF5 (0x20) and PF6 (0x40);
}
04/21/23 Thermal Arm Wrestling, Copyright M. Smith, ECE, University of
Calgary, Canada
10 / 24 + extras
PF registers
Direction, Data, Polarity and Enable all the same from Lab. 1
Flag Mask registers – 14-11Flag mask Interrupt data register – basically which
PF pins have been set to allow to cause interruptFlag mask Interrupt Set register – sets PF pin that is allowed to
cause an interrupt, without the need for a read – or mask – write operation
Flag Mask Interrupt Clear register – which PF pin is no longer allowed to cause an interrupt without the need for a read – and mask – write operation
Flag interrupt Sensitivity register (FIO_EDGE) – set for edge-sensitive
FIO_BOTH allows you to cause interrupts on “both” leading and trailing edges of PF signals
EX_INTERRUPT_HANDLER(PFInter)
All PF interrupts are multiplexed. That means any interrupt on PF line gets to same ISR
We get here ifPF5 line goes from low to highPF6 line goes from low to high
How do we know which one interruptedIf PF5 interrupt then FIO_FLAG bit 5 is highIf PF6 interrupt then FIO_FLAG bit 6 is high
Interrupt routine looks like this#define BIT5 0x20
#define BIT6 0x40
extern volatile int count;
extern volatile int stop;
EX_INTERRUPT_HANDLER(PFInterrupt) {
short int whichInterrupt = *pFIO_FLAG_D & (BIT6 | BIT5); // Brackets around (BIT6 | BIT5); very important in Quiz 3
if ( (whichInterrupt & BIT5) == BIT5) { // Brackets important in Quiz 3
count++; *pFIO_FLAG_D &= ~BIT5; // Clear interrupt bit or *pFIO_FLAG_C = BIT5; // Clear interrupt bit
}
if ( (whichInterrupt & BIT6) == BIT6) { // Brackets important in Quiz 3
stop = 1; *pFIO_FLAG_D &= ~BIT6; // Clear interrupt bit or *pFIO_FLAG_C = BIT6; // Clear interrupt bit
}
} // Can you translate this into assembly code for post-lab quiz 3
Getting interrupts to work
void SetUpInterrupts( ) {
// SetUp_VectorTable( ); Lab. 3
// SetUp_IMASK( ); Lab. 3
register_handler(ik_ivg12, PFInterrupt);
SetUp_SIC_MASK( ); Lab. 3 SetUp_PFLinesForInterrupts( ); Lab. 3
}
Getting interrupts to workvoid SetUpInterrupts( ) {// SetUp_VectorTable( );
Lab. 2
// SetUp_IMASK( ); Lab. 2
register_handler(ik_ivg12, PFInterrupt);
// SetUp_SIC_MASK( ); Lab. 2 *pSIC_IMASK = 0x00100000
// SetUp_PFLinesForInterrupts( );
*pFIO_FLAG_D = 0; // In case interrupt waiting
*pFIO_MASKA_S = (BIT5 | BIT 6);
}
void StartInterrupts( ) { *pFIO_FLAG_C = (BIT4 | BIT5); // Waiting
*pFIO_MASKA_D = (BIT4 | BIT5); Lab. 2
}
Other approaches
We could
Use PF Interrupt A for PF5 line
and PF Interrupt B for PF6 line
Writing 2 ISR’s
Example interrupt routine In assembly codeDesign the codeStart the special ISR instructionsWrite “the subroutine” part of the ISRFinish the special ISR instructionsTest the codeOptimize for FAST ISR
ISR routines are marked for efficiency
Design the code
Fix the easy bits-- Unoptimized code okay at this point
Add in the code
HINT:Easier to optimizeif use higher registers first
Optimize the code – save ONLY the registers used
ENTER 10 cyles205 1+206 1+207 6+209 2 + 4210 1+211 12121214 1215 1 ?216 2217 2 + 4218 1
224 5 jumpMissing ssync( )236 RTI 10 cycles