The interrupt controller is responsible for preprocessing an Interrupt Request (IRQ) from a number of on-chip peripherals and presenting them in the appropriate order to the processor.
The interrupt controller is designed to receive up to 256 IRQs from the processor core, on-chip peripherals capable of generating interrupts, and five external inputs. All IRQs are sampled on the rising edge of the SYSCLK and latched in associated IFSx registers.
A pending IRQ is indicated by the flag bit being equal to ‘1’ in an IFSx register. The pending IRQ will not cause further processing if the corresponding IECx bit in the Interrupt Enable register is clear. The IECx bits act to mask the interrupt flag. If the interrupt is enabled, all IRQs are encoded into a Vector Number.
Each vector number is assigned an interrupt-priority-level and a shadow-set number. The priority level is determined by the IPCx register setting of the associated vector.
On some PIC32 MCUs, there are more IRQs than available vector numbers, so some IRQs share common vector numbers.
A key feature of the exception processing system is the implementation of a user-programmable priority setting for peripheral and external interrupt sources. This requires an understanding of the concept of CPU priority.
The CPU can operate at one of 8 priority levels, 0-7. An interrupt source must have a set priority level greater than the current CPU priority in order to initiate an interrupt exception process.
The CPU priority for the currently executing thread is indicated by the CP0 StatusIPL<2:0> bits.
Interrupt exceptions, by default, are nestable. Any ISR that is in progress may be interrupted by another interrupt source having a higher programmed priority level.
Conflicts between pending IRQs programmed at the same priority level are resolved via:
Interrupt Group Priority:
- The user can assign a group priority to each of the interrupt vectors. The group priority level bits are located in the IPCx register
- The user can assign a subpriority level within each group priority. The subpriority will not cause preemption of an interrupt in the same priority; rather, if two interrupts with the same priority are pending, the interrupt with the highest subpriority will be handled first. The subpriority bits are located in the IPCx register.
Interrupt Natural Priority:
- When multiple interrupts are assigned to same group priority and subpriority, they are prioritized by their natural priority. The natural priority is a fixed priority scheme, where the highest natural priority starts at the lowest interrupt vector, meaning that interrupt vector 0 is the highest natural priority. Refer to the Interrupt Vector Table (IVT) in the “Interrupt Controller” chapter of the specific device data sheet to determine the natural priority order of each IRQ.
Modes of Operation
The PIC32MZ interrupt controller can be configured to operate in one of following modes:
- Single Vector mode (INTCONMVEC = 0) – all interrupt requests will be serviced at one vector address (mode out of reset)
- Multi-Vector mode (INTCONMVEC = 1) – interrupt requests will be serviced at the calculated vector address (= Ebase + OFFx)
In Multi-Vector mode, the user can select a priority level to receive a dedicated shadow register set. In Single Vector mode, all interrupts may receive a dedicated shadow set. The interrupt controller selects the highest priority IRQ among all the pending IRQs and presents the associated vector number, offset, priority-level and shadow-set number to the processor core.
The processor core samples the presented vector information between the “E” and “M” stages of the pipeline. If the vector’s priority level presented to the core is greater than the current priority indicated by the CPU Interrupt Priority bits, StatusIPL<2:0>, the interrupt is serviced; otherwise, it will remain pending until the current priority is less than the interrupt’s priority.
When servicing an interrupt exception, the processor core pushes the Program Counter into the Exception Program Counter (EPC) register in the CPU and sets the Exception Level bit (StatusEXL) in the CPU. The EXL bit disables further interrupts until the application explicitly re-enables them by clearing the EXL bit, and then it branches to the vector address calculated from the presented vector number and offset.
The INTSTAT register contains the interrupt request location and SRIPL<2:0> bits (INTSTAT<10:8>) of the current pending interrupt. This may not be the same as the interrupt that caused the core to diverge from normal execution.
After the handler processes the interrupt, the processor execution context restored to the previous state when the Exception Return (eret) instruction is executed. The eret instruction clears the StatusEXL bit, restores the Program Counter, and reverts the current shadow set to the previous one.
There are two types of interrupts found in PIC32 devices: persistent and non-persistent.
Persistent interrupts will remain active and the associated interrupt flag (IFSx) set until the issue causing the interrupt is serviced. An example would be an interrupt declaring data in a UART receive buffer. Until this data is read, the interrupt flag will remain set even if the associated IFSx flag is cleared in 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 CPU Exceptions & Interrupt Controller section in the device data sheet to determine which interrupts are persistent/non-persistent.