Review of ISR for Post-Lab Quiz 3

Handling multiple input signals
Version #2 – co-operative scheduler
Version #3 – pre-emptive scheduler
Midterm question
 Light sensor is in front of the door
+5V
 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.
10k
resistor
PF6
 Button connected to PF6 line
 Show the count of the people on
the LCD using WriteLCD( int
count).
GROUND
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 ideas
While (loop is not stopped) {
Read GPIO Flags
4 possible things possible
At least 2 true at the same time
1.
2.
3.
4.
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”
}
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;
}
Using Lab. 2 ideas
Co-operative Scheduler
TTCOS_Init_Scheduler( );
press buttons
// Assume Ticks occur every 1 ms – which is faster than people move or
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 ideas
Co-operative Scheduler
int count_G = 0;
int stop_G = 0;
int oldState_G = 0;
void InitInterfaces(void) {
FINAL EXAM HINT
InitAllInterfaces( );
oldState_G = ReadGPIO( ) & PEOPLEMASK;
You write
}
the code for
void WriteToLCD(void) {
WriteLCD(count_G); 50, 100); }
CheckButton( )
void Count_People(void) {
and convert into
int newstate = ReadGPIO( ) & PEOPLEMASK;
assembly code
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;
}
}
Using Lab. 2 ideas
Event 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);
}
PF registers
 Direction, Data, Polarity and Enable all the same from Lab. 1
 Flag Mask registers – 14-11
Flag mask Interrupt data register – basically which
PF pins have been set to allow to cause interrupt
 Flag 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
7/31/2017
Thermal Arm Wrestling,
Copyright M. Smith, ECE, University of Calgary,
Canada
10 / 24 + extras
EX_INTERRUPT_HANDLER(PFInter)
All PF interrupts are multiplexed. That
means any interrupt on PF line gets to
same ISR
We get here if
PF5 line goes from low to high
PF6 line goes from low to high
How do we know which one interrupted
If PF5 interrupt then FIO_FLAG bit 5 is high
If 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( );
SetUp_PFLinesForInterrupts( );
}
Lab. 3
Lab. 3
Getting interrupts to
work
void 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 code
Design the code
Start the special ISR instructions
Write “the subroutine” part of the ISR
Finish the special ISR instructions
Test the code
Optimize 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 optimize
if use higher registers first
Optimize the code – save ONLY the
registers used
ENTER 10 cyles
205 1+
206 1+
207
6+
209
2+4
210
1+
211
1
2121
214
1
215
1?
216
2
217
2+4
218
1
224 5 jump
Missing ssync( )
236 RTI 10 cycles