Interrupts are a very important part of a computer system, they allow a CPU to be notified when something needs attention. Before I explain how interrupts work on the 6502, I want to explain what an interrupt is, an alternative and why I will be using interrupts.
When you perform an action (such as pressing a key on a keyboard), you need a way of telling the CPU what has happened and that something should be done about it. Interrupts work by letting the CPU do what it needs to and only alerts the CPU to something happening at the point of time that it happens – it interrupts the CPU. If this is an infrequent action (which pressing a key on a keyboard is), then interrupts are a suitable method.
An alternative to interrupts is polling. Polling is a method where the CPU continuously monitors a piece of hardware, to see if it needs attention. This is a good method for something that needs regular attention but a poor method for something that is used infrequently, as it is a waste of CPU cycles.
A good analogy is a doorbell. Imagine that a friend has said that they will visit you one evening but couldn’t give you an exact time. There are two things that you could do until they arrive. You could keep going to the front door to check if they are there, which isn’t good time management. Or you could carry on with what you are doing until the doorbell goes. Constantly checking is like polling. The doorbell is like an interrupt. If you kept on checking the door, you wouldn’t get anything done. Polling a keyboard to see if a keyboard needs attention would mean that the CPU wouldn’t get anything done!
Interrupts can be broken down into either hardware or software interrupts. I am concerned with hardware interrupts and this is what I will be implementing. Hardware interrupts can be broken down further, into maskable and non-maskable interrupts. A maskable interrupt is one that doesn’t force the CPU to stop, usually because it isn’t considered important. In contrast, a non-maskable interrupt is one that will stop the CPU from doing its current task, usually because it is important. The 6502 allows for both maskable and non-maskable interrupts.
Interrupts stop the CPU from doing its current operation, carries out a new operation and then returns to what it was doing.
For an interrupt to occur I need a way of triggering an interrupt and then some code that runs when the interrupt has been triggered. The 6502 had 2 ways of triggering an interrupt – IRQ (pin 4) and NMI (pin 6). Currently, I have both of these tied to 5V because they are active low and I was not using any interrupts. There are 2 vector locations for these interrupts: FFFE for the IRQ and FFFA for the NMI. These are locations where I can place code to tell the 6502 what to do, when triggering one of these interrupts. So I will write some code to test out these interrupts. To test the IRQ I will connect a button from IRQ (pin 4) to ground, with a pull-up resistor to 5V. This means that the IRQ pin will remain low but when the button is pressed, it will go high. It should then trigger my code. As can be seen, pressing the button did not do anything! This is because IRQ is disabled and needs to be enabled in software. IRQ is enabled by clearing the I flag needs to be cleared. To clear the I flag an OpCode is used, CLI (CLear Interrupt). This is not required for NMI, as it is not optional!
The 6502 offers two interrupts. These are IRQ (Interrupt ReQuest) and NMI (Non-Maskable Interrupt). I plan on using the IRQ but not the NMI.
Even though I am not using the NMI (pin 6), it cannot be left unconnected. Since it is an active low connection, I will need to connect it to the positive rail. IRQ (pin 4) is also an active low connection and therefore needs to be connected to the positive rail, so that it is not active when not in use. Then, when needed, it needs to be brought low. I will use a 3.3KΩ resistor for R1. See Figure 1.
Eventually, I want to connect various input and output devices. This is why I will need to deal with interrupts.