Separated by a common vocabulary
Embedded systems developers use so many terms in so many different ways, it's surprising that we understand each other as well as we do.
England and America are two countries separated by a common language.
--George Bernard Shaw
In my September column, I explained that an interrupt vector is a memory-mapped object, which you can model using techniques similar to those you can use for other memory-mapped objects.1 A number of readers subsequently wrote to me to explain that I was confusing the term interrupt vector with interrupt vector table.
I had written that an interrupt vector is a collection of pointers to ISRs (interrupt service routines). Those readers suggested that it's more common to use interrupt vector to refer to a single pointer to an interrupt handler, and to use the term interrupt vector table to refer to the collection of pointers. One reader referred me to the online encyclopedia Wikipedia to support this claim.2
In my November column,3 I carefully examined the Wikipedia definition and compared it with the definition from Ganssle's and Barr's Embedded Systems Dictionary.4 I concluded that the Wikipedia definition was badly worded. However, the G&B (Ganssle and Barr) definition, while better, doesn't really define interrupt vector as I believe programmers actually understand the term.
This month, I'll explain why neither G&B's nor Wikipedia's definition actually describes interrupt vectors as they are implemented in popular architectures such as the Intel 8051, the ARM, or the PowerPC.
Why you should care
Before I address any specific technical issues, I ought to explain why I think it's worth spending a little time trying to pin down this terminology. My reason is simple: miscommunication can be costly. It can waste time and money, raise stress levels, and cause accidents leading to injury or death.
Interrupt handling is among the more crucial aspects of real-time embedded systems. It can be very hard to get right. One of the best ways to validate designs based on interrupt handling is to talk them through with a colleague or two, whether or not as part of a formal review process. If, during our discussions, I were to say "interrupt vector" thinking it's a pointer, but you thought I was talking about an index into a table, we could mislead ourselves into thinking we agree about something when we really don't. This could delay finding flaws in the design.
Interrupt handling is hard enough even when everyone talks about it using the same vocabulary. We don't have to make it harder by talking at cross purposes.
Interrupts vs. exceptions
Over the past few months, I've looked at numerous books, articles, and manuals to see how they use the term interrupt vector. I expected some disagreement, but was surprised by how much more I found.
Some manuals use the term exception instead of interrupt. According to G&B, an interrupt is "an asynchronous electrical signal from a peripheral to the processor," whereas an exception is "a detected error condition" and that "exceptions typically cause the equivalent of a software interrupt." Depending on the machine, hardware exceptions might result from invalid instructions, invalid addresses, arithmetic overflow or underflow, privilege violations, or any of a variety of other sins that the CPU recognizes as it executes instructions. G&B observe that "hardware exceptions are generally termed traps," which sounds right to me.
Many hardware platforms use much of the same circuitry for handling both interrupts and hardware exceptions. (I'm not concerned here about what part of that circuitry is in the processor, in the interrupt controller, or in peripheral controllers. In this discussion, it's all just hardware.) Consequently, it's not uncommon for hardware documentation to use the term exception to refer to any event that disrupts the normal flow of execution, be it an interrupt, an error, or some other (non-erroneous) event such as a software interrupt or system reset. This appears to be the practice in some manuals from ARM and Freescale (formerly Motorola).
For example, the ARM Evaluator 7-T single-board computer uses a Samsung chip built around the ARM7TDMI core. The processor reference manual uses the more general term exception in preference to interrupt, and uses exception vector instead of interrupt vector, and exception handler instead of interrupt handler.5 Documentation for the Freescale (Motorola) 68K family appears to do so as well.6
The problem with using the word exception in this context is that the same word has similar but different meanings in various high-level languages and operating systems. For example, the Ada, C++, and Java languages each have their own notions of exceptions and exception handlers. You have to be very careful if you use the same terms to describe both language-level and hardware-level facilities. I prefer to limit my use of the term exception to software (programming language and operating system) events, and use the term interrupt for hardware events. When I need to be more specific, I'll distinguish the different kinds of interrupts as device interrupts, software interrupts, or traps.
Mapping a table of instructions into a table of pointers
In my earlier column on modeling interrupt vectors,1 I used the ARM processor to illustrate how you can use C to model interrupt vectors that are pointers. In fact, the interrupt vectors on the ARM are instructions, not pointers. Yet the code I used in my example does work on the ARM Evaluator-7T board. The code works because the firmware on the board employs an interrupt vector table of pointers (the "secondary" table) in addition to the actual interrupt vector table with instructions (the "primary" table) used by the hardware.
The primary interrupt vector table resides at location 0 in memory. The secondary table resides at location 0x20. The firmware initializes the primary table with:
Each load instruction in the primary table loads the program counter with the address in the corresponding position in the secondary table, thus causing a branch to that address. Programs running on this board can ignore the primary table and work entirely with the handler addresses in the secondary table.
C and C++ don't do well manipulating machine instructions, but they do just fine with function pointers. It's much easier for C and C++ programs to manipulate the secondary table of pointers than to manipulate the primary table of instructions. If your application can tolerate the small performance hit, it's a good approach.
The concept of interrupt number appears to be nearly universal across hardware platforms, although the terminology is hardly so.
A few hardware platforms route all interrupts (including software interrupts and traps) to a single interrupt handler. In that case, the lone handler has to do detective work (usually by probing various control registers) to determine which specific event triggered the interrupt so the handler can take action appropriate to that event.
Most platforms let you (possibly even compel you to) write multiple handlers. They map each interrupt signal into an integer value called the interrupt number. The processor then selects the interrupt handler by using the interrupt number as an index into the interrupt vector table. Some interrupts may map to the same interrupt number, and thus invoke a common handler. Other interrupts may be assigned a unique interrupt number, and thus can invoke a handler responsible only for that particular interrupt.
In some platforms, the interrupt number for each interrupt is determined solely by the hardware. Other platforms let you choose that number via software that sets values in certain control registers. For example, the ARM processor core on the Evaluator-7T supports eight interrupt numbers, 0 through 7. The board provides numerous peripheral devices, each of which can be programmed to use either interrupt number 6 (plain IRQ interrupts), or interrupt number 7 ("fast"FIQ interrupts), or no interrupt at all.
G&B don't provide a definition for interrupt number. However, they define interrupt type as "a unique number associated with each interrupt." Most of the manuals I've looked at recently employ the concept of interrupt number, and some even call it such. I've seen no documents other than G&B's dictionary that use the term interrupt type as they do.
Interrupt vector tables and interrupt vectors
I got started down this path when some readers informed me that I was using the term interrupt vector to describe what is more commonly called an interrupt vector table. Some colleagues agreed with me that an interrupt vector is a collection of pointers, rather than just one pointer. Apparently, so does the Dictionary of Scientific and Technical Terms, which defines an interrupt vector as "a list comprising the locations of various interrupt handlers."7 Nonetheless, after looking at numerous books, articles, and reference manuals, I'm persuaded that interrupt vector table is the more common name for the collection, and that's the one I'll use.
Most published definitions for interrupt vector more-or-less agree with G&B that it's "the address of an interrupt service routine." However, I'm not prepared to accept that an interrupt vector is just a pointer. On some processors it is, but on others it clearly isn't.
For example, on the ARM and Xilinx MicroBlaze processors, each interrupt vector contains a single machine instruction. When an interrupt with interrupt number n occurs, the processor responds by executing the instruction in the nth position of the interrupt vector table. That instruction is typically a branch instruction that transfers control to the start of an interrupt handler.
On the PowerPC, each interrupt vector is a 256-byte block of memory capable of holding many machine instructions, possibly even an entire handler. IBM's PowerPC Operating Environment Architecture manual is quite clear that an interrupt vector is not a pointer, but a chunk of code:
Associated with each kind of interrupt is an interrupt vector, which contains the initial sequence of instructions that is executed when the corresponding interrupt occurs.8
The interrupt vector table on the Intel 8051 is similar to that on the PowerPC, but each block of code is only 8 bytes long. However, Intel's 8051 processor reference manual never speaks of an interrupt vector table.9 It simply refers to each block as an interrupt service routine.
I think it's a mistake to define interrupt vector as just "a pointer to a handler" when that's not the way it is on so many popular architectures. Embedded systems developers would be better served by a definition that acknowledges that an interrupt vector might be code rather than data. However, before we can craft a more comprehensive definition for interrupt vector, we should consider yet another take on this woefully overloaded term.
Intel's curious usage
In my previous column, I criticized the definition from Wikipedia (as of October 2006) as being poorly worded. That definition said, in part, "An interrupt vector is the memory address of an interrupt handler, or an index into an array called an interrupt vector table . . ." The part before the "or" is essentially the same as G&B's definition, and I had no problem with that. However, after carefully parsing it, I decided that the part after the "or" was poorly worded at best. I felt confident in that position because G&B noted that using interrupt vector to refer to the interrupt type or interrupt number is incorrect.
Reader Ian Okey disagreed. He wrote:
When designing processor boards back in the 1980s I used the 8086, '186 and '386 together with the 8259 interrupt controller and 8274 serial port controller devices. Both of these devices provided vectored interrupt support by providing the processor with an interrupt vector on the processor bus. This value was the index into the table of addresses held in the interrupt vector table. The data sheet for the 8259 device states that "When an interrupt is acknowledged the highest priority request is determined and its vector placed on the bus."
(You can find his letter in its entirety in the Parity Bits section of the January 2007 issue or online at the bottom of my November column, along with other reader comments.)
I found a recent online copy of the datasheet for the Intel ICH6 family (which includes the 8259).10 It indeed contains the cited sentence. Although the document never explicitly defines what an interrupt vector is, it's pretty clear from context throughout the document that it means "an integer value that identifies an interrupt signal"--an interrupt number. This is the usage that G&B claimed is incorrect, and I concurred.
The ICH6 datasheet doesn't specify the layout and contents of the interrupt vector table. For that, I looked in a recent Intel software developer's manual.11 That manual is fairly explicit about what an interrupt vector is. At one point it says:
To access an interrupt or exception handler, the processor first receives an interrupt vector (interrupt number) from internal hardware, an external interrupt controller, or from software by means of an INT, INTO, INT 3, or BOUND instruction.
Elsewhere it says:
The interrupt vector provides an index into the IDT.
The IDT is the interrupt descriptor table. Apparently, with this processor family, the interrupt vector table is called the IDT when the processor is operating in protected mode. It's called the interrupt vector table only when the processor is operating in real mode.
Ian Okey's letter led me to realize that the second part of Wikipedia's definition for interrupt vector is not as badly worded as I thought; it's just acknowledging Intel's uncommon usage. Thanks Ian. G&B can say this usage is incorrect, and I can agree, but it's unlikely that this usage will disappear on our say so.
I believe Intel's choice of terminology is unfortunate. When programmers and engineers talk about an X table, they usually mean "a table containing X's," not "a table indexed by X's." (You might find a few contrary examples using associative arrays, but that's why I said "usually.")
Intel's own documentation has trouble using the term interrupt vector consistently. For example, the x86 software developer's manual repeatedly uses the phrase interrupt vector number, which I see as an acknowledgement that interrupt vector by itself can easily be misunderstood to be something other than a number.11
The ICH6 datasheet says: "Poll mode can be used to conserve space in the interrupt vector table. . . . The polling interrupt service routine can call the appropriate service routine, instead of providing the interrupt vectors in the vector table."10 This seems to suggest that the interrupt vector table contains interrupt vectors. It does if you define interrupt vector as most of us understand it, but not if you define it as Intel's datasheet does.
So now what?
I still plan to propose a more accurate and comprehensive definition for the terms interrupt vector and interrupt vector table, but not just yet. The feedback from my last column clued me in to some issues I had overlooked. I'm going to wait for more feedback before proposing new definitions.
In the meantime, please remain aware of just how often embedded developers attribute different meanings to the same terms. In any exchange of technical information, you should be on the alert for misunderstandings of even the most basic terminology.
Thanks to Norton Allen, Jack Ganssle, Bill Gatliff, Nigel Jones, and Joel Saks for their help with this article.
Dan Saks is president of Saks & Associates, a C/C++ training and consulting company. For more information about Dan Saks, visit his website at www.dansaks.com. Dan also welcomes your feedback: e-mail him at firstname.lastname@example.org. For more information about Dan click here .
3. Saks, Dan. "Coming to terms with interrupt vectors and tables," Embedded Systems Design, November 2006, p. 11.
6. Motorola M68000 Family Programmer's Reference Manual. Motorola, Inc., 1992. Available at: www.freescale.com/files/archives/doc/ref_manual/M68000PRM.pdf
7. McGraw-Hill Dictionary of Scientific and Technical Terms. McGraw-Hill, 2003. Cited at www.answers.com/topic/interrupt-vector.
8. PowerPC Operating Environment Architecture, Book III, Version 2.02. IBM Corp., January 2005. Available at: www-128.ibm.com/developerworks/eserver/library/es-archguide-v2.html
10. Intel I/O Controller Hub 6 (ICH6) Family Datasheet. Intel Corp., January 2005. Available at: http://support.intel.com/design/chipsets/datashts/30147302.pdf
11. Intel 64 and IA-32 Architectures Software Developer's Manual, Volume 3A: System Programming Guide, Part 1. Intel Corp., November 2006. Available at: www.intel.com/design/processor/manuals/253668.pdf
Let me first define my terms (!), so that what I'm going to say might be clear. An event occurs, and it is either an interrupt (in the hardware), or an exception (in the software). The hardware (uP or interrupt controller--whatever) has to determine the source of this event. This will *always* result in a number--the interrupt number. This number is then used, by various means, to evoke a response from the processing engine. It's the way the number is used that appears to differ, but really it's only a question of whether the conversion from number to code is done via a table, a calculation or some other 'magic' process, and as you say, it's then a question of the words we use to describe the steps and artefacts in that conversion process.
The process will be one of the following (there may be others, but the last one will cover most options):
- Use the number as an index into a table. At that entry in the table is an address. Run the code at the address.
- Use the number as an index into a table. At that entry in the table is code. Run the code.
- Use the number as a reference to a device. Ask the device for an address. Run the code at the address.
- Perform magic on the number to create an address. Run the code at the address.
In the above, one could consider (2) to be the same as (1), but with the indirection step performed in hardware rather than via a table. (3) effectively uses an extra level of indirection, but somewhere there has to be a table or calculation that tells the interrupt processing engine where to find the device associated with the interrupt number. And (4) could cover any of the other three, and is there to catch the processes I missed.
So to get back to the original problem of what the words mean and why they might mean different things to different engineers: I believe the problem is rooted in the fact that the steps in the process are, depending on processor & peripheral choice, sometimes more and sometimes less visible to the software, but the software community (of which I consider myself a part) has tried to use the same terminology regardless.
And finally, an opinion or two.
'Vector' to me implies indirection. So there is only an interrupt vector table when there is a list of addresses, each of which points at some code to run in response to the interrupt (the interrupt service routine, or ISR). The interrupt vector is then the address in that table, and the interrupt number is used to find the interrupt vector in the interrupt vector table. If the interrupt system works like the PowerPC then there is no interrupt vector, and no interrupt vector table, *in the software* (you might find them in the hardware, if you look in the right place...). Nevertheless the code still 'vectors' to the ISR in response to the event.
So. Has that cleared the waters, or just muddied them further?
Principal Software Engineer