PIC32MZ Exception Entry Points

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

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.

The CP0 Status register flag StatusBEV controls the Bootstrap mode.

  • 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.

Note: 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 PIC32MZ device linker script (for PIC32MZ2048EFG100, _ebase_address = 0x9D000000).

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

As seen in the above table, PIC32MZ Interrupt exception vector addresses have an additional variable offset component which is added to Ebase to form the final entry point:

  • Variable Offset = OFFx register value (initialized by the C-Run-time startup for each defined Interrupt Service Routine (ISR), starting at 0x200).

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

exception vectors


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

Therefore, for normal interrupt operations on PIC32MZ,

  • The Interrupt Exception Vector Base Address = 0x9D000000.
  • The Interrupt Exception Vector Final Address = 0x9D000000 + <OFFx> register value.


  • The first ISR's <OFFx> value is set to 0x200, and
  • Subsequent ISR vector offsets (<OFFx> value) are set according to the size of the handler function(s).

For an illustration, see the multi-vector example below.


Exception Level: Set by the processor when any exception other than Reset, Soft Reset, NMI or Cache Error exception is 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.

Note: 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, PIC32MZ interrupt controllers operating in Multi-Vector mode implement a Variable Offset mode for calculating the final interrupt vector address:

  • Interrupt Exception Vector Final Address = Ebase + OFFx

MPLAB XC32 Compiler calculates & initializes the values of OFFx for each defined application interrupt service routine (see table 7.2 in the PIC32MZ datasheet for a listing of OFFx registers for each interrupt source).

The first handler is assigned 0x200 for it's OFFx register. Subsequent handler OFFx registers are initialized based on the size of the handler functions.

Handler functions linked directly to the vector will be executed faster than those linked as the target of a dispatch function (as done on PIC32MX).

Back to top

Multi-Vector Example Using Timer 2 and Timer 4 Interrupts

A small project using Timer 2 and Timer 4 to blink 2 different LEDs at different rates produced the following results for the final exception vector addresses:


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

Timer 2 Vector Offset Register (OFF009):

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

Timer 2 Interrupt Exception Vector Final Address:

  • 0x9D000000 + 0x200 = 0x9D000200

Timer 4 Vector Offset Register (OFF019):

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

Timer 4 Interrupt Exception Vector Final Address:

  • 0x9D000000 + 0x274 = 0x9D000274

multi-vector example results

Back to top