16.6 Enabling/Disabling Interrupts

Note: Traps, such as the address error trap, cannot be disabled. Only IRQs can be disabled.

Each interrupt source can be individually enabled or disabled. One interrupt enable bit for each IRQ is allocated in the Interrupt Enable Control registers (IECn). Setting an interrupt enable bit to one (1) enables the corresponding interrupt; clearing the interrupt enable bit to zero (0) disables the corresponding interrupt. When the device comes out of Reset, all interrupt enable bits are cleared to zero.

The safe method of enabling and disabling peripheral interrupts is to use the __write_to_IEC() macro, which is defined in the device header files. This is helpful because some devices require one cycle of delay for this to take effect, but some require two. A different version of __write_to_IEC() will be generated based on device-specific information.

In addition, the processor has a disable interrupt instruction (DISI) that can disable all interrupts for a specified number of instruction cycles.The DISI instruction can be used in a C program through the use of:

__builtin_disi

For example:

__builtin_disi(16);

will emit the specified DISI instruction at the point it appears in the source program. A disadvantage of using DISI in this way is that the C programmer cannot always be sure how the C compiler will translate C source to machine instructions, so it may be difficult to determine the cycle count for the DISI instruction. It is possible to get around this difficulty by bracketing the code that is to be protected from interrupts by DISI instructions, the first of which sets the cycle count to the maximum value, and the second of which sets the cycle count to zero. For example,

__builtin_disi(0x3FFF); /* disable interrupts */
/* ... protected C code ... */
__builtin_disi(0x0000); /* enable interrupts */

An alternative approach is to write directly to the DISICNT register to enable interrupts. The DISICNT register may be modified only after a DISI instruction has been issued and if the contents of the DISICNT register are not zero.

__builtin_disi(0x3FFF); /* disable interrupts */
/* ... protected C code ... */
DISICNT = 0x0000; /* enable interrupts */

For some applications, it may be necessary to disable level 7 interrupts as well. These can only be disabled through the modification of the COROCON IPL field. The provided support files contain some useful preprocessor macro functions to help you safely modify the IPL value. These macros are:

SET_CPU_IPL(ipl)
SET_AND_SAVE_CPU_IPL(save_to, ipl)
RESTORE_CPU_IPL(saved_to)

For example, you may wish to protect a section of code from interrupt. The following code will adjust the current IPL setting and restore the IPL to its previous value.

void foo(void) {
  int current_cpu_ipl;

  SET_AND_SAVE_CPU_IPL(current_cpu_ipl, 7); /* disable interrupts */
  /* protected code here */
  RESTORE_CPU_IPL(current_cpu_ipl);
}