PIC32MX Exception Control Registers
Contents
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.
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.
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
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.
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
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)
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 CLR, SET, 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:
Firmware in the Interrupt Service Routine (ISR) must acknowledge the interrupt by clearing the associated IFSx flag.
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.
Interrupt Enable Control (IECx) Register
The IECx register control bits are used to individually enable/disable peripheral interrupt requests (IFSx signals) from triggering interrupts.
Interrupt Priority Control (IPCx) Register
The IPCx register control bits are used to individually control peripheral interrupt priority and sub-priority settings.
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
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 <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 */
}
}