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.
   351   352   353   354   355   356   357   358   359   360   361