PIC32MX Exception Entry Points

Last modified by Microchip on 2023/11/10 11:07

The Reset, Soft Reset, and NMI exceptions are always vectored to location 0xBFC00000 (uncached, start-up safe KSEG1 region). Addresses for all other exceptions are a combination of a vector base address and a vector offset.

Exception Vector "Base" Addresses

In MIPS32® Release 2 and higher architectures, the software is allowed to specify the vector base address via the CP0 Ebase register for exceptions that occur when CP0 StatusBEV equals 0.


MIPS32 architectures provide a "bootstrap" mode (referred to as Boot-Exception Vector (BEV) mode) whereby exception entry points are reallocated into the uncached, start-up-safe KSEG1 region.

Bootstrap mode is controlled by the CP0 Status register flag StatusBEV

  • StatusBEV = 1: Exceptions vector to an uncached entry point in KSEG1: 0xBFC00xxx
  • StatusBEV = 0: Exceptions vector to cached entry points in KSEG0: defined by CP0 Ebase register, plus some offset


StatusBEV = 1 at reset.

The following table gives the vector base address as a function of the exception and whether the BEV bit is set in the Status register:

Exception vector base addresses

MPLAB® XC32 start-up code initializes Ebase to the value defined by the symbol _ebase_address in the PIC32MX device linker script (for PIC32MX795F512L, _ebase_address = 0x9FC01000).

If Ebase is to be changed, it must be done with StatusBEV = 1 (i.e. at system boot). The operation of the CPU is UNDEFINED if Ebase is written when StatusBEV = 0.

Back to top

Vector "Offsets"

Next, we have fixed vector offsets, which are added to the above exception base addresses as a function of the exception:

Exception vector offsets


Setting the CP0 CauseIV bit to 1 causes Interrupt exceptions to use a dedicated exception vector offset (0x200), rather than having to use the general exception vector offset (0x180).

MPLAB XC32 start-up code initializes CauseIV to 1.

Back to top

"Final" Entry Point Addresses

PIC32MX interrupt exception vector addresses have an additional computed offset component, which is added to Ebase and the fixed offset (0x200).

  • Computed Offset = Interrupt Vector Number (0-63) * Interrupt Vector Spacing (as defined by CP0 register/bitfield IntCtlVS)

We can now list the complete vector addresses for the most common exceptions (not incl. EJTAG or TLB exceptions):

Exception vectors


These bits specify the spacing between each interrupt vector for CPUs supporting Computed Interrupt Vector Offsets (PIC32MX).

MPLAB XC32 start-up code initializes IntCtlVS to 0x01, which encodes a spacing of 32 bytes (eight words) between interrupt exception vectors.


MPLAB XC32 start-up code initializes Ebase to the value defined by the symbol _ebase_address in the PIC32MX device linker script (for PIC32MX795F512L, _ebase_address = 0x9FC01000).

Therefore, for normal interrupt operations on PIC32MX:

  • The Interrupt Exception Vector Base Address = 0x9FC01000
  • The Interrupt Exception Vector Final Address = 0x9FC01000 + 0x200 + (VectNum*IntCtlVS)

For an illustration, see the following Timer 2 Interrupt Vector Address calculation example.


Exception Level: Set by the processor when any exception other than Reset, Soft Reset, NMI or Cache Error exception are taken

  • StatusEXL = 0: Normal level
  • StatusEXL = 1: Exception level; when EXL is set
    • The processor is running in Kernel Mode
    • Hardware and Software Interrupts are disabled
    • EPC, BD, and SRSCtl will not be updated if another exception is taken


StatusEXL must be cleared by the exception handler in order to re-enable interrupts. MIPS® CPUs have an instruction, eret, that both clears StatusEXL and returns control to the address stored in EPC.

Back to top

Interrupt Exception Vectors

As discussed above, PIC32MX interrupt controllers operating in Multi-Vector Mode implement a "computed offset" mode for calculating the final interrupt vector address:

  • Interrupt Exception Vector Final Address = Ebase + 0x200 + (VectNum * IntCtlVS)

The MPLAB XC32 Compiler calculates & initializes the vector address for each defined application interrupt service routine (see Table 7.1 in the PIC32MX datasheet for a listing of vector numbers assigned to each interrupt source).

Back to top


The following example illustrates how the Timer 2 Interrupt Vector Entry Point is calculated/initialized.

Back to top


  • 0x9FC01000 (initialized by the C-Run-time startup)

Back to top


  • 0x01 (Interrupt Vector Spacing = 32 bytes (0x20) - initialized by the default C-Run-time startup code)

Back to top

Timer 2 Interrupt Vector Number

  • 8 (from Table 7.1)

Back to top

Timer 2 Interrupt Exception Vector Final Address

  • 0x9FC01000 + 0x200 + (8 * 32) = 0x9FC01300

In most cases, since the spacing between interrupt exception vectors is insufficient to hold the entire handler routine, the compiler will insert an unconditional jump to the start address of the handler routine as shown in this example:

Sample ISR jump table

An interrupt handler function can be associated with an interrupt vector either as the target of a dispatch function located at the exception vector address (as shown in the above example) or as being located directly at the exception vector address.

Handler functions that are linked directly to the vector will be executed faster. Although the vector spacing can be adjusted, there is limited space between vectors, and linking a substantial handler function directly at a vector may cause it to overlap the higher vector locations, preventing their use. In such situations, using a dispatch function is a safer option.

MPLAB XC32 start-up code initializes IntCtlVS to the value defined by the symbol _vector_spacing in the PIC32MX device linker script (for PIC32MX795F512L, _vector_spacing = 0x00000001, which corresponds to the spacing of 32 bytes or eight words), however, by using function attributes, a handler can be located directly at the vector address. See the MPLAB XC32 User's Manual for details.

Back to top