Lab6

advertisement
ECE 2325
UMD
Fall 2002
Lab6: Interrupts and Interrupt Service Routines
Reaction Time Calculator
Objective:
This lab demonstrates the initiation and resolution of interrupts on the 68HC11 and
explores some possible applications for Interrupt Driven I/O.
Discussion:
Interrupts on the 68HC11 are rather straightforward. They are usually maskable (can be
disabled by setting a mask bit). They automatically push all registers to the stack at the
initiation of the interrupt and restore them upon return from interrupt. For all interrupts
maskable by the I-bit (bit 4 of the CCR), the 68HC11 automatically disables interrupts
for the duration of the interrupt service routine.
It is desired to construct a Reaction Timer to test the eye-hand reaction time of a human
being. The timer will be constructed using the 68HC11 EVB lab station and a pushbutton
switch that shorts the IRQ pin to ground. The EVB will be driven by a program which
will do the following:
1. Prompt the test subject to declare their readiness for the test: (“Ready (y or n)?”
2. Upon an “n” response to the above query, the program will end via the SWI
(Software Interrupt).
3. Upon a “y” response, the program will enter a pseudo random delay of 1 to 2
seconds.
4. Upon any other response, the program will re-prompt for readiness.
5. After a “y” response and the random delay, the 8 digit LED display will start to
flash and a counter will be started by setting the RTII bit (bit 6 in register 1024).
6. The counter will be incremented by the Real Time Interrupt Service Routine.
7. As soon as the subject sees the flashing LEDs, the subject will press the spacebar.
8. The press of the spacebar will initiate an SWI interrupt, whose service routine will
stop the flashing LEDs and disable RTI interrupts.
9. The press of the spacebar will also cause the reaction time to be displayed on the
monitor in milliseconds.
10. The program must keep track of the four most recent reaction times.
11. At any time, if the pushbutton switch is pressed, the ensuing IRQ Interrupt
Service Routine will average the four most recent reaction times and display that
average on the monitor, in milliseconds.
The skeleton of the program is shown at the end of this document. In order to
complete it, 4 routines must be coded:
1.
seconds
2.
S.Norr
A Delay Subroutine, DelVar, which is of variable length between 1 and 2
An Interrupt Service routine, IRQSvc, initiated by the IRQ interrupt
-1-
10/17/02
ECE 2325
3.
4.
UMD
Fall 2002
An Interrupt Service Routine, RTISvc, initiated by the RTI interrupt
An Interrupt Service Routine, SWISvc, initiated by the SWI interrupt
NOTE: The three service routines also need to have their jump vectors initialized at the
top of the main program.
Each of these routines is described in some detail below:
Delay Subroutine, DelVar:
When called, this subroutine will execute a delay loop of variable length between 1 and 2
seconds. Therefore, the down-counter loop must be initialized by a variable number.
The variable number is obtained by performing the 16-bit addition of two values. Value
1 is the number for the fixed delay value, (4000)16. Value 2 is the variable delay value.
To obtain a pseudo-random value for the variable delay, use the current value of TCNT.
TCNT is a free running 16-bit counter located in registers 100E and 100F. TCNT must
be scaled from its current range, 0000 – FFFF, down to 0000 – 3FFF. This can be
accomplished by dividing TCNT by 4 (Do not use IDIV for this).
The pseudo-code for this subroutine should look something like this:
DelVar:
Loop:
Save old register values on the stack
Load TCNT in a 16 bit accumulator
Divide TCNT by 4
Add 4000 to result
Make that sum a counter value
NOP
Dec Counter
Branch not equal zero to Loop
Restore old register values
Return from subroutine
The value 4000 Hex, should, in a one NOP loop, provide about 1 second of delay.
TCNT/4 should provide between zero and one second of additional delay.
IRQ Interrupt Service Routine:
As previously stated, the IRQ pin on the 68HC11 causes an interrupt on a transition from
one to zero. To make the IRQ pin edge sensitive, set the IRQE flag, which is bit 5 of
register 1039. Use the bset instruction to do this during the jump vector initialization
portion of the main program.
On the EVB stations in Lab, the IRQ pin is wired out to a 16-pin test socket, as is
ground. IRQ will be wired to ground through a spring-contact, push-button switch as
shown below:
S.Norr
-2-
10/17/02
ECE 2325
UMD
Fall 2002
This interrupt will be used to initiate an IRQ Interrupt Service Routine that calculates the
arithmetic average of the four most recent reaction time tests. Each test result will be an
8-bit, unsigned number, located in memory at addresses C000 – C003. The summing of
four 8-bit, unsigned numbers can create a 10-bit result. If we divide this result by 4 (back
to 8-bits), we would have the average count. However, we want the average time in
milliseconds which would be that average count multiplied by 4. Thus, if we just sum the
four numbers in a 16 bit register, push it on the stack and call a custom subroutine, Reslt
(provided in the code at the end of this document), it will send the information to the
monitor for display as milliseconds. End this Routine with the rti (Return from Interrupt)
instruction.
Note: The main program will initially clear the 4 memory locations. This subroutine
will not accurately compute an average until after the first 4 test results have been
performed.
Also Note: Since an IRQ interrupt can happen at any time, it would make the screen
look nice if a carriage return and a line feed were sent to screen prior to calling the Reslt
subroutine. Use the following code or something similar at the TOP of your IRQ service
routine:
ldx #0a0d
pshx
jsr PutC
jsr PutC
Your calculations here
push 2 bytes of data
jsr Reslt
S.Norr
-3-
10/17/02
ECE 2325
UMD
Fall 2002
pull off 2 bytes of data
IMPORTANT: Reslt does not corrupt registers, BUT it does leave data on the stack.
When called during an interrupt service routine it will alter the stack frame, unless data
pushed to Reslt is pulled off afterward.
RTI (Real-Time Interrupt) Service Routine:
It is intended to use the RTI counter to initiate interrupts at regular intervals of 4.1
milliseconds during the test sequence. The monitor program for the EVB initializes RTI
to interrupt at that rate already. The main program will enable the RTII flag at the start of
the test (After the variable delay and just after the LED’s start to flash). At that point,
RTI interrupts will occur every 4.1 ms until the spacebar is pushed. Each time an RTI
interrupt occurs, a counter (an 8-bit memory location) must be incremented. Thus, the
number of counts multiplied by 4.1 milliseconds will result in the reaction time in
milliseconds. In order to accomplish this the RTI Interrupt Service Routine will need to
do the following things:
1. Clear the RTIF flag. RTIF is set every time the RTI counter overflows. In
order to clear the flag, a logic One must be written to that bit. This may sound
odd, but is standard practice to avoid the accidental clearing of important
flags. Do this with the bclr instruction. RTIF is bit 6 of register 1025, so use
bclr with a mask byte that is all ones, but has a zero in bit six..
2. Increment the memory location that currently counts the number of RTI
interrupts. Memory addresses C000 – C003 are used for this. The main
program will keep track of which memory location is currently being used. It
will store this memory address at C006, C007. Use that address as the vector
for incrementing memory in indexed mode.
3. Important: Check if memory is making the transition from FF to 1(00).
Since the interrupt interval is 4.1 ms and the number of interrupts counted can
only reach 25510, the reaction timer can only measure about 1 Second of
reaction time. To prevent the count from “rolling over” to zero and starting
over, “freeze” the counter at FF if it occurs.
4. Return from Interrupt
VALID ASSUMPTION:
You may assume that your service routine won’t need to overwrite the data in C000C003. In other words, you may write RTISvc in a manner that doesn’t clear the memory
address it’s going to use, the second time it uses it. The main program will take care of
initializing and maintaining the data locations.
SWI Interrupt Service Routine:
Since swi is a useful instruction for ending the main program, it is desired to use it both
as normally intended and also as a means of ending the reaction time measurement. The
SWI interrupt will be used normally unless the spacebar is pressed. Therefore, the
custom service routine must check to see if the spacebar was pressed. If not, the custom
S.Norr
-4-
10/17/02
ECE 2325
UMD
Fall 2002
routine will jump to the normal jump vector for swi and execute the normal interrupt
sequence. If the spacebar was indeed pressed, the custom routine must do the following:
1. Disable the RTI interrupt by clearing the RTII bit. RTII is bit 6 of register
1024. Use the bclr instruction with a 1 in bit six, zeros elsewhere.
2. Load the value of the current count. Remember that the address of the
memory location for the current count resides in C006,7. Use an indexed
load.
3. Multiply the value by 4 (4 is close enough to 4.1 ms for this application),
realizing once again that the result will be a 10-bit number (2 bytes). This will
scale the test result as milliseconds.
4. Push both bytes on the stack, low byte first, and call the custom subroutine,
Reslt. Remember that to use Reslt:
A. push 2 bytes of data to stack, lo byte first
B. jsr Reslt
C. pull 2 bytes of data off stack
Do this twice.
5. Return from Interrupt.
As mentioned above, the custom service routine must check to see if spacebar was
pressed. The main program will use GetC to detect a keypress. If the spacebar is
pressed, the main program will push it on the stack and execute the swi instruction,
causing an interrupt. At that point, all registers are pushed on the stack ON TOP of the
spacebar push. Therefore, upon entering the custom routine, the stack appears as follows:
CCR
AccB
AccA
InX hi
InX lo
InY hi
InY lo
PC hi
PC lo
SpaceBar = $20
Load the value of the stack where the spacebar push should be. Compare it to the hex
value 20. If true, your custom routine should do 1 through 4 above. If false, jump to
AA73, the normal jump vector for SWI.
Memory Map of Data Locations:
Address
C000
C001
C002
C003
S.Norr
Contents
Test Result 1
Test Result 2
Test Result 3
Test Result 4
-5-
10/17/02
ECE 2325
UMD
C004
C005
C006
C007
Fall 2002
Current Test Hi-byte
Current Test Lo-byte
INTERRUPT DATA: Jump table data on the EVB after reset:
Interrupt
Base Address
IRQ
RTI
SWI
BFF2,3
BFF0,1
BFF6,7
Jump Table
Address
00EE
00EB
00F4
Jump Vector
FF FF FF
FF FF FF
7E AA 73
Example Main Program:
;
;
;
;
;
;
;
;
L6NEW.asm - new Reslt Subr, better
management of data locations
Code for Lab 6 on the EVB
Must be modified to test on THRSim11
Program prints a message to screen,
accepts a keypress, and calculates
reaction time in SWI ISR.
PutC = bfd3 ;assign labels to the custom
GetC = bfd0 ; instruction address locations
;;;;;;;;;;;;;;;;;;;;;;;;
IRQ = ef
SWI = f5
; You may use these
RTI = ec
; or make your own
TCNT = 100e
;;;;;;;;;;;;;;;;;;;;;;;;
org c00a
db
db
db
db
db
0a,0d
72,65,61,64
79,28,79,20
6f,72,20,6e
29,3f,00
; Message data
org c200
Main:
lds #dfff ; initialize the stack at bottom of
; memory
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Set jump table for
; Interrupt Svc. Routines
; here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
clr c000
clr c001
S.Norr
; initialize test data locations
-6-
10/17/02
ECE 2325
UMD
Fall 2002
clr c002
clr c003
First: ldy #c000
Load: sty c006
cli
ldx #c00a
Send: ldaa 0,x
beq Wait
psha
inx
jsr PutC
bra Send
Wait:
Next:
Port:
Spc:
End:
S.Norr
; initialize data pointer
; enable interrupts
; load A with ASCII for Message
; push the contents of A onto the stack
; Send message to screen
jsr GetC
; use GetC to detect a key press
bcc Wait
pula
; when a key is pressed load the ASCII vale into A
psha
; put it back on the stack
jsr PutC
; dump the ASCII character for the key to the Monitor
cmpa #79
; check to see if the key press was "yes"
beq Next
cmpa #6e
beq End
bra Load
clr 0,y
clr 1004
com 1004
; blank the LEDs
jsr DelVar ; Wait for a variable time
ldx #1000
bset 24,x,40
; Enable RTI interrupt
com 1004
; Shine LEDs
jsr GetC
; Wait for spacebar press
bcc Spc
pula
cmpa #20
bne Spc
psha
ldx #0a0d
pshx
jsr PutC
jsr PutC
swi
; If Spacebar press, Interrupt
ldy c006
iny
cpy #c004
bne Load
jmp First
ldaa #65
psha
ldx #6279
pshx
ldx #0a0d
pshx
jsr PutC
jsr PutC
jsr PutC
-7-
10/17/02
ECE 2325
UMD
Fall 2002
jsr PutC
jsr PutC
jsr DelVar
swi
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
DelVar:
; make your delay subroutine here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
IRQSvc:
; make your IRQ ISR here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
RTISvc:
; make your RTI ISR here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SWISvc:
;make your SWI ISR here
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HtoA:
; Convert 8-bit ASCII to 4-bit Hex
; input registers: none - 8-bit
;
local variable
;
passed to stack
; output registers: none - 8-bit
;
local variable
;
passed to stack
;
4-bits of leading
;
zeros, 4-bits data
;
pshx ; store old values of X and A
psha
tsx
; transfer SP contents to X
ldaa 5,x ; load ASCII char from stack
adda #30 ; stubtract 30 from ASCII
cmpa #3a ; check if number was less than A (10)
blt Done ; if so, done, restore registers
adda #27 ; if not, convert to "a" thru "f" value
Done: staa 5,x ; put HEX number on stack
pula
; restore contents of A and X
pulx
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Reslt:
;
Input: 16 bit variable passed to stack
;
Output: Puts 2 ASCII Char to Montr
;
!!Data NOT removed from stack!!
;
Does not corrupt registers
;
Calls Subroutine Parse
pshy
S.Norr
-8-
10/17/02
ECE 2325
UMD
Fall 2002
pshx
psha
tsx
ldaa 7,x
psha
psha
jsr Parse
jsr HtoA
jsr PutC
jsr HtoA
jsr PutC
ldaa 8,x
psha
psha
jsr Parse
jsr HtoA
jsr PutC
jsr HtoA
jsr PutC
ldx #6d53
pshx
jsr PutC
jsr PutC
pula
pulx
puly
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Parse:
;
Subr to turn 8-bit Hex into
;
2 4-bit Hex
;
INPUT: 2 pushes of one 8-bit Hex
;
passed to the stack
;
OUTPUT: 2 nibbles of 4-bit Hex
;
passed to the stack,
;
4-bits of leading zeros
pshx
psha
pshb
tsx
ldaa 6,x
tab
anda #0f
lsrb
lsrb
lsrb
lsrb
staa 7,x
stab 6,x
pulb
pula
pulx
rts
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
S.Norr
-9-
10/17/02
Download