Interrupt (Overview)


Introduction

Interrupts provide a mechanism for temporarily interrupting one executing program so a more urgent program can execute, and then resume execution of the first program.

If some special process needs to be conducted because of the state of the system or hardware, the only way to implement that process—if interrupts are not employed—is to check the status periodically (polling) to look for an opportunity. But if interrupts are used, a program that has been prepared for a set of conditions can be executed immediately when those conditions arise. The interrupt mechanism provides more immediacy than polling, and it lets the main program devote itself to its own processes.

This page explains the functions that handle interrupts.


Interrupt Causes

A variety of events can cause interrupts, and the causes differ for the ARM9 and the ARM7. Below is a list of of interrupt names and their causes on the ARM9.

OS_IE_V_BLANK V blank interrupt
OS_IE_H_BLANK H blank interrupt
OS_IE_V_COUNT V counter interrupt
OS_IE_TIMER0 Timer0 interrupt
OS_IE_TIMER1 Timer1 interrupt
OS_IE_TIMER2 Timer2 interrupt
OS_IE_TIMER3 Timer3 interrupt
OS_IE_DMA0 DMA0 interrupt
OS_IE_DMA1 DMA1 interrupt
OS_IE_DMA2 DMA2 interrupt
OS_IE_DMA3 DMA3 interrupt
OS_IE_KEY Key interrupt
OS_IE_CARTRIDGE Game Pak IREQ/DREQ interrupt
OS_IE_SUBP ARM7 interrupt
OS_IE_SPFIFO_SEND ARM9-ARM7 send FIFO empty interrupt
OS_IE_SPFIFO_RECV ARM9-ARM7 receive FIFO not-empty interrupt
OS_IE_CARD_DATA Card data transfer end interrupt
OS_IE_CARD_IREQ Card IREQ interrupt
OS_IE_GXFIFO Geometry command FIFO interrupt

Registers and Work Regions Associated With Interrupts

The reg_IME (0x04000208) register functions as the master enable/disable flag—setting all interrupts. When the bit is 1, all interrupts are enabled. When the bit is 0, all interrupts are disabled.

 

The I/O register, reg_IE (0x04000210), specifies which causes are allowed to generate interrupts. When the bit for a cause is set to 1, it is permitted to generate an interrupt.

 

Each bit in the Interrupt Request register reg_IF (0x03000214) takes the value 1 when the corresponding interrupt gets generated. The relation between interrupts and bits is the same as that for the reg_IE register.

 

The ARM9 processor's Current Program Status Register (CPSR) has a bit that defines whether IRQs are enabled. (See System (overview)for details.) IRQs are disabled when the I flag of this register is 1 and are enabled when the bit is 0.

 

Check-flag regions are set up so the interrupt handlers can check things out when interrupts are generated. These regions are located in DTCM. The relation between interrupt causes and bits is the same as that for the reg_IE register.

 

Interrupts are a kind of processor exception. When an interrupt occurs, the system jumps to the address stored in the interrupt vector HW_INTR_VECTOR_BUF. The address for the OS IRQ handler is usually stored here, but you can overwrite the value if you want to use your own interrupt routine. This region is also located in DTCM.

 


Process Flow For an Interrupt

The interrupt signal from a device or elsewhere reaches the processor through the flow depicted below:

 

If the specified device has been configured so the IF flag is set when an IRQ is generated, then the corresponding IF bit will take the value 1 when an IRQ is generated and fully satisfies the device's IRQ conditions. (This is not related to the register settings for interrupts that were mentioned above.)

An interrupt will not be generated if the interrupt cause associated with that standing IF flag bit has not been set in the IE register. An interrupt will also not be generated if the IME master enable flag has been set to disable all interrupts. If none of these conditions exist the interrupt signal will reach the ARM9 processor, but an IRQ interrupt still will not be generated if the CPSR's IRQ flag is set to 1 (disable). However, if the CPSR's IRQ flag is set to 0, an IRQ interrupt will be generated.

IRQ interrupts are a kind of ARM processor exception (called an IRQ exception). For details, see Exceptions (overview).

When an IRQ interrupt is generated, the ARM9 processor interrupts the program and jumps to 0xFFFF0018. Take a look at the flow shown below.

 

After the process jumps to 0xFFFF0018, control is transferred to the address stored in HW_INTR_VECTOR_BUF in some region of DTCM. The address for the OS IRQ handler is usually stored here, so overwrite HW_INTR_VECTOR_BUF if you want to create your own IRQ handler. The user's preregistered interrupt handler is called from inside the IRQ handler. After that, the program starts again from the address where the interrupt occurred. (Actually, the thread can also switch. See Threads (overview).)

Following is a more detailed description of the processes inside the OS IRQ handler.

 

Once inside the handler, the process first checks whether the IME register enables interrupts and returns without doing anything if the answer is "No." Otherwise, the next step is to perform a logical AND on the IE and IF bits. If the result is 0, the process returns without doing anything. Otherwise, the process continues by calling the interrupt handler corresponding to the bit that is 1. The IME, IE, and IF bits are checked because it is possible for an interrupt signal to make it to the processor while some process is accessing the I/O register and making changes to prohibited interrupts and the causes of interrupts. These checks thus ensure that the settings in the I/O register are correctly followed.

The interrupt handler called is one that has already been registered in the IRQ table by the user. This table is referenced from the IRQ handler to determine the address of the user's interrupt handler.

After the process comes back from the user's interrupt handler it returns to the user program. However, if a thread-switch event occurs inside the interrupt handler, thread rescheduling occurs (see Threads (overview)).

Set a check flag for the interrupt inside the user's interrupt handler. This check flag is used by other OS functions. If these functions will not be using the check flag, it does not need to be set. However, we recommend that you set it anyway so it is there just in case later changes require its presence. (See OS_SetIrqCheckFlag().)


Enabling/Disabling Interrupts

These functions can be used to control the master enable flag for all interrupts:

OS_EnableIrq(), OS_DisableIrq(), OS_RestoreIrq()


Enabling/Disabling System State Interrupts

For details, see System (overview). These functions are "system" category functions, not "interrupt" category functions. They can be used to change the CPSR status.

OS_EnableInterrupts(), OS_DisableInterrupts(), OS_RestoreInterrupts()


Configuring Interrupt Causes

The following functions can be used to set the causes of interrupts:

OS_SetIrqMask(), OS_GetIrqMask(), OS_EnableIrqMask(), OS_DisableIrqMask()


Controlling Interrupt Request Flags

The following functions can be used to control interrupt request flags:

OS_ResetRequestIrqMask(), OS_GetRequestIrqMask()


Configuring Interrupt Handlers

The following functions can be used to set interrupt handlers:

OS_InitIrqTable(), OS_SetIrqFunction(), OS_GetIrqFunction()


Controlling the Interrupt Check Flag

The following functions can be used to control the interrupt check flag:

OS_SetIrqCheckFlag(), OS_ClearIrqCheckFlag(), OS_GetIrqCheckFlag()


Waiting for Interrupts

The following functions are designed to wait until an interrupt occurs:

OS_WaitIrq(), OS_WaitAnyIrq(), OS_WaitInterrupt()

The arguments in OS_WaitIrq() and OS_WaitInterrupt() specify which interrupt to wait for. In contrast, OS_WaitAnyIrq() is designed to wait for any interrupt to occur.

OS_WaitIrq() and OS_WaitInterrupt() differ in the way they operate while waiting for an interrupt. OS_WaitIrq() switches the context and transfers the process to another thread, while OS_WaitInterrupt() stops when OS_Halt() is called, so no thread switching occurs. If you are not using the thread system, both functions behave the same way.

The SVC_WaitVBlankIntr() function is available to wait for a V blank in a system call.


The V-Blank Counter

The following function is available to get the V-blank counter value used for V-blank interrupts:

OS_GetVBlankCount()

V-blank interrupts are always enabled in the ARM7, so this function internally writes the number of interrupts in the shared region of main memory. The ARM9 command reflects the value written in the shared region.

 

See Also

List of OS Functions (Interrupts)

Revision History

11/17/2004 Initial version