Next Previous Contents

5. Interrupt Service Routine Definition

For this system, the CPU is put into a wait condition prior to allowing interrupt processing. Therefore, the interrupt service routine is very simple: return from all valid interrupts. However, as mentioned before, the BRK instruction is used to indicate a software fault, which will call the same interrupt service routine as the maskable interrupt signal IRQ. The interrupt service routine must be able to tell the difference between the two, and act appropriately.

The interrupt service routine shown below includes code to detect when a BRK instruction has occurred and stops the CPU from further processing. The interrupt service routine is in a file named "interrupt.s".


; ---------------------------------------------------------------------------
; interrupt.s
; ---------------------------------------------------------------------------
;
; Interrupt handler.
;
; Checks for a BRK instruction and returns from all valid interrupts.

.import   _stop
.export   _irq_int, _nmi_int

.segment  "CODE"

.PC02                             ; Force 65C02 assembly mode

; ---------------------------------------------------------------------------
; Non-maskable interrupt (NMI) service routine

_nmi_int:  RTI                    ; Return from all NMI interrupts

; ---------------------------------------------------------------------------
; Maskable interrupt (IRQ) service routine

_irq_int:  PHX                    ; Save X register contents to stack
           TSX                    ; Transfer stack pointer to X
           PHA                    ; Save accumulator contents to stack
           INX                    ; Increment X so it points to the status
           INX                    ;   register value saved on the stack
           LDA $100,X             ; Load status register contents
           AND #$10               ; Isolate B status bit
           BNE break              ; If B = 1, BRK detected

; ---------------------------------------------------------------------------
; IRQ detected, return

irq:       PLA                    ; Restore accumulator contents
           PLX                    ; Restore X register contents
           RTI                    ; Return from all IRQ interrupts

; ---------------------------------------------------------------------------
; BRK detected, stop

break:     JMP _stop              ; If BRK is detected, something very bad
                                  ;   has happened, so stop running

The following discussion explains the purpose of several important assembler level directives in this file.

.import   _stop

This line instructs the assembler to import the symbol _stop from another module. This routine will be called if a BRK instruction is encountered, signaling a software fault.

.export   _irq_int, _nmi_int

This line instructs the assembler that the symbols _irq_int and _nmi_int are to be accessible from other modules. In this example, the address of these symbols will be placed in the interrupt vector table.

.segment  "CODE"

This line instructs the assembler that the code is to be placed in the CODE segment of memory. Note that because there are 65C02 mnemonics in the assembly code, the assembler is forced to use the 65C02 instruction set with the .PC02 directive.

The final step is to define the interrupt vector memory locations. Recall that a segment named VECTORS was defined in the memory configuration file, which started at location $FFFA. The addresses of the interrupt service routines from "interrupt.s" along with the address for the initialization code in crt0 are defined in a file named "vectors.s". Note that these vectors will be placed in memory in their proper little-endian format as:

$FFFA - $FFFB: NMI interrupt vector (low byte, high byte)

$FFFC - $FFFD: Reset vector (low byte, high byte)

$FFFE - $FFFF: IRQ/BRK interrupt vector (low byte, high byte)

using the .addr assembler directive. The contents of the file are:


; ---------------------------------------------------------------------------
; vectors.s
; ---------------------------------------------------------------------------
;
; Defines the interrupt vector table.

.import    _init
.import    _nmi_int, _irq_int

.segment  "VECTORS"

.addr      _nmi_int    ; NMI vector
.addr      _init       ; Reset vector
.addr      _irq_int    ; IRQ/BRK vector

The cc65 toolset will replace the address symbols defined here with the actual addresses of the routines during the link process.


Next Previous Contents