What exactly is an interrupt?
Asked Answered
D

4

7

I want to understand what exactly an interrupt is for my 6502 work-alike processor project in Logisim. I know that an interrupt does the following steps:

  1. Stops the current program from processing

  2. Saves all unfinished data into the stack

  3. Does "SOMETHING"

  4. Loads back the unfinished data and let's the program keep running normally.

    My question is: what happens during that "SOMETHING" step? Does the program counter get redirected to a special program to be executed? Something like reading the pressed button's ASCII code and saving that into a register or some memory location? If so, where is that special program usually stored in the memory? And can you make such a CPU that will handle different kinds of interrupts? Maybe if you press the button "a" then it's ASCII will be stored in A register, but if you press the button "b" then it will be stored in X register?

Any help is greatly appreciated.

Edit: Thanks to everybody for answers. I learned a lot and now can proceed with my project.

Doriedorin answered 21/3, 2019 at 11:31 Comment(3)
See en.wikipedia.org/wiki/Interrupts_in_65xx_processorsPermeability
Reading and storing (esp. queuing) something in response to an interrupt is a good general concept as an interrupt doesn't convey much information itself, perhaps not even which specific "device" is signaling the interrupt. "Button" and "ASCII code" are undefined in this question. (What a PC CPU reads from a PC keyboard is a "scan code". That wouldn't get mapped to a character code in any particular character encoding until much, much later.)Seismology
Also 6502.org/tutorials/interrupts.htmlWillardwillcox
J
13

My question is: what happens during that "SOMETHING" step? Does the program counter get redirected to a special program to be executed?

What happens with a 6502 maskable interrupt is this:

  • the interrupt is raised (by this I mean the interrupt pin on the chip is forced low.
  • when it's time to execute a new instruction, the 6502 checks if the interrupt pin is low and the interrupt mask in the status register is not set. If either is not thew case i.e. if the interrupt pin is high or the interrupt mask is high, the CPU just carries on.
  • Assuming an interrupt is required, the CPU saves the PC on the stack
  • The CPU then saves the status register on the stack but with the B bit set to 0. The B bit is the "break" bit. It would be set to 1 for a BRK instruction and that is the only way to tell the difference between a hardware interrupt and a BRK instruction.
  • The CPU then fetches the address at locations $FFFE and $FFFF and stuffs it into the PC, so execution begins again at that address.

That's all it does. Everything else is up to the programmer until the programmer executes an RTI, then the status word and the return address are pulled off the stack and restored into their respective registers. It is the programmer's responsibility to save any registers and other data.

Does the program counter get redirected to a special program to be executed? Something like reading the pressed button's ASCII code and saving that into a register or some memory location?

That is correct. In 6502 based computer systems, there are three vectors at the top of memory:

$FFFA - $FFFB : Non maskable interrupt (as above except the I bit in the status register is ignored).

$FFFC - $FFFD : Reset vector used when the CPU detects a reset

$FFFE - $FFFF : Normal interrupt vector.

The above are usually in ROM because the reset vector (at least) has to be there when the CPU powers up. Each address will point to a routine in the machine's operating system for handling interrupts.

Typically, the interrupt routine will first do an indirect jump through a vector stored in RAM. This allows the interrupt routine to be changed when the machine is running.

Then the interrupt routine has to determine the source of the interrupt. For example, on the Commodore PET thew interrupt might originate from the VIA chip or either of the PIA chips and each of those may raise an interrupt for various reasons e.g. one of the PIA chips raises an interrupt when the monitor does a vertical blank i.e. when it finishes scanning the screen and goes back to the top line. During this interrupt, the PET executes a routine to scan the keyboard and another routine to invert the cursor. Another interrupt might occur when the VIA timer hits zero and the programmer can insert an interrupt routine to, for example toggle an output line to generate a square wave for sound.


Some answers to questions in the comments.

program counter goes to address $FFFE to get relocate to the address

No, the program counter is set to whatever is at that address. If you have:

FFFE: 00 
FFFF: 10

the program counter will be set to $1000 (6502 is little endian) and that's where the interrupt routine must start. Also, the vector for NMI is at $FFFA. The normal interrupt shares $FFFE with the BRK instruction, not the NMI.

What exactly the reset vector does? Does it reset the cpu?

The reset vector contains the location of the code that runs after the processor has been powered on or when a reset occurs.

What's the difference between NMI and IRQ? Then I also would like to know what's up with masking? Is it the way to set the "I" flag in Processor Status Register high or low?

The 6502 status register contains seven flags. Mostly they are to do with the results of arithmetic instructions e.g. Z is set if the result of an operation is zero, C is set when an operation overflows eight bits and for shifts. The I flag enables and disables the normal interrupt (IRQ). If it's zero, interrupts on IRQ will be respected. If it's 1, interrupts are disabled. You can set it and disable it manually with the SEI and CLI instructions and it is set automatically when an interrupt occurs (this is to prevent an interrupt from interrupting an interrupt).

NMI is a non maskable interrupt. The difference is that it ignores the state of the I flag and uses a different vector.

And finally, what are vectors? Are they synonymous for indirect addresses?

Yes.

Oh, and if you do know, how are interrupt addresses starting from $FFFA stored in ROM instead of RAM in real 6502?

You have to arrange for the address decoding logic to point those address at ROM instead of RAM. In fact, in Commodore systems the whole block from $F000 is ROM containing part of the operating system. The same probably applies to most other 6502 based systems.

Jovitajovitah answered 21/3, 2019 at 12:44 Comment(11)
Thank you for your fantastic answer! Now I understand that when an interrupt happens (IRQ or NMI), after the data is saved, program counter goes to address $FFFE to get relocate to the address stored there and on that relocated address will be the program that is up for the programmer to write. This is awesome, this is like the universal way of making interrupts.Doriedorin
I have a new questions now tho. I didn't know there were 4 interrupts. I understand the purpose of BRK, but 1) What exactly the reset vector does? Does it reset the cpu? 2) What's the difference between NMI and IRQ? Then I also would like to know what's up with masking? Is it the way to set the "I" flag in Processor Status Register high or low? And finally, what are vectors? Are they synonymous for indirect addresses?Doriedorin
Oh, and if you do know, how are interrupt addresses starting from $FFFA stored in ROM instead of RAM in real 6502?Doriedorin
@Doriedorin The address $FFFA/B is only one from 6502's viewpoint. It can be RAM or ROM.Durnan
This is whole other level stuff, and why I visit SO.Syringe
@Jovitajovitah thank you for all your answers. It's pretty cool how processor uses RESET vector to not mess up turning on. I also stated my first question about Program Counter relocating wrong. I basically meant to ask if vectors work as an inderect pointers, which I did ask later for some reason.Doriedorin
This is a great answer to an often mysterious set of questions. Nice work.Zirkle
If only they had to work with computers during the days of DOS. Installing a DOS game manually by copying the floppy disk onto the hard drive into a specified folder so that you wouldn't flood the root directory. After copying then you would either A: have to call the setup or install file or B: first decompress or extract specific files or a set of files then run the installer. Afterwards, you then had to type the name of the executable for the game to run. You weren't done yet. You had to go into the games settings and set the IRQs, Ports, etc. for your specific video and sound cards...Potbelly
Here the IRQs and their channels for the Sound card and for audio to work properly are your Interrupt Request Channels! And setting the correct ports to make sure they triggered properly! Oh the gold old days with some DOS style DOOM!Potbelly
If the interrupt pin is pulled low but then released before the start of the next instruction, is that ignored? I.e. is there no internal interrupt latch on the 6502?Grimbald
@Grimbald see Appendix A here for further information: 6502.org/tutorials/interrupts.htmlGeaghan
G
4

There are four types of interrupt on the 6502: RESET, NMI, IRQ and BRK. The first three are hardware interrupts and the last is a software interrupt. The hardware interrupts have physical input voltages on pins on the microprocessor itself. The software interrupt is caused by a BRK instruction.

All interrupts are 'vectored'. That means when they occur the program counter (PC) is immediately loaded from an address stored in memory, and instruction execution continues from that address.

The addresses are stored as two bytes little endian format at the end of the 64k memory space. They are (in hex):

NMI     $FFFA/$FFFB 
RESET   $FFFC/$FFFD
IRQ     $FFFE/$FFFF 
BRK     $FFFE/$FFFF

In the case of NMI, IRQ and BRK, the current PC address is pushed on to the stack, before loading the interrupt address. The processor status register is also pushed on to the stack.

Pushing the registers on to the stack, is enough information to resume execution after the interrupt has been serviced (processed). The A, X and Y registers however, are not pushed automatically on to the stack. Instead the interrupt service routine should do this if necessary - and pull them back off the stack at the end of the service.

Notice that the IRQ and BRK vectors have the same address. In order to distinguish what happened in your service code, you need to examine the Break Bit of the pushed processor status register. The Break Bit is set if the interrupt came from a BRK instruction.

The currently executing instruction will always be completed before servicing the interrupt.

There are many subtleties to interrupt processing. One of which is which type of interrupt wins in the case that they happen (asserted) at the same time. Another is the point at which an interrupt occurs during the instruction cycle. If the interrupt occurs before the penultimate cycle of the instruction, then it will be serviced on the next instruction. If on or after the penultimate cycle, then it will be delayed until one instruction after.

IRQ interrupts can be 'switched off' or ignored by setting a bit in the processor status register, using the SEI instruction.

Typically the interrupt service routine needs to determine the cause of the interrupt (disc drive, keyboard etc.) and to make sure the interrupt condition is cleared and perform any processing (e.g. putting key presses into a buffer). It can normally do this by reading/writing specific memory locations which are mapped to hardware.

There is more information at this link: https://www.pagetable.com/?p=410

Some more information on how interrupts work in a real 8 bit machine (pages 59, 86, 295): BBC Microcomputer Advanced User Guide

And more information on the physical chip package where you can see the NMI, RES(ET) and IRQ pins on the chip package itself (pages 2,3): 6502 Datasheet

Geaghan answered 21/3, 2019 at 12:46 Comment(13)
Thank you for your answer. Partially from it and the one written by @Jovitajovitah I now understand how interrupts are executed. I still haven't figured what's the difference between IRQ and NMI is and I didn't understand what are vectors.Doriedorin
The vectors are just memory locations ranging from $FFFA to $FFFF. It doesn't matter if they are ROM or RAM, but usually they're ROM. There will be a machine code routine to service NMIs for example at address $ABCD. In that case the byte at $FFFA will contain $CD and the byte at $FFFB will contain $AB. The masking happens because the Interrupt Disable bit in the PSR can disable or 'mask' IRQ interrupts. NMIs cannot be 'masked' or disabled, hence non-maskable. Only IRQs can be masked not BRK or RESET or NMI.Geaghan
Aha... so you mean, when the IRQ is being processed, when it start's to execute the program (at $ABCD for example), if that program in it has CLI instruction, then the interrupt will be disabled without completing the interrupt program and, basically RTI will be executed? In another words, CLI will work like RTI in the IRQ triggered program, whereas NMI ignores CLI and only stops when processor hits RTI?Doriedorin
The interrupt disable bit is ONLY checked at the point the interrupt happens, not at any point after. Any changes to the I bit are ignored, only RTI will return from the interrupt service, nothing else. EXCEPT if another interrupt occurs inside your interrupt service, but you would normally try to avoid this situation by either making the service routine very short or using CLI.Geaghan
Another subtlety, is that the BRK instruction will actually push PC+1 on to the stack. In other words it's treated as a two byte instruction.The byte after the BRK can have anything you like in it, but the service routine could treat it as an error code or some other type of status.Geaghan
So if you write SEI at some point in program then IRQ can never happen untill CLI occurs later in program, whereas NMI happens indefinitely wheather SEI set "I" flag high or low? If so... if IRQ happens while "I" flag is high then BRK will be executed instead?Doriedorin
@GuillermoPhillips The routine for BRK can use the following byte as software interrupt number like INT xx on x86 systems. I have implemented such system - the soft interrupt (BRK) number is index and there is table with start addresses of corresponding subroutines (system functions). Finally they return to calling program with RTI instead of normal RTS. The positives from this system are 2: system calls need only 2 bytes instead of 3 for JSR and there are no fixed entry point addresses for system function, you call them indirectly by index.Durnan
@Senjis that's right, SEI only works for IRQ and is permanent until CLI is issued. NMI (or RESET) cannot be disabled in any way. SEI will block IRQ, so nothing happens, the next instruction is executed as normal (not BRK happening instead).Geaghan
@Durnan exactly and a good use for it. But it's completely flexible. For example BASIC on a BBC Microcomputer uses it to display error messages to the user.Geaghan
@GuillermoPhillips thank you for taking your time and providing me with so much information. I was stuck on my project unable to find any decent info on interrupts, but I can take on from here complete in on my own.Doriedorin
@Doriedorin I'm glad I could help. Good luck!Geaghan
@GuillermoPhillips with that said I do have one last question haha. What are the benefits of using NMI instead of IRQ? I'm thinking of only using IRQ in my project for any button pressed, but maybe I'll asign one random letter to be bound with NMI routine. Because you can't really change which interrupt a button will trigger after it's done in hardware. Unlike interrupt's program which can be reprogrammed whenever you want since it's software.Doriedorin
If you're using real hardware, then just use IRQ. The service routine should then somehow 'read' the keyboard and work out which key is pressed. The keyboard will also have to be 'de-bounced' (see Google) otherwise you'll get weird effects. If you're just experimenting, then by all means play with NMI too. In reality (see the datasheet), the NMI is edge triggered, i.e. the pin needs to go from 'high' to 'low' to trigger the interrupt. The IRQ pin is level triggered, i.e. it only needs to be 'low' to interrupt. In practice that means IRQ will keep interrupting until it goes 'high' again.Geaghan
D
1

I guess you ask for hardware interrupt (IRQ or NMI). At your step 2 in stack (not in stack register) are stored program counter and flags register. Later you call RTI to resume program execution. The program counter is loaded with start address of "something" which is interrupt subroutine or program to process the interrupt. It has to store A, X, Y registers if need to modify their values and restore them before RTI. The IRQ interrupt can be masked (delayed) with I flag and NMI is non-maskable i.e. it is always processed. They have different addresses for subroutine.

Durnan answered 21/3, 2019 at 12:28 Comment(1)
I have edited "stack register" to "stack", you're right. I wanted to understand what happens during the interrupt. I got my question answered, the interrupt tells Program Counter to go to inderect address $FFFE, there it get's relocated to the direct address which is written by programmer himself and that address has the program that will be executed whenever an interrupt happens.Doriedorin
A
0

An interrupt is the signal to the running processor by means of hardware or software so that the processor will give attention to that action and does the action according to the interrupt message. There are three kinds of interrupt:

  • Internal interrupt :- which include the clock cycle interrupt ,in which cpu has to perform the certain action until the particular time and has to go to perform for the another operation.
  • Software interrupt:- This interrupt is occurred when the problem or errors occurs in the software itself. For example user tries to divide something by zero and error occurs. And there is interrupt.
  • External interrupt:- External interrupt is caused by IO devices for example mouse and keyboards.

Cpu is designed to handle such type of interrupt and resumes the process before the interrupt occurred.

Ade answered 15/6, 2021 at 12:10 Comment(1)
I think you mean "timer interrupt", i.e. the CPU can program a timer to interrupt every 10ms or whatever. The OS might update a "clock" variable to keep track of the time of day in a timer interrupt handler, and usually run the scheduler to see if it should context switch. (If this is a multi-tasking OS!). A "clock cycle" is usually the shortest amount of time anything can take in a CPU, e.g. the latency of one add instruction on a modern CPU. (e.g. a modern x86 CPU's clock can run at up to 4 or 5 GHz). You obviously can't handle interrupts that fast, there'd be no time for anything else.Effects

© 2022 - 2025 — McMap. All rights reserved.