Page 356 - Introduction to Microcontrollers Architecture, Programming, and Interfacing of The Motorola 68HC12
P. 356
11.6 Interrupt Synchronization 333
An optimized assembly-language program segment for the body of the C procedure is
shown below. For it and the subsequent handler program segment, we assume there is a
global variable I that is initialized to $80, the number of elements in the buffer, and there
is an $80-element buffer.
LDAB #$80 ; Put one in leftmost bit of Accumulator B
STAB $86 ; Write it into control register TSCR
LDD #$102 ; Generate one in Accumulator A, 2 in Accumulator B
STAA $8C ; Write one in rightmost bit of control register TMSK1
STAA $ 8E ; Write one in rightmost bit of control register TFLG1
STAB $ 8B ; Write 2 in rightmost bit of control register TCTLE
LDD #$FF80 ; Generate two constants in Accumulators A and B
STAA $2 ; Make PORT A output
CLI ; Enable Interrupts
LOOP: LDAB i ; Get index
BNE LOOP ; Wait until all vector elements are output
CLR $8C ; Disable interrupt
An optimized assembly-language program segment for the handler is
CCTO : MOVE #1, TFLG1 ; Write one in rightmost bit of control register TFLG1
LDX #BUFFER ; Get the address of the buffer into X
DEC i ; Decrement index
LDAB i ; Get index
LDAA B f X ; Read a byte from the buffer
STAA $ 0 ; Output the data
RTI ; Return to interrupted routine
This program is quite like the gadfly program in Section 11.5. However, the loop
do ; while { i ); can be replaced by a program that does useful work. Interrupts
provide output whenever the device needs it, without wasting time in a delay or gadfly
loop.
This raises an often-misunderstood point about interrupts. Gadfly has lower latency
than interrupt synchronization. Gadfly does not have to save the registers and then
initialize registers used in the handler. If, when using interrupt synchronization, you just
waste time in a gadfly or wait loop, use gadfly synchronization to lower latency.
The 6812 has a number of I/O devices, and most of them have their own interrupt
vector, shown in Table 11.1. The handler used in the previous example has its vector at
$FFEE and $FFEF, for "Timer channel 0." When an edge occured on PORTT bit 0, the
contents of this vector, the 16-bit data in $FFEE (high byte) and $FFEF (low byte), are
put into the program counter, and the interrupt handler is then executed starting at this
address. Other interrupt vectors of interest in this introductory discussion are the reset,
SWI, and TRAP vectors. The reset vector at $FFFE and $FFFF is the address of the first
instruction that is executed when a 6812 comes out of reset. Locations $FFF6 and
SFFF7 usually contain the address of the monitor program, which is where you go when
an SWI instruction is executed, or a BOND instruction is executed, but the background
debug module is not set up to handle a monitor program. Locations $FFF8 and $FFF9
usually contain the address of the handler for illegal instructions, which can be used to
emulate instructions not implemented in the 6812.