Back to Basics: Interrupts for the 8XC196KC/KD Using Standard ISRs

For additional information about Interrupts, refer to the 8XC196KC/KD User's Manual or ApBUILDER.

One of a microcontroller's primary functions is to provide real-time signals to a device in order to maintain control over a system. In an automobile, for example, a microcontroller may generate the signals to actuate the anti-lock braking device to stop the car when the brake pedal is depressed. In order to process and generate such real-time signals, a microcontroller relies heavily on its interrupt subsystem.

Interrupt Subsystem

When the central processing unit of a microcontroller is executing code, an internal peripheral or external device may request assistance from the processor, or in other words, interrupt the processor. Typically, the processor responds by halting execution of the next instruction and servicing the device that requested the interrupt. Upon completion of the interrupt service routine, the processor resumes normal program flow.

There may be several interrupt sources that require servicing - the completion of an A/D conversion, a timer overflow, the triggering of an external interrupt pin, etc. Naturally, some sources will have higher priority than others. Hence, they need to be handled in an efficient manner. The interrupt subsystem is responsible for prioritizing interrupts and ensures that interrupts with a higher priority are serviced before interrupts of a lower priority. It consists of the interrupt control unit (ICU) and the peripheral transaction server (PTS). This document discusses and gives example programs on the ICU.

Interrupt Processing

An interrupt on the 8XC196KC/KD may be processed in one of two ways: software interrupt service routines through the Interrupt Control Unit or microcoded hardware interrupt processing through the Peripheral Transaction Server.

There are sixteen interrupts available which may be handled by software interrupt service routines. Of the sixteen, fifteen may be masked (disabled). The Nonmaskable Interrupt (NMI) is used to implement critical interrupt routines. If the NMI pin is not used in an application, it should be tied to Vss to prevent spurious interrupts from occurring.

There are two special interrupts which are handled by the interrupt controller directly. These are the Unimplemented Opcode and Software Trap Interrupts (See Table 1). The Unimplemented Opcode interrupt prevents random software execution during hardware and software failures. The Software Trap interrupt serves as a useful debugging tool.

As mentioned above, interrupts have different priorities. When interrupts are detected by the Interrupt Controller, a priority encoder in hardware determines the priority of all current and subsequent requests. The Interrupt Controller then selects the corresponding vector location in Special-Purpose memory. This vector location contains the starting address of the corresponding interrupt service routine. In addition, a transition detector in hardware sets corresponding bits in special function registers (SFRs), INT_PEND and INT_PEND1, to indicate that an interrupt is pending. These bits are set even if individual interrupts are masked. The bits are cleared when the program vectors to the interrupt service routine.

NumberInterrupt VectorKC/KD Vector LocationTarget Board Vector Loc.Priority
SpecialUnimplemented Opcode2012hRET-
SpecialTRAP Instruction2010hreserved for RISM-
INT15NMI (Non Maskable)203Ehreserved for RISM15
INT14HSI FIFO Full203ChD1C0h14
INT12Timer2 Overflow2038hD180h12
INT11Timer2 Capture2036hD160h11
INT10HSI FIFO 42034hD140h10
INT09Receive2032hreserved for RISM_isr9
INT06Serial Port200ChD0C0h6
INT05Software Timer200AhD0A0h5
INT04HSI.0 Pin2008hD080h4
INT03High Speed Outputs2006hD060h3
INT02HSI Data Available2004hD040h2
INT01A/D Conversion Complete2002hD020h1
INT00Timer Overflow2000hD000h0

Table 1 (Interrupt Vectors and Priorities)

Overview of Programming Interrupts

Handling interrupts through software service routines can be very easy. By setting and/or clearing individual bits in the special function registers, interrupts may be enabled and/or disabled. Program flow may be controlled by reading the SFRs as well. Table 2 lists the SFRs typically associated with programming interrupts.

Register MnemonicDescription
INT_MASK, INT_MASK1Enable/Disable each maskable interrupt
INT_PEND, INT_PEND1Bits in this register are set to indicate that an interrupt is pending
IOC1Select the source of INT00, INT02, and INT07
IOS1Contains flags that indicate which events triggered interrupts

Table 2

In addition to the SFRs listed in Table 2, there are other SFRs that may require programming. These, of course, depend on the peripherals being used and which interrupts need to be serviced. Programs 1 and 2 demonstrate how to generate a simple program to handle interrupts in assembly language. For bit descriptions of each SFR, refer to the 8XC196KC/KD User's Manual or ApBUILDER software.

Program 1

Program one illustrates how to handle the HSI FIFO 4 interrupt (INT07) with a simple interrupt service routine. Before programming, it is important to determine which special function registers will be used to ensure that a peripheral and its associated interrupts will work properly. To determine which SFRs need to be used, consult the user's manuals, Back to Basics documents on FaxBACK, or ApBUILDER software. In program one, the additional SFRs which require programming are hsi_mode and ioport1 (ioport1 on the target evaluation board is connected to LEDs)

The HSI FIFO 4 interrupt is generated when the HSI FIFO contains four entries. Events will be registered by positive-edged signals through High Speed Input 0. As a result of the interrupt being generated, the code contained in the interrupt service routine is executed. In this particular program, the interrupt service routine loads a value of FFh into input/output register 1 (illuminates all LEDs on target and evaluation boards).

NOTE: When using the target board, the interrupt vectors have different locations because the RISM code is located in the special-purpose memory space. To work properly, code for the target board should reflect the change in interrupt vector locations. The evaluation board requires no changes.

The following listing shows the assembly language code for program one. A line by line discussion of the program follows:

Program 1 Listing: The following code can be found in BTBEVAL.EXE (HSI4EVL.A96) for evaluation boards and BTBDEVEL.EXE (HSI4TGT.A96) for Project Builder boards on the Intel Bulletin Board Service in the MCS(R)96 Family/General section.

(1) $include (80c196kd.inc)
(2) cseg at 2034h 
(3) dcw hsi4_isr 
(4) cseg at 2080h
(5) di 
(6) ldb wsr, #0 
(7) ldb ioc0, #01H 
(8) ldb wsr, #0 
(9) ldb hsi_mode, #0FDH 
(10) ldb int_mask1, #04H
(11) ei 
(12) loop: 
(13) br loop 
(14) hsi4_isr: 
(15) pusha 
(16) ldb ioport1, #0FFh 
(17) popa 
(18) ret 
(19) end
Line1: The file, 80C196KD.INC, includes all the instructions necessary to equate register names with their appropriate addresses in memory. This file is included with the Project Builder Kit and is also available on Intel's BBS under EV196KD.ZIP.

Line2-3: The interrupt vector is set up in these two lines. The HSI FIFO Fourth Entry interrupt is associated in hardware with location 2034h (see Table 1). When the interrupt is serviced, the command "dcw hsi4_isr" will force the CPU to jump to the hsi4_isr loop. This loop contains the interrupt service routine.
NOTE: On the target board, "dcw" must be replaced by "br".

Line4: Upon reset, the processor fetches code from location 2080h.
NOTE: On the target board, code should start at location 0C000h

Line5: When using ISRs to service interrupts, it is good programming practice to globally disable all interrupts during initialization with di. This will prevent any unwanted interrupts from occuring during initialization.

Line6-9: Set window select register = 0. The 8XC196KC/KD employs horizontal windowing to make up for a lack of special function register address space. Although it is not necessary to reload the window select register in Line 7, it serves as a reminder to which horizontal window this register may be written. (When reading or writing to register locations, a different horizontal window might be used, and hence, the window select register must change). A value of 01h is loaded into the IOC0 SFR in order to set the 0th bit of this register. The 0th bit is the HSI0 enable bit. A value of 0FDh is loaded into the HSI_MODE register to select that only positive edges trigger an event.

Line10: By loading a 04h in the INT_MASK1 register, we enable the HSI FIFO fourth entry interrupt.

Line11: The ei command is the global interrupt enable command. Individual bits in the INT_MASK and INT_MASK1 registers still must be set to enable each interrupt.

Line12-13: This is the main loop. User code is usually placed in between lines 10 and 11, but for simplicity, code is omitted.

Line 14-18: This is the software interrupt service routine. Line 14 is the name, or label, of the ISR. This MUST match the name specified by the dcw command in line 3. Since serving an interrupt requires that the processor halt the execution of the next instruction, the pusha command saves all flags and registers (if applicable) so that these values are unchanged when code within the routine is executed. The popa command in line 17 restores the flags and registers when the interrupt service routine has finished. Any user code may be entered between lines 15-17, but line 15 simply contains a command to load a value into the ioport1 register. The ret command in line 19 instructs the processor to resume normal program flow.

Line20: The end instruction must conclude every assembly language program.

Program 2

Program two demonstrates the use of the 8XC196KC/KD's external interrupts. These interrupts may be connected to a number of different external devices to request help from the processor. In this program, EXTINT and EXTINT1 are used as switches to turn on and off the LEDs of the target or evaluation board, respectively. The EXTINT interrupt will be triggered by a positive edge on Port 0 pin 7 (analog channel 0 on eval board), and the EXTINT interrupt is triggered by Port 2 pin 2. If no signal is detected on either pin, the LEDs will retain their current state.

The SFRs associated with programming the EXTINT and EXTINT1 interrupts are wsr, int_mask, int_mask1, and ioc1. One additional register used for output purposes is ioport1.

Since much of the programming techniques are similar, a line by line discussion of program 2 is omitted.

Program 2 Listing: The following code can be found in BTBEVAL.EXE (INTEVL.A96) for evaluation boards and BTBDEVEL.EXE (INTTGT.A96) for Project Builder boards on the Intel Bulletin Board Service in the MCS96 Family/General section.

(1) $include (80c196kd.inc)
(2) cseg at 200Eh
(3) dcw extint_isr
(4) cseg at 203Ah 
(5) dcw extint1_isr
(6) cseg at 2080h
(7) di
(8) ldb wsr, #00h
(9) ldb ioc1, #02h 
(10) ldb int_mask, #80h 
(11) ldb int_mask1, #020h
(12) ei
(13) loop: 
(14) br loop
(15) extint_isr:
(16) pusha
(17) ldb wsr, #00h
(18) ldb ioport1, #00h
(19) popa
(20) ret
(21) extint1_isr:
(22) pusha
(23) ldb wsr, #00h
(24) ldb ioport1, #0FFh
(25) popa
(26) ret
(27) end
In program 2, two interrupt vectors are needed since there are two interrupt sources (lines 2-5). When a positive-edged signal on the EXTINT pin is detected, the interrupt controller associates that interrupt with vector location 200Eh (or D0E0h for target board). Line 4 contains the command to jump to the corresponding interrupt service routine. Likewise, when a positive-edged signal is detected on EXTINT1, vector location 203Ah (or D1A0h for target board) is associated with the starting address for the EXTINT1 ISR. Remember to change "dcw" in lines 3 and 5 to "br" if the target board is used.

Interrupt service routines, once again, may execute any user code. In lines 15-20, the ISR is used to turn the LEDs off. In lines 21-25, the ISR illuminates the LEDs.

Modifying Interrupt Priorities

An interrupt service routine may be interrupted by another interrupt source, in which case, the completion of the current service routine will be preempted by the new interrupt's request to be serviced. In some cases, this may not be desired. Modifying priorities in software can be accomplished rather easily. This task can be accomplished by masking off certain bits in the interrupt mask registers, INT_MASK and INT_MASK1. For example, the EXTINT interrupt only has a priority of 7. Hence, any other interrupt with a higher priority can interrupt EXTINT's ISR. If we wished that only the EXTINT1 interrupt have priority over EXTINT, we would set the corresponding bit in the INT_MASK1 register and mask off all other bits.

ext_int_isr: pusha ; Save flags and registers (including int_mask & int_mask1) ldb int_mask1, #10000000b ; Bit 7 = 1 enables the EXTINT1 mask register only . ; User ISR code belongs here . popa ; Restore flags and registers ret ; Return from ISR

Interrupt Timing

Interrupt timing becomes an issue when external sources are used to interrupt the microcontroller. An interrupt is sampled when a low-to-high transition occurs. Therefore, an input must be held high for a minimum pulse width to ensure recognition. The five external sources and their minimum pulse width requirements are HSI.0 (>2 state times), NMI (>1 state time), P0.7 (>2 state times), P2.2 (> 2 state times), and Timer 2 Capture (> 2 state times).

There are also certain instructions that prevent interrupts from being acknowledged until after the next instruction is executed. These are di, ei, popa, popf, pusha, and pushf.

The execution of any of the following also inhibit interrupts from being acknowledged until after the next instruction is executed:

Interrupt Latency

Interrupt latency is the total delay between the time that the interrupt is acknowledged and the time that the interrupt service routine is executed. An interrupt is acknowledged only after the current instruction is finished executing. If the interrupt was not acknowledged at least 4 state times before the current instruction, the interrupt might not be acknowledged until after the next instruction. (Instructions are prefetched and prepared a few state times before they are actually executed). If this is the case, a delay equal to the number of state times of the next instruction will be incurred (NORML, the longest instruction, is 39 state times). When an interrupt is acknowledged, the process of obtaining the vector and forcing the call to the proper address takes a total of 11 state times (13 if the stack is located in external RAM assuming zero wait states). Therefore, the maximum latency for standard interrupts is 4+13+39 = 56 state times.

Legal Stuff © 1997 Intel Corporation

Free Web Hosting