PIC32MX Exception Control Registers

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

Summary

PIC32MX Interrupt and Exception system configuration and status are managed through two sets of registers; one in the Interrupt Controller and the other in the CPU's Coprocessor0 (CP0) register set.

To avoid confusion, the PIC32MX family documentation provides a typographic distinction for these registers:

  • Interrupt Controller register names are signified by upper-case letters only (e.g. INTSTAT, INTCON)
  • CP0 register names are signified by upper and lower-case letters (e.g. IntCtl, Ebase)

When taken, exception hardware preserves certain CPU states in the CP0 & Interrupt Controller Registers, based on the exception type. See MIPS®32 M4K® Processor Core Software User's Manual for more details.

​The information provided on this page summarizes exception-related registers and associated control/status bits. Please review the following documentation for complete register and bit-field definitions:

Key CP0 Exception Registers

Exception (Restart) Program Counter (EPC) Register

The EPC (CP0 Register 14, Select 0) is a read/write register that contains the address at which processing resumes after a general exception (StatusEXL = 1) has been serviced. All bits of the Exception Program Counter (EPC) register are significant and writable.

For synchronous (precise) exceptions, the EPC contains one of the following:

  • The virtual address of the instruction that was the direct cause of the exception.
  • The virtual address of the immediately preceding BRANCH or JUMP instruction, when the exception causing instruction is in a branch delay slot and the Branch Delay bit in the Cause register (CauseBD) is set.

A precise exception is one in which the EPC (CP0, Register 14, Select 0) can be used to identify the instruction that caused the exception. For imprecise exceptions, the instruction that caused the exception cannot be identified. Most exceptions are precise. Bus error exceptions may be imprecise.

Error Exception Program Counter (ErrorEPC) Register

The ErrorEPC (CP0 Register 30, Select 0) is a read/write register, similar to the EPC register, except that ErrorEPC is used on error exceptions (Reset, Soft Reset, and Non-Maskable Interrupt (NMI) exceptions, where StatusERL = 1).

The ErrorEPC register contains the virtual address at which instruction processing can resume after servicing these error exception types.

Status Register

The read/write Status register (CP0 Register 12, Select 0) contains the operating mode, interrupt enabling, and the diagnostic states of the processor. The bits of this register combine to create operating modes for the processor.

Interrupt Enable:

Interrupt exceptions are enabled when all of the following conditions are true:

  • StatusIE = 1
  • StatusERL = 0
  • StatusEXL = 0
  • DebugDM = 0

If these conditions are met, the settings of the StatusIPL bits are enabled and functional.

Operating Modes:

If the DebugDM bit is 1, the processor is in Debug mode; otherwise, the processor is in either Kernel mode or User mode. The CP0 Status register bit settings shown below determine User or Kernel mode:

  • User mode (requires all of the following bits and values):
    • StatusUM = 1
    • StatusEXL = 0
    • StatusERL = 0
  • Kernel mode (requires one or more of the following bit values):
    • StatusUM = 0
    • StatusEXL = 1
    • StatusERL = 1

StatusEXL:

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.

StatusERL:

Error Level: Set by the processor when a Reset, Soft Reset, NMI, or Cache Error exception is taken.

  • StatusERL = 0: Normal level
  • StatusERL = 1: Error level; when ERL is set
    • The processor is running in Kernel Mode
    • Hardware and Software Interrupts are disabled
    • eret instruction will use return address held in ErrorEPC instead of EPC

Note: MPLAB® XC32 start-up code clears StatusERL.

StatusIPL<2:0>:

CPU Interrupt Priority Level (IPL): This field is the encoded value of the current IPL. An interrupt signals only if the requested IPL (provided by the interrupt controller) is greater than the current priority indicated by these bits.

StatusBEV:

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

Note: StatusBEV = 1 at reset.

Cause Register

The Cause Register (CP0 Register 13, Select 0) primarily describes the cause of the most recent exception. In addition, bits also control software interrupt requests and the vector through which interrupts are dispatched.

CauseEXCCODE<4:0>:

Exception Code Bits: Indicates what kind of exception happened. Used by the _general_exception_handler() to determine the cause of the exception and branch to the appropriate handler code.

Case Register

Note: On PIC32MX, Interrupt Exceptions all have their own dedicated entry point and therefore, their handlers do not need to consult CauseEXCCODE.

CauseBD:

Branch Delay Bit: Indicates whether the last exception taken occurred in a branch delay slot:

  • CauseBD = 0: Not in delay slot
  • CauseBD = 1: In delay slot

The processor updates BD only if the EXL bit (StatusEXL) was 0 when the exception occurred.

Ebase Register

The Ebase register (CP0 Register 15, Select 1) is a read/write register containing the base address of the exception vectors used when StatusBEV=0

Refer to PIC32MX Exception Entry Points for information on exception entry points and the usage of the Ebase register.

IntCtl Register

The IntCtl Register (CP0 Register 12, Select 1) controls the interrupt vector spacing in the PIC32MX architecture.

IntCtlVS<4:0>:

Interrupt Vector Spacing Control: 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 default spacing of 32 bytes (eight words) between interrupt exception vectors. Therefore, for normal interrupt operations on PIC32MX:

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

Refer to PIC32MX Exception Vector Entry Points for more details on how PIC32MX exception vector entry points are determined.

Back to top

Interrupt Controller (INTCON) Registers

INTCON Register

Interrupt exceptions on PIC32MX can either all vector to a single handler, or to a unique handler for each interrupt.

The INTCON register is used primarily to configure the Interrupt Controller Vector mode.

INTCONMVEC:

Multi-Vector Configuration Bit: Indicates whether the last exception taken occurred in a branch delay slot:

  • INTCONMVEC = 0: Interrupt controller configured for Single Vectored mode
  • INTCONMVEC = 1: Interrupt controller configured for Multi Vectored mode

This register has an associated Clear, Set, and Invert register at an offset of 0x4, 0x8, and 0xC bytes, respectively. These registers have the same name with CLRSET, or INV appended to the end of the register name (e.g., INTCONCLR). Writing a 1 to any bit position in these registers will clear/set/invert valid bits in the associated register.

IFSx Register

The Interrupt Flag Status (IFSx) Registers indicate the current interrupt status for all of the peripheral/external interrupt sources.

For example, on PIC32MX, Timer 1 has a period register (PR1) that, when properly initialized, periodically triggers a Timer 1 interrupt signal on IFS0 as shown in the accompanying image:

Interrupt Flag Status (IFSx) Registers

Firmware in the Interrupt Service Routine (ISR) must acknowledge the interrupt by clearing the associated IFSx flag.

Refer to the Interrupt Controller chapter in the specific device datasheet to learn exact bit definitions.

There are two types of interrupts found in PIC32MX devices: persistent and non-persistent.

Persistent interrupts will remain active and the associated interrupt flag set until the issue causing the interrupt is serviced. An example would be an interrupt declaring data in a Universal Asynchronous Receiver Transmitter (UART) receive buffer. Until this data is read, the interrupt flag will remain set even if the flag is cleared in the software.

ISRs for persistent interrupts should clear the interrupt flag after removing the condition that caused the interrupt to ensure that the interrupt flag actually clears.

Refer to the device datasheet for details on which peripheral interrupts are persistent/non-persistent.

Interrupt Enable Control (IECx) Register

The IECx register control bits are used to individually enable/disable peripheral interrupt requests (IFSx signals) from triggering interrupts.

Refer to the Interrupt Controller chapter in the specific device datasheet to learn exact bit definitions.

Interrupt Priority Control (IPCx) Register

The IPCx register control bits are used to individually control peripheral interrupt priority and sub-priority settings.

Refer to the Interrupt Controller chapter in the specific device datasheet to learn exact bit definitions.

Back to top

Assigning the Shadow Register Set

Most PIC32MX devices implement one CPU shadow register set, enabling low latency interrupt context save/restore for all handlers configured at a specific CPU priority level (0-7). The DEVCFG3FSRSSEL<2:0> (Device Configuration Word 3) bit settings are used to assign the shadow register set to any handler running at this priority.

DEVCFG3FSRSSEL<2:0>:

Shadow Register Set Select Configuration Bits: Associate the shadow register set to a CPU priority level (0-7).

  • DEVCFG3FSRSSEL<2:0> = 0x111: Assign Interrupt Priority 7 to a shadow register set
  • DEVCFG3FSRSSEL<2:0> = 0x110: Assign Interrupt Priority 6 to a shadow register set
  • DEVCFG3FSRSSEL<2:0> = 0x001: Assign Interrupt Priority 1 to a shadow register set
  • DEVCFG3FSRSSEL<2:0> = 0x000: All interrupt priorities are assigned to a shadow register set

If you configure an ISR to use a shadow register set, be sure to initialize DEVCFG3,,FSRSSEL<2:0> accordingly.

The following code example defines a Timer 2 ISR as a priority level 7 interrupt that uses the shadow register set.

Note:

  • Line 5: The DEVCFG3FSRSSEL<2:0> bitfield is initialized accordingly to associate the shadow register set to all priority level 7 interrupts.
  • Line 9: ISR definition specifies the use of the shadow register set and CPU priority of 7
    • Must match the IPCx setting on line 23
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <xc.h>
#include
<sys/attribs.h>

/* Config bits */
#pragma config FSRSSEL = PRIORITY_7     /* Assign the SRS to level 7 priority handlers */

/* Define a Timer 2 ISR function at IPL level 7 that uses a shadow register set */

void __ISR (_TIMER_2_VECTOR, IPL7SRS) T2Interrupt(void)
{
   // Do some useful work

   // Reset interrupt flag
   IFS0bits.T2IF = 0;
}

/* Application begins here */
int main(void)
{
   // Initialize Timer 2 peripheral
   ...
   // Set Timer 2 interrupt priority to 7
       IPC2bits.T2IP = 7;                

   // Reset the Timer 2 interrupt flag
       IFS0bits.T2IF = 0;

   // Enable interrupts from Timer 2
       IEC0bits.T2IE = 1;

   // Interrupt Controller
   INTCONSET = _INTCON_MVEC_MASK;    /* enable interrupt controller for multi-vector mode */
    __builtin_enable_interrupts();            /* atomic enable CP0 Status(IE) flag */

   while(1)
    {
        mainTasks();                /* main application loop */
    }
}

Since there is only one shadow register set available on PIC32MX, you need to be careful when/where it is allocated.

Ideally, you should dedicate it to your single, lowest latency ISR task, defined as a level 7 priority.

If your application has several ISRs firing and they are at the same level (i.e. they will not preempt each other), you could assign the SRS directive to each ISR, giving them the benefit of lower latency entry/exit.

Do not assign the SRS to multiple ISRs at different priority levels! The SRS Configuration bit setting must match the ISR function definition for proper SRS functionality.

Back to top

Which Registers Are Relevant And When?

Refer to PIC32MX Exception Operation for information on PIC32MX exception operation, which registers are relevant, and when they are used in exception processing, 

Back to top