MCS6500
Microcomputer Family
Programming Manual
CHAPTER 9
RESET AND INTERRUPT CONSIDERATIONS
9.0 VECTORS
Before developing the concepts of how the MCS650X Microprocessors
handle interrupts and start-up, a brief definition of the concept of
vector pointers needs to be developed.
In the sections on Jumps and Branches, it was always assumed that
the program counter is changed by the microprocessor under control of the
programmer while accessing addresses which were in program sequence. In
order to get the microprocessor started and in order to properly handle
external control or interrupt, there has been developed a different way
of setting the program counter to point at a specific location. This
concept is called vectored pointers. A vector pointer consists of a program
counter high and program counter low value which, under control of
the microprocessor, is loaded in the program counter when certain external
events occur. The word vector is developed from the fact that the microprocessor
directly controls the memory location from which a particular
operation will fetch the program counter value and hence the concept of
vector.
By allowing the programmer to specify the vector address and then by
allowing the programmer to write coding that the address points to, the
microprocessor makes available to the programmer all of the control
necessary to develop a general purpose control program. The microprocessor
has fixed address in memory from which it picks up the vectors. By this
implementation, minimum hardware in the microprocessor is obtained. Locations
FFFA through FFFF are reserved for vector pointers for the microprocessor.
Into these locations are stored respectively the interrupt
vectors or pointers for: non-maskable interrupt, reset and interrupt
request.
9.1 RESET OR RESTART
In the microprocessor, there is a state counter which controls when
the microprocessor is going to use the program counter to access memory
to pick up an instruction, then after the instruction is loaded, the
microprocessor goes through a fixed sequence of interpreting instructions
and then develops a series of operations which are based on the OP CODE
decoding.
Up to this point, it has been assumed that the program counter was
set at some location and that all program counter changes are then
directed by the program once the program counter had been initialized.
Instructions exist for the initialization and loading of all other
registers in the microprocessor except for the initial setting of the
program counter. It is for this initial setting of the program counter
to a fixed location in the restart vector location specified by the microprocessor
programmer that the reset line in the microprocessor is primarily
used.
The reset line is controlled during power on initialization and is
a common line which is connected to all devices in the microcomputer system
which have to be initialized to a known state. The initialization of
most I/O devices is such that they are brought up in a benign state such
that with minimum coding in the microcomputer, the programmer can configure
and control the I/O in an orderly fashion.
The concept has important systems implications in systems where
damage can be done if peripheral devices came up in unknown states. Therefore,
in the MCS650X, power on or reset control operates at two levels.
First, by holding of an external line to ground, and having this external
line connected to all the devices during power up transient conditions,
the entire microcomputer system is initialized to a known disabled state.
Second, the releases of the reset line from the ground or TTL zero
condition to a TTL one condition causes the microprocessor to be automatically
initialized, first by the internal hardware vector which causes it
to be pointed to a known program location, ana secondly through a software
program which is written by the user to control the orderly start-up
of the microcomputer system.
All of the MCS650X family parts also obey a discipline that while
the reset line is low, the system is in a stop or reset state. The microprocessor
is guaranteed to be in a Read state and upon release of the reset
line from ground to positive, the microprocessor will continue to
hold the line in a Read state until it has addressed the specified vectored
count location, at which time control of the microprocessor is available
to the programmer.
NOTE: The MC6800 family also follows this convention.
9.2 START FUNCTION
While the reset line is in the low state, it can be assumed that
internal registers may be initialized to any random condition; therefore,
no conditions about the internal state of the microprocessor are assumed
other than that the microprocessor will, one cycle after the reset line
goes high, implement the following sequence:
Example 9.1: Illustration of Start Cycle
Cycles Address Bus Data Bus External Operation Internal Operation
1 ? ? Don't Care Hold During Reset
2 ? + 1 ? Don't Care First Start State
3 0100 + SP ? Don't Care Second Start State
4 0100 + SP-1 ? Don't Care Third Start State
5 0100 + SP-2 ? Don't Care Fourth Start State
6 FFFC Start PCL Fetch First Vector
7 FFFD Start PCH Fetch Second Vector Hold PCL
8 PCH PCL First Load First OP CODE
OP CODE
The start cycle actually takes seven cycles from the time the reset
line is let go to TTL plus. On the eighth cycle, the vector fetched from
the memory location FFFC and FFFD is used to access the next instruction.
The microprocessor is now in a normal program load sequence, the location
where the vector points should be the first OP CODE which the programmer
desires to perform.
The second point that should be noted is that the microprocessor
actually accesses the stack three times during the start sequence in
cycles 3, 4 and 5. This is because the start sequence is in effect a
specialized form of interrupt with the exception that the read/write line
is disabled so that no writes to stack are accomplished during any of the
cycles.
9.3 PROGRAMMER CONSIDERATIONS FOR INITIALIZATION SEQUENCES
There are two major facts to remember about initialization. One, the
only automatic operations of the microprocessor during reset are to turn
on the interrupt disable bit and to force the program counter to the vector
location specified in locations FFFC and FFFD and to load the first instruction
from that location. Therefore, the first operation in any normal program
will be to initialize the stack. This should be done by having previously
decided what the stack value should be for initial operations and
then doing a LDX immediate of this value followed by a TXS. By this simple
operation, the microprocessor is ready for any interrupt or non-maskable
interrupt operation which might occur during the rest of the start-up
sequence.
Once this is accomplished, the two non variable operations of the
programmer control and the stack is initialized and under program control.
The next operations during the initialization sequences will consist of
configuring and setting up the various control functions necessary to
perform the I/O desired for the microprocessor.
Specific discussion for considerations regarding the start-up are
covered in Section 11.
The major things which have to be considered include the current
state of the I/O device and the non destructive operations that will
allow the state to be changed to the active state.
The initialization programs mostly consist of loading accumulator
A immediately with a bit pattern and storing it in the data control register
of an I/O device.
Note: The interrupt disable is automatically set by the microprocessor
during the start sequence. This is to minimize
the possibility of a series of interrupts occurring during
the start-up sequence because of uncontrolled external
values although it is usually possible to control interrupts
as part of the configuration.
The programmer should consider two effects. First, that the non
maskable interrupt is not blockable by this technique since it would be
possible to configure a device that was connected to a non maskable interrupt
and have to service the interrupt immediately. Secondly, the mask
must be cleared at the end of the start sequence unless the user has
specific reason to inhibit interrupts after he has done the start-up
sequence. Therefore, the next to last instruction of the start-up
sequence should be CLI.
It should be noted that the start-up routine is a series of
sequential operations which should occur only during power on initialization
and is the first step in the programmed logic machine.
Because the execution of the routine during power on occurs very
seldom in the normal operation of the machine, the coding for power
on sequence should tend to minimize the use of memory space rather
than speed.
The last instruction in the start-up sequence should initialize
the decimal mode flag to the normal setting for the program.
The next instruction should be the beginning of the user's normal
programming for his device, everything preceding that being known as
"housekeeping."
9.4 RESTART
It should be noted that the basic microprocessor control philosophy
allows for a single common reset line which initializes all devices.
This line can be used to clear the microprocessor to a known state and to
reset all peripherals to a known state; therefore, it can be used as a
result of power interruption, during the power on sequence, or as an
external clear by the user to re-initialize the system.
As discussed in the hardware manual, restart is often used as an
aid to making sure the microprocessor has been properly interconnected
and that programs have been loaded in the correct locations.
9.5 INTERRUPT CONSIDERATIONS
Up until this point, the microprocessor has to proceed under programmer
control through a variety of sequences. The only way for the programmer
to change the sequence of operations of the microprocessor was to
change the program counter location to point at new operations. The
microprocessor is in control of fetching the next instruction at the
conclusion of the current instruction. The only way that external events
could control the microprocessor, if it were not for interrupts, would be
for the programmer to periodically interrupt or stop processing data and
check to see whether or not an extemal event which might cause him to
change his direction has occurred. The problem with this technique is that
I/O events are usually asynchronous, i.e., not timed with the microprocessor
internal instructions, thererore, it would be possible for the
event to occur shortly after the programmer has stopped to look at I/O
events which would mean that the event would not be sampled until the
programmer took the time to stop his coding and sample again.
Because the sampling of I/O devices normally takes several byte
counts or cycles to accomplish, the frequent insertion of checking
routines into straight line code results in significant delays to the
entire program. In trying to use this technique, there has to be a
trade-off between the fact that the program wastes a significant
amount of time checking events which have not yet occurred versus
delaying checking of an event which has occurred and if not timely
serviced the data may be lost.
In order to solve this dichotomy, the concept of interrupt is used
to signal the microprocessor that an external event has occurred and the
microprocessor should devote attention to it immediately. This technique
accomplishes processing in which the microprocessor's program is interrupted
and the event that caused the interrupt is serviced.
Transferring most of data and control to I/O devices in an interrupt
driven environment will usually result in maximum program and/or programmer
efficiency. Each event is serviced when it occurs which means there
is a minimum amount of delaying in servicing events, also a minimum amount
of coding because of elimination of the need to determine occurrence
of several events simultaneously; each interrupting event is handled
as a unique combination. It is possible to interrupt an interrupt
processing routine and, therefore, all the interrupt logic uses the
stack which allows processing of successive interrupts without any
penalty other than increasing the stack length.
A real world example of an event which should interrupt is when
the user is given a panic button indicating to the microcomputer some
event has occurred which requires total immediate attention of the
microprocessor to solving that problem.
The action and events are as follows : The microprocessor user
pushes the panic button; the panic switch sensor causes an external
device to indicate to the microprocessor an interrupt is desired; the
microprocessor checks the status of the internal interrupt inhibit
signal; if the internal inhibit is set, then the interrupt is ignored.
However, if it is reset or when it becomes reset through some program
reaction, the following set of operations occur:
Example 9.2: Interrupt Sequence
Cycles Address Bus Data Bus External Operation Internal Operation
1 PC OP CODE Fetch OP CODE Hold Program Counter,
Finish Previous
Operation
2 PC OP CODE Fetch OP CODE Force a BRK,
Instruction, Hold
P-Counter
3 01FF PCH Store PCH on Stack Decrement Stack
Pointer to 01FE
4 01FE PCL Store PCL on Stack Decrement Stack
Pointer to 01FD
5 01FD P Store P on Stack Decrement Stack
Pointer to 01FC
6 FFFE New PCL Fetch Vector Low Put Away Stack
7 FFFF New PCL Fetch Vector High Vector Low →
PCL and Set I
8 Vector OP CODE Fetch Interrupt Increment PC to
PCH PCL Program PC + 1
As can be seen in Example 9.2, the microprocessor uses the stack to
save the reentrant or recovery code and then uses the interrupt vectors
FFFE and FFFF, (or FFFA and FFFB) , depending on whether or not an interrupt
request or a non maskable interrupt request had occurred. It should be
noted that the interrupt disable is turned on at this point by the microprocessor
automatically.
Because the interrupt disable had to be off for an interrupt request
to have been honored, the return from interrupt which loads the processor
status from before the interrupt occured has the effect of clearing the
interrupt disable bit. After the interrupt has been acknowledged by the
microprocessor by transferring to the proper vector location, there are a
variety of operations which the user can perform to service the interrupt;
however, all operations should end with a single instruction which
reinitializes the microprocessor back to the point at which the interrupt
occurred. This instruction is called the RTI instruction.
9.6 RTI - RETURN FROM INTERRUPT
This instruction transfers from the stack into the microprocessor
the processor status and the program counter location for the instruction
which was interrupted. By virtue of the interrupt having stored this data
before executing the instruction and the fact that the RTI reinitializes
the microprocessor to the same state as when it was interrupted, the
combination of interrupt plus RTI allows truly reentrant coding.
The symbolic notation for RTI is ↑P ↑PC.
The RTI instruction reinitializes all flags to the position to the
point they were at the time the interrupt was taken and sets the program
counter back to its pre- interrupt state. It affects no other registers
in the microprocessor.
RTI is a single byte instruction and its addressing mode is Implied.
In the following example, we can see the internal operation of the
RTI which restores the microprocessor:
Example 9.3: Return from Interrupt
Cycles Address Bus Data Bus External Operation Internal Operation
1 0300 RTI Fetch OP CODE Finish Previous
Operation, Increment
PC to 0301
2 0301 ? Fetch Next OP CODE Decode RTI
3 01FC ? Discarded Stack Increment Stack
Fetch Pointer to 01FD
4 01FD P Fetch P Register Increment Stack
Pointer to 01FE
5 01FE PCL Fetch PCL Increment Stack Pointer
to 01FF, Hold PCL
6 01FF PCH Fetch PCH M→PCL, Store
Stack Pointer
7 PCH PCL OP CODE Fetch OP CODE Increment New PC
Note the effects of the extra cycle (3) necessary to read data from
stack which causes the RTI to take six cycles. The RTI has restored the
stack, program counter and status register to the point they were at
before the interrupt was acknowledged.
There is no automatic save of any of the other registers in the
microprocessor. Because the interrupt occurred to allow data to be transferred
using the microprocessor, the programmer must save the various internal
registers at the time the interrupt is taken and restore them prior
to returning from the interrupt. Saving of the registers is best done
on the stack as this allows as many consecutive interrupts as the programming
will allow for. Therefore, the routines which save all registers
and restore them are as follows:
Example 9.4: Illustration of Save and Restore for Interrupts
Cycle Bytes
3 1 SAVE PHA Save A
2 1 TXA Save X
3 1 PHA
2 1 TYA Save Y
3 1 PHA
13 5
4 1 RESTORE PLA Restore Y
2 1 TAY
4 1 PLA Restore X
2 1 TAX
4 1 PLA Restore A
16 5
The SAVE coding assumes that the programmer wants to save and to
restore registers A, X and Y. It should be noted that for many interrupts,
the amount of coding that has to be performed in the interrupt is
fairly small.
In this type of operation, it is usually more desirable to shorten
the interrupt processing' time and not use all of the registers in the
machine. Therefore, a more normal interrupt processing routine would
consist of just saving registers A and X which means that the restore
routine would be just restore registers X and A. This has the effect of
shortening the interrupt routine by two bytes, and also shortens the restore
routine by two bytes and will cut 5 cycles out of the interrupt routine
and 6 cycles out of the restore routine.
This technique combined with automatic features of the interrupt
and the RTI allows multiple interrupts to occur with successive interrupts
interrupting the current interrupt. This is one of the advantages
of the use of the stack so that as many interrupts can interrupt other
interrupts as can be held in the stack. The stack contains six bytes for
every interrupt if all registers are saved, so 42 sequences of interrupts
can be stored in one page. However, in more practical situations, consecutive
interrupts hardly ever get more than about three deep.
The advantage of allowing an interrupt to interrupt an interrupt is
that the whole concept behind the interrupt is that asynchronous events
can be responded to as rapidly as possible; therefore, it is desirable
to allow the processing to service one interrupt to be interrupted to
service the second, as long as the first interrupt has been properly
serviced.
To review how this is accomplished using the normal interrupt
capability of the MCS650X, it is important that we review the bus concept
which is inherent in the MCS6500 family and which is compatible with the
M6800.
As has already been discussed, all I/O operations on this type of
microprocessor are accomplished by reading and writing registers which
actually represent connections to physical devices or to physical pins
which connect to physical devices.
Up until this point, this discussion has addressed itself to
transferring of data into and out of the microprocessor. However, there
is a concept that is inherent in the bus discipline that says that whenever
an interrupt device capable of generating an interrupt desires to
accomplish an interrupt, it performs two acts; first, it sets a bit,
usually bit 7, in a register whose primary purpose is to communicate
to the microprocessor the status of the device. The interrupting device
causes one of perhaps many output lines to be brought low. These
collector-or'd outputs are connected together to the IRQ pin on the
MCS650X microprocessor.
The interrupt request to the MCS650X is the IRQ pin being at a
TTL zero. In order to minimize the handshaking necessary to accomplish
an interrupt, all interrupting devices obey a rule that says that once an
interrupt has been requested by setting the bit and pulling interrupt
low, the interrupt will be held by the device until the condition that
caused the interrupt has been satisfied. This allows several devices
to interrupt simultaneously and also allows the microprocessor to
ignore an interrupt until it is ready to service it. This ignoring is
done by the interrupt disable bit which can be set on by the programmer
and is initialized on by the interrupt sequence or by the start sequence.
Once the interrupt line is low and interrupt disable is off, the
microprocessor takes an interrupt which sets on the interrupt disable.
The interrupt disable then keeps the input low line from causing more than
one interrupt until an interrupt has been serviced. There is no other
handshaking between the microprocessor and the interrupting device other
than the collector-or'd line. This means that the microprocessor must use
the normal addressing registers to determine which of several collector-or'd
devices caused the line to go low and to process the interrupt which
has been requested.
Once the processor has found the interrupting device by means of
analyzing status bits which indicates an interrupt has been requested,
the microprocessor then clears the status by reading or writing data
as indicated by the status register.
It should be noted that a significant difference between status
registers and data registers in I/O devices is that status registers
are never cleared by being read, only by being written into or by the
microprocessor transferring data from a data register which corresponds
to some status in the status register. Detailed examples of this
interaction are discussed in Chapter 11. The clearing of the status
register also releases the collector-or'd output thereby releasing the
interrupt pin request.
The basic interaction between the microprocessor and interrupting
device is when interrupting device sets the status bit and brings its
output IRQ line low. If its output IRQ line is connected to the microprocessor
interrupt request line, the microprocessor waits until the
interrupt disable is cleared, takes the interrupt vector, and sets the
interrupt disable which inhibits further interrupts in the IRQ line.
The microprocessor determines which interrupting device is causing an
interrupt and transfers data from that device.
Transferring of data clears the interrupt status and the IRQ pin. At
this point, the programmer could decide that he was ready to accept another
interrupt even though the data may have been read but not yet operated on.
Allowing interrupts at this point, gives the most efficient operation of
the microprocessor in most applications.
There are also times when a programmer may be working on some coding
the timing of which is so important that he cannot afford to allow an
interrupt to occur. During these times, he needs to be able to turn on
the interrupt disable. To accomplish this, the microprocessor has a set
and clear interrupt disable capability.
9.7 SOFTWARE POLLING FOR INTERRUPT CAUSES
As was indicated above, any one of several devices are collector-or'd
to cause an IRQ. The effect of any one of the devices or combination of
them having polled the IRQ line low is always the same. The interrupt
stores the current status of the program counter and processor on the
stack and transfers to a fixed vector address. In servicing the interrupt,
it is important to save those registers which will be used in the
analysis of the interrupt and during the interrupt processing, so the
normal first steps of the interrupt routine are to do the SAVE procedures.
The next operation is to determine which of the various potential
interrupting devices caused the interrupt. To accomplish this, the
programmer should make use of the fact that all interrupting devices
signal the interrupt by a bit in the status register. All currently
implemented 6800 and 6500 peripherals always have interrupt indicators;
either bit 7 or bit 6 in their status register. Therefore, the basic loop
that a user will use to verify the existence of an interrupt on one of
five devices is as follows:
Example 9.5: Interrupt Polling
No. of Bytes Cycles
3 4 LDA Status 1
2 2 BMI FIRST
3 4 LDA Status 2
2 2 BMI SECOND
3 4 LDA Status 3
2 2 BMI THIRD
3 4 LDA Status 4
2 2 BMI FOURTH
3 4 LDA Status 5
2 2 BMI FIFTH
RES1 JMP to RESTORE
FIRST LDA DATA 1
CLI
Process 1
etc.
In this example, the simplest case where the potential interrupts
are indicated by bit 7 being on, has been assumed. This allows advantage
to be taken of the free N-bit test by following the load of the first
status register with a branch on result minus. If the first device has an
active interrupt request, the BMI will be taken to FIRST where the data is
transferred. This automatically clears the interrupt for the first device.
To allow multiple interrupts, the load A is followed by the CLI instruction
which allows the program to accept another interrupt. As a result of the
CLI, one of two things can occur; there is not another interrupt currently
active, in which case, the microprocessor will continue to process the
first interrupt down to the point where the interrupt is complete and the
first subroutine does a jump to RESTORE, which is the routine that unsaves
the registers that were used in the process of servicing the interrupt.
If another device has an active interrupt which occurred either prior
to the first interrupt or subsequent to it but before the microprocessor
has reached the point where the CLI occurs , then the microprocessor will
immediately interrupt again following the CLI, go back and save registers
as defined before and come back into the polling loop. Therefore, multiple
interrupts are serviced in the order in which they are looked at in polling
sequence. Polling means that the program is asking each device individually
whether or not it is the one that requested an interrupt.
It should be noted that polling has the effect of giving perfect
priority in the sense that no matter which two interrupts occur before the
microprocessor gets to service one, the polling sequence always gives
priority to the highest priority device first, then the second, then the
third, etc. In light of the fact that this polling sequence requires no
additional hardware to implement other than is available in the interrupting
devices themselves, this is the least expensive form of interrupt
and the one that should be used whenever possible because of its independence
from external hardware.
Although it would appear that the last interrupting device in a
sequence pays a significant time penalty based on the amount of instructions
to be executed before the last device is serviced, the amount of
time to perform polls is only six cycles per device and, therefore,
the extra penalty that the last device has to pay over the first device
is 24 cycles. This is in comparison to a minimum time to cause an interrupt
(eight cycles) , plus store time for registers (in the range of
another 8 to 13 cycles) which means that the delay to the last devices
is roughly twice what it would be for the first device.
This timing just described represents a most interesting part of the
analysis of interrupts for a microprocessor. There is a significant
amount of fixed overhead which must be paid for the interrupt. This overhead
includes the fact that the interrupts can only occur at the end of
an instruction so, therefore, if an interrupt occurs prior to the end of
an instruction, the microprocessor delays until the end of the instruction
to service it. Therefore, in doing the worst case analysis, one has to
consider the fact that the interrupt might be occurring in the middle of
a seven cycle, read/modify/write instruction which means that the worst
case time to process the first instruction in an interrupt sequence is
14 cycles (7 cycles plus the 7 cycles for the interrupt).
In light of the fact that saving of additional registers is often
required (at least the accumulator A must be saved), at least twice
the number of cycles will be required. Consequently the absolute minimum
worse case time for an interrupt is 17 cycles plus the time to transfer
data which is another 4 cycles. Therefore interrupt driven systems must
be capable of handling a delay of at least 20 cycles and more realistically,
20 to 50 cycles before the first interrupt is serviced. This means that
devices which are running totally interrupt driven must not require successive
bytes of data to be transferred to the microprocessor in less than 30
or 40 cycles and on a given system, only one device is capable of operating
at that rate at one time. This limits the interrupt driven frequency of
data transfer co 40KHZ at a one megahertz clock system and 80KHZ on a two
megahertz clock system.
An even more serious problem is the timing delay when an interrupt
has just started to be serviced. The interrupt mask is on and higher
priority interrupts are blocked from service. In this case, the delay
to the service can easily stretch out to 100 cycles before the interrupt
mask is cleared. This is one of the reasons for clearing up the interrupt
mask as soon as data is transferred. (The non-maskable interrupt
which will be discussed later is one solution to this problem.) A second
is to only use interrupts for systems that have adequate buffering and/or
slower transfer rates. This does not imply that most microprocessor
applications should not be primarily interrupt driven. The MCS650X interrupt
system is designed to be very economical and easy to apply. It should
be used for almost all control applications, other than when the throughput
described is not sufficient to handle the particular problem. It should
be remembered that at one megahertz the fast MCS650X is not really capable
of handling problems with more than 50KHZ byte throughput for a sustained
period of operation. It is also true that in most control applications,
many of the signals occur at much slower rates or are bufferable so that
the response time to a request for service is significantly longer than
the 20 to 50 cycles that can normally be expected with a polling system.
Because of this, it is expected that most applications will be quite
satisfied using the polling technique described above.
9.8 FULLY VECTORED INTERRUPTS
However, there are occasions where several high speed peripherals
can be managed by the microprocessor if the user is willing to make the
investment to attain a truly vectored interrupt. There is a second level
of interrupt vectoring possible by just putting one high priority device
on the non-maskable interrupt line. However, the case when multiple
inputs are desired with both priority encoding and true vectoring, the
MCS650X when combined with appropriate hardware has the ability in the
first polling instruction to transfer control to appropriate interrupting
device service software.
The MCS6520 contains, in its two bytes of memory,
an indirect pointer to the address of the subroutine in which
resides the interrupt processing for the devices, which the priority
encoder has selected. This gives an effective service time of approximately
24 cycles to a prioritized interrupt and is one of the primary
applications of the jump indirect capability.
9.8.1 JMP Indirect
This instruction establishes a new value for the program counter.
It affects only the program counter in the microprocessor and affects
no flags in the status register.
JMP Indirect is a three byte instruction.
In the JMP Indirect instruction, the second and third bytes of the
instruction represent the indirect low and high bytes respectively of the
memory location containing ADL. Once ADL is fetched, the program counter is
incremented with the next memory location containing ADH.
Example 9.6: Illustration of JMP Indirect
Address Data External Internal
Cycle Bus Bus Operation Operation
1 0100 OP CODE Fetch OP CODE Finish Previous
Operation.
Increment PC to 0101
2 0101 IAL Fetch IAL Interpret Instructions
Increment PC to 102
3 0102 IAH Fetch IAH Store IAL
4 IAH, IAL ADL Fetch ADL Add 1 to IAL
5 IAH,IAL+1 ADH Fetch ADH Store ADL
6 ADH, ADL Next OP Fetch Next
CODE OP CODE
9.9 INTERRUPT SUMMARY
There is an interrupt request line (IRQ) that, when low, indicates
one of the devices which are connected to the interrupt request line
requires service. At the beginning of the interrupt service routine, the
user should save, on the stack, whatever registers will be used in his
interrupt processing routine. His program then goes through a polling
sequence to determine the interrupting device by analyzing the status
registers in the order of priority of service for the I/O devices. On
finding a device which requires service, the data for that device should
be read or written as soon as possible and the interrupt disable cleared
so that the microprocessor can interrupt again to service lower priority
devices. Devices with over 40KHz byte transfer, etc., and mixed devices
with over 20KHz should not normally be run interrupt driven. All others
should be run interrupt driven as it minimizes the service time and
programming for interrupt I/O operations.
9.10 NON-MASKABLE INTERRUPT
As is discussed, it is often desirable to have the ability to interrupt
an interrupt with a high priority device which cannot afford to wait
during the time interrupts are disabled. For this reason, the MCS650X has
a second interrupt line, called a Non-Maskable Interrupt. The input
characteristics of this line are different than the interrupt request line
which senses it needs service when it remains low. The non-maskable input
is an edge sensitive input which means that when the collector-or'd input
transitions from high to low, the microprocessor sets an internal flag
such that at the beginning of the next instruction, no matter what the
status of the interrupt disable, the microprocessor performs the interrupt
sequence shown in Example 9.2 except that the vector pointer put out in
cycle 6 and 7 is FFFA and FFFB.
This gives two effects of a non-maskable interrupt. First, no
matter what the status of the interrupt disable, the non-maskable interrupt
will interrupt at the beginning of the next instruction, therefore,
the maximum response time to the vector point is 14 cycles. Secondly, the
internal logic of the MCS650X is such that if an interrupt request and nonmaskable
interrupt occur simultaneously or if the non-maskable interrupt
occurs prior to the time that the vectors are selected, the microprocessor
always assigns highest priority to the non-maskable interrupt. Therefore,
the FFFA and FFFB vector are always taken if both interrupts are active
at the time the vector is selected. Thus the non-maskable interrupt is
always a higher priority fast response line, and can, in any given system
be used to give priority to the high speed device.
It is possible to connect multiple devices to the non-maskable interrupt
line except for the fact that the non-maskable interrupt is edge
sensitive. Therefore, the same logic that allows the IRQ to stay low until
the status has been checked and the data transferred will keep the non-maskable
interrupt line in a low state until such time as the first interrupt
is serviced. If subsequent to the first interrupt of a non-maskable interrupt
line occuring, a second device which is collector-ored would have
turned on its status and collector-or'd output, the clearing of the first
interrupt request would not cause the line to re-initialize itself to the
high state and the microprocessor would ignore the second interrupt. Therefore,
multiple lines connected to the non—maskable interrupt must be carefully
serviced.
In any case, NMI is always one free high priority vectored interrupt.
By virtue of the fact that it goes to a different vector pointer, the
microprocessor programmer can be guaranteed that in 17 cycles he can transfer
data from the interrupting device on the non-maskable interrupt input.
The IRQ and NMI are lines which, externally to the microprocessor,
control the action to the microprocessor through an interrupt sequence.
As is mentioned during the discussion on the start command, the restart
cycle is a pseudo interrupt operation with a different vector being
selected for reset which has priority over both interrupt and nonmaskable
interrupt. Non-maskable interrupt has priority over interrupt.
There is also a software technique which allows the user to simulate an
interrupt with a microprocessor command, BRK. It is primarily used for
causing the microprocessor to go to a halt condition or stop condition
during program debugging.
9.11 BRK - BREAK COMMAND
The break command causes the microprocessor to go through an interrupt
sequence under program control. This means that the program counter
of the second byte after the BRK is automatically stored on the stack
along with the processor status at the beginning of the break instruction.
The microprocessor then transfers control to the interrupt vector.
Symbolic notation for break is PC + 2↓ (FFFE)→PCL (FFFF)→PCH.
Other than changing the program counter, the break instruction
changes no values in either the registers or the flags.
The BRK is a single byte instruction and its addressing mode is
Implied.
As is indicated, the most typical use for the break instruction is
during program debugging. When the user decides that the particular program
is not operating correctly, he may decide to patch in the break
instruction over some code that already exists and halt the program when
it gets to that point. In order to minimize the hardware cost of the
break which is applicable only for debugging, the microprocessor makes use
of the interrupt vector point to allow the user to trap out that a break
has occurred. In order to know whether the vector was fetched in response
to an interrupt or in response to a BRK instruction, the B flag is stored
on the stack, at stack pointer plus 1, containing a one in the break bit
position, indicating the interrupt was caused by a BRK instruction. The B
bit in the stack contains if it was caused by a normal IRQ. Therefore,
the coding to analyze for this is as follows in Example 9.6.
Example 9.7: Break-Interrupt Processing
Cycles Bytes Check for A BRK Flag
4 1 PLA Load status register
3 1 PHA Restore onto Stack
2 2 AND # $ 10 Isolate B Flag
2 2 BNE BRKP Branch to Break Programming
11 6 |
↓
Normal Interrupt Processing
This coding can be inserted any place in the interrupt processing
routine. During debugging, if the user can afford the execution time, it
should be placed immediately after the save routine. If not, it can be
put at the end of the polling routine which gives a priority to the
polling devices as far as servicing the interrupts. However, it should
be noted that in order not to lose the break, the returns from all interrupts
during debugging should go through an equivalent routine.
Once the user has determined that the break is on, a second analysis
and correction must be made. It does not operate in a normal manner of
holding the program counter pointing at the next location in memory during
the BRK instruction. Because of this, the value on the stack for the
program counter is at the break instruction plus two. If the break had
been patched over an instruction, this is usually of no significant
consequence to the user. However, if it is desired to process the next
byte after the break instruction, the use of decrement memory instructions
in the stack must be used.
It is recommended that the user normally takes care of patching
programs with break by processing a full instruction prior to returning
and then use jump returns.
An interesting characteristic about the break instruction is that it's
OP CODE is all zero's (0), therefore, BRK coding can be used to patch
fusable link PROMS through a break to an E-ROM routine which inserts patch
coding.
An example of using the break to patch with is shown below:
Example 9.8: Patching with a break utilizing PROM
Old Code FC21 LDA
FC22 05
FC23 21
FC24 Next OP CODE
Patched FC21 BRK 00
Code FC22 05
FC23 21
FC24 Next OP CODE
The interrupt vector routine points to:
Patch LDA
06
21
JMP
24
FC
This coding substitutes:
LDA 2106
for the
LDA 2105
coding at
FC21
by use of the BEK and a break processing routine.
9.12 MEMORY MAP
A series of requirements were discussed to this point for the
memory organization which can be illustrated by the following memory map:
Hex Address
0000-00FF RAM used for zero page and indirect memory addressing
operation.
0100-01FF RAM used for stack processing and for absolute addressing.
0200-3FFF Normally RAM.
4000-7FFF Normally I/O
8000-FFF9 Program storage normally ROM.
FFFA Vector low address for NMI.
FFFB Vector high address for NMI.
FFFC Vector low address for RESET.
FFFD Vector high address for RESET.
FFFE Vector low address for IRQ + BRK.
FFFF Vector high address for IRQ + BRK.
The addressing schemes for I/O control between locations 4000 and
8000 Hex, have not been fully developed. This is described in detail in
the Hardware Manual, Chapter 2. The Zero Page addressing requires that
RAM should be located starting in location 00. If more than one RAM page
is necessary, RAM location 0100 through 01FF should be reserved for the
stack or at least a portion of parts should be reserved for the stack
with the rest of it being available to the user to use as normal RAM.
Locations from 0200 up to 4000 are normally reserved for RAM expansion.
In small memory configurations such as are inherent in a MCS6530 class device,
in order to minimize the addressing lines, page two (02XX) will be
normally used for input/output as opposed to using the 40XX page which is
used for devices which require significant amount of outboard RAM, ROM
and I/O.
Because of the fact that the MCS650X has three very important vector
points selected in highest order memory, it is usually more useful to
write programs with the memory storage located at a starting address
which allows the programmer to make sure that the last address in his
ROM contains the start and interrupt vectors. Because of these allocations,
the user finds himself working in three directions. RAM is
assigned in location 0000 working up. I/O devices are started at
location 4000 starting up and ROM starts at location FFFF and works down.
Although this seems like an unusual concept, one must remember that the
hardware really only gives performance to either end of memory and,
therefore, data located in the middle has no priority one over the other.
So starting at either end is just as useful a technique as starting at one
end and working up.
In order to take maximum advantage of the capability of the microprocessor,
particularly when using a symbolic assembler, working data
should be located starting in the location 0, and stack addresses should
be reserved until after analysis of the working storage requirements have
been completed. Program storage should start in high order memory with
some guess as to the amount of memory required being taken and that being
taken as a start address. However, care should be taken to assign the
three fixed vectors almost immediately at least symbolically as they are
all necessary for correct operation of the microprocessor.