An interrupt is an event in hardware that triggers the processor to jump from its current program counter to a specific point in the code. Interrupts are designed to be special events whose occurrence cannot be predicted precisely (or at all). The MSP has many different kinds of events that can trigger interrupts, and for each one the processor will send the execution to a unique, specific point in memory. Each interrupt is assigned a word long segment at the upper end of memory. This is enough memory for a jump to the location in memory where the interrupt will actually be handled. Interrupts in general can be divided into two kinds- maskable and non-maskable. A maskable interrupt is an interrupt whose trigger event is not always important, so the programmer can decide that the event should not cause the program to jump. A non-maskable interrupt (like the reset button) is so important that it should never be ignored. The processor will always jump to this interrupt when it happens. Often, maskable interrupts are turned off by default to simplify the default behavior of the device. Special control registers allow non-maskable and specific non-maskable interrupts to be turned on. Interrupts generally have a "priority;" when two interrupts happen at the same time, the higher priority interrupt will take precedence over the lower priority one. Thus if a peripheral timer goes off at the same time as the reset button is pushed, the processor will ignore the peripheral timer because the reset is more important (higher priority).
The function that is called or the particular assembly code that is executed when the interrupt happens is called the Interrupt Service Routine (ISR). Other terms of note are: An interrupt flag (IFG) this is the bit that is set that triggers the interrupt, leaving the interrupt resets this flag to the normal state. An interrupt enable (IE) is the control bit that tells the processor that a particular maskable interrupt should or should not be ignored. There is usually one such bit per interrupt, and they are often found together in a register with other interrupt enable bits. The most important interrupt on MSP430 is the reset interrupt. When the processor detects a reset or powers up for the first time, it jumps to the beginning of memory and executes the instructions there. The highest priority interrupt vector begins at the address 0xFFFE. The lowest priority interrupt begins at 0xFFE0. The complete set of interrupts is ranked by priority:
When the interrupt first occurs on the MSP there is a precise order of events that will occur. This process takes 6 instruction cycles AFTER the current instruction completes.
The interrupt service routine is the code that the programmer writes to take care of the work that needs to be done when a particular interrupt happens. This can be anything you need it to be. Because entering the interrupt turned off the GIE bit, you will not receive any interrupts that happen while you are still in the interrupt service routine. You can turn the interrupts back on if you need to receive interrupts during your interrupt, but usually it is a better idea to make interrupt service routines shorter instead. In C interrupts are simply functions with special declarations. You never call these functions; the compiler simply sets up the interrupt vector table to call your function when the particular interrupt occurs.
This example interrupt is pulled from the msp430x20x3_wdt_01.c example file by Mark Buccini. The complete file can be found on the Ti-ez430 homepage.
// Watchdog Timer interrupt service routine
#pragma vector=WDT_VECTOR
__interrupt void watchdog_timer(void)
{
P1OUT ^= 0x01; // Toggle P1.0 using exclusive-OR
}
Interrupt functions should always be void and accept no arguments. This particular interrupt service routine (ISR) is called watchdog_timer, but the name does not matter. The way the compiler knows that this function should handle the watchdog timer interrupt is what follows the function name. the #pragma vector = indicates that this is an interrupt and WDT_VECTOR is a macro from the MSP header file that indicates the interrupt vector being used. Every interrupt vector in the processor has a macro defined for it (which can be found in the header file). To attach this interrupt service routine to a different interrupt, all you need to do is change the WDT_VECTOR to one of the other macros defined in the ez430 header file.
When the end of the ISR is reached the MSP executes a precise set of steps to pick up the execution of the program where it left off before the interrupt occurred. This process takes 5 cycles.
Using interrupts successfully is not as simple as just writing an interrupt service routine and waiting for the event to occur. Because you do not necessairly want to activate every interrupt in the processor at once, the MSP allows you to mask out certain interrupts. When the triggering event first occurs, the processor checks whether the interrupt is enabled before jumping to the interrupt service routine. For most interrupts, the MSP checks the general interrupt enable bit in the status register and the particular interrupt’s enable in the interrupt enable registers. If both of these have been configured to allow the interrupt, then the processor enters the interrupt service routine if the event in question has occurred.
By default most interrupts are turned off upon reset. To use most peripheral modules you will need to set the enable bits in the interrupt enable registers and turn on the general interrupt enable. Enabling sometimes causes the interrupt flag to be set, so you should consult the User’s guide on the best order to handle the enabling. Usually to properly configure the interrupt, you will also need to have set up the peripheral module in question before enabling the interrupt.
There are three categories of interrupts for the purpose of masking in the ez430. Reset interrupts, non-maskable non-reset interrupts, and maskable interrupts.
Maskable interrupts are the lowest priority interrupts and can be turned off individually with the various interrupt enable registers or turned off as a group by setting the general interrupt enable bit (GIE) in the status register (SR).
Non-maskable interrupts are not subject to the general interrupt enable (GIE). However each non-maskable interrupt source can be controlled by a bit to specifically turn it on or off. These are the flash access violation interrupt enable (ADDVIE), external NMI interrupt enable (NMIIE), and the oscillator fault interrupt enable (OFIE). All three of these bits are located in the interrupt enable register 1 (IE1).
Reset interrupts have the highest priority and will always reset the execution of the device. The external reset can be configured to trigger either the reset interrupt or an NMI interrupt.
The interrupt enable registers (IE1 and IE2) are used to individually enable the interrupts. Refer to the ez430's User’s Guide and Data sheet for the specifics of each peripheral. The example code on Ti's website are also very helpful when learning how to use interrupts. The procedures followed are drawn from the instructions and notes in the documentation. Often the relevant information may not be in one chapter or section of the guides. This is part of the reason working examples are essential to developing a working knowledge of the processor.
More detailed information on the operation of interrupts can be found in the MSP User’s Guide. Unfortunately the material is generally found in the chapter for each subsystem. The general interrupt information is found in chapter 2.
"A basic introduction to interrupts and their uses. An example uses the F2013 chip."