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