You are on page 1of 13

Interrupts

Topic Outlines:

➢ Exceptions and Interrupts

➢ Cortex-M0+ Interrupt Sources

➢ Cortex-M0+ Nested Vector Interrupt Controller (NVIC)


CSE211s Introduction to Embedded Systems ➢ Interrupt Enable/Disable
Spring 2023
➢ Interrupt Priorities
Interrupts
➢ Sequence to servicing an interrupts

➢ Sequence to return from an interrupt

➢ Example using port module

➢ Sharing data safely between ISRs and other threads

Basic IO Example Polling


The main loop handles multiple activities and includes polls for events to handle them when they occur.
Goal was to light either LED1 or LED2 based on switch
SW1 position. We achieve that by software through an ➢ Busy-Wait: (Blocking) ➢ Rapid Polling: (Nonblocking)
infinite loop that does nothing but read the switch state If not yet, wait. If not yet, continue executing tasks sequentially.
on one side and update the LEDs on the other.
while (1) { while (1) {
. .
. .
. .
➢ In practice, an embedded system should manage multiple activities. while (!event_condition) { if (event_condition) {
} Execute event handler
The software of an embedded application normally is made up of multiple tasks executed by the CPU: Execute event handler Clear event_condition
• to do normal activities and Clear event_condition
. }
• to handle events when they occur. . .
. .
.
}
An event is detected either by: }
• the CPU polling for the event occurrence or
Waiting for event_condition to be true results in Reaching the statement that tests event_condition may
• the CPU is notified by an interrupt when the event occurs. undetermined time delays while blocking other tasks come late in case the main loop has many tasks. In such
which may be critical. case, the event handling may be delayed or even missed.
8 © 2019 Arm Limited
5
Embedded Software Structure Simple Embedded Software Structures
1. The Super-Loop

➢ Simple Embedded Software Structures (Most embedded systems are simple) A super-loop is an infinite loop, with all the tasks of the system
contained in the loop.
1. Super Loop Benefit:
After system initialization, the program executes an infinite loop, • Simple
2. Event-driven program in which all tasks are executed sequentially in order.
Drawbacks:
main() { Each task in the loop does the • Wasting CPU time and system power
➢ Complex Embedded Software Structure
system_initialization(); following: checking the status of all devices, even if
• Application is decomposed into tasks: // super loop Check_Status(); not ready.
while(1){ if condition then • Accurate timing not guaranteed.
Run-to-Completion, Endless-Loop, System, and Application Tasks Task_1(); Do_Calculations();
Task_2(); • Sequential task execution results in bad
A task scheduling policy ensures task concurrency and system responsiveness. Output_Response();
…; system responsiveness as it is unable to
else
wait(35); //optional respond to an input e.g., from keyboard
} return until it reaches the keyboard task.
} end

Simple Embedded Software Structures Simple Embedded Software Structures


2. Event Driven Structure 2. Event Driven Structure

In a programming environment, an event is something that is generated by a source and recognized


Events can be:
by a recipient, causing the latter to take action to handle the event.
1. Periodic (such as a timer reaching zero)
A hardware event is a logical condition in a peripheral.
2. Asynchronous (such as user pressing a key, or from the UART receiving a character)
Instead of continually checking for all peripherals status, an embedded system can be designed to
be event-driven … It acts in response to events when they occur. Events in an embedded system are usually associated with interrupts to the CPU caused by
hardware signals.
The CPU may execute an endless loop or sit in an idle state, waiting to react to any event when it
In this case, an event-driven system is called interrupt-driven system.
occurs. When the event occurs, the CPU is notified by a hardware signal.

For this reason, event-driven systems are also called reactive systems. When an interrupt occurs, it invokes a routine to handle the event.

When the CPU has nothing to do, a special instruction can put it into a power-saving state,
waiting for events.
Interrupts Basic Questions when Considering Interrupts
➢ Which peripherals are allowed to cause interrupts?
➢ Interrupts provide efficient event-based processing.
▪ The startup code configures the peripheral (and an interrupt controller) to let it cause an interrupt on a specific event. ➢ Should we have control on when to allow or disallow interrupts?
▪ A code (background) starts executing main function and other background tasks.
➢ In case we have multiple sources of interrupts, how does the interrupting source is identified?
▪ When the specified event occurs, an interrupt occurs triggering the following sequence:

11) CPU does some hard-wired processing to ➢ Which code (function) should the CPU execute to service the identified interrupt?
save its current context, to be able to come
1 ➢ How the interrupted code status is saved so that the CPU can resume it after the interrupt is serviced.
back. Also, it identifies what to execute to Main Code Hardwired CPU ISR
(Background) response activities (Foreground)
service the interrupt.
➢ What does the CPU do if multiple interrupts are requested simultaneously?
2
22) CPU executes the identified interrupt
service routine (ISR) which includes a ➢ What does the CPU do if an interrupt is requested while servicing another interrupt?
return instruction at its end. time
➢ How to share data safely between different pieces of code?
33) CPU resumes the interrupted code.
3 17

CORTEX-M Exceptions
In the ARM programmer’s model, interrupts are a type of exception. The term “exception” in ARM definition means
any deviation of program flow which may be caused by an external event (an interrupt) or any internal CPU condition.

1) External events (interrupts): Caused by an event in a peripheral which is asynchronous to the CPU.
It can be caused by:
• A condition in an on-chip peripheral module such as GPIO, ADC, Timer, UART …
• A signal on a pin of the MCU.
2) Internal CPU events:
• Requested by the program executing specific instruction such as:
▸ SVC (supervisor call) and SWI (software interrupt) by ARM
▸ INT (interrupt) by Intel (x86)
▸ TRAP by Motorola (HC12)
Cortex-M0+ Interrupts • Automatically generated trap (coerced rather than requested) caused by an exceptional condition such as:
▸ Undefined instruction
▸ Bus fault
▸ Division by zero
18
Cortex-M0+ Exception Sources CORTEX-M Interrupts
➢ The ARM Cortex-M has room for the total of 255 interrupts and exceptions.
➢ The ARM core uses vectored interrupts which means that each interrupt source is assigned:
➢ The Cortex-M0+ CPU supports up to 32 non-core interrupt sources and 16 core sources.
• An interrupt request number (IRQn) identifying itself
▪ Core exception examples:
• An interrupt vector (an address) to tell the CPU where to go to execute the service to the interrupt
• when the CPU starts up (Power-up reset or RESET pin signal)

• when errors occur e.g., the code tries to access a peripheral that is not enabled yet through clock gating.
➢ The lowest 1024 bytes (256 × 4 = 1024) of memory space are set aside for the interrupt vector table that maps
• when system services are requested. (Supervisor call; SVC instruction)
the interrupt request number IRQn to the interrupt vector and must not be used for any other function.
▪ Non-Core 32 interrupt sources (numbered IRQ0-IRQ31):
• These interrupts are caused by peripheral modules, so they are MCU-manufacturer dependent. ➢ The ARM core uses prioritized interrupts: it uses priority numbers to assign precedence to different sources.
Priority means:
➢ All Cortex-M has an on-chip interrupt controller called Nested Vector Interrupt Controller (NVIC) to interface the
• which interrupt is serviced first when simultaneous requests are made, or
CPU to different interrupt sources. It allows some degree of standardization among the ARM Cortex-Mx (M0, M1,
M3, and M4) family members. • can a new interrupt preempt a running interrupt service routine.

➢ The Nested Vector Interrupt Controller (NVIC), part of the ARM core, is configured to control the peripheral’s
20 interrupt generation behavior. It employs a priority resolution that can be customized by software.

Selected Cortex-M0+ Core Exception Sources Selected Cortex-M0+ Core Exception Sources
Vector Address Vector # Source Description Priority
2. NMI: The non-maskable interrupt request to the NVIC is controlled by the external NMI signal.
0x0000_0004 1 Reset CPU reset −3 Priority:
The lower the number, the The pin which the NMI signal is multiplexed on, must be configured for the NMI function to generate the non-
0x0000_0008 2 NMI Nonmaskable interrupt −2 higher the priority maskable interrupt request.
0x0000_000C 3 HardFault Hard fault error −1
Programmable:
0x0000_002C 11 SVCall Call to supervisor with SVC instruction Programmable Means can be changed by 3. HardFault: The catchall for assorted system failures that can take place such as accesses to bad memory,
program.
0x0000_0038 14 PendSV System-level service request Programmable divide-by-zero errors and illegal unaligned accesses.
0x0000_003C 15 SysTick System timer tick Programmable
11. SVCall: Exception handler invoked when a Supervisor Call (svc) instruction is executed.
1. Reset: is caused by
• Asserting RESET pin which wakes the device from any mode. 14, 15. PendSV & SysTick: System level interrupts triggered by software. They are typically used when
• Power-on reset beginning with the on-chip regulator in full regulation and system clocking generation from an internal reference. running areal-time operating system (RTOS) to manage when the scheduler runs and when context switches
Reset provides a way to start processing from a known set of initial conditions: take place.
1. The CPU performs the following:
• Reads the start SP (SP_main) from vector-table offset 0
• Reads the start PC from vector-table offset 4 The interrupts that are external to the core are usually routed to vendor-specific peripherals on the MCU such
• LR is set to 0xFFFF_FFFF
as GPIOs. All these interrupts are configured via the Nested Vectored Interrupt Controller (NVIC).
2. The on-chip peripheral modules are disabled.
3. The non-analog I/O pins are initially configured as disabled.
4. The pins with analog functions assigned to them default to their analog function.
22 23
KL25Z Interrupt Sources
ARM Cortex-M NVIC
Vector address Vector # IRQ Description
0x0000_0040, 44, 48, 4C 16–19 0–3 Direct memory access controller
Mapping IRQ number to interrupt vector: ➢ If any enabled interrupts are requested, the NVIC selects the one with the highest priority and directs the CPU
0x0000_0058 22 6 Power management controller
For example, if PORTD requests an interrupt: to start executing its ISR.
0x0000_005C 23 7 Low leakage wake up
2
0x0000_0060, 64 24–25 8–9 I C communications 1. The port control module signals the NVIC. ➢ The supported 32 interrupt sources IRQ0 through IRQ31 can be configured individually:
0x0000_0068, 6C 26–27 10–11 SPI communications
– Enabled or disabled
0x0000_0070, 74, 78 28–30 12–14 UART communications
2. The NVIC will issue interrupt request #31 – Prioritized
0x0000_007C 31 15 Analog to digital converter
0x0000_0080 32 16 Comparator to the CPU. – Set as pending (requested but not yet serviced)
0x0000_0084, 88, 8C 33–35 17–19 Timers and pulse-width modulation
0x0000_0090, 94 36–37 20–21 Real-time clock alarm and seconds
➢ Interrupt processing status can be read and modified
3. The CPU will read the vector table to find
0x0000_0098 38 22 Programmable interval timer
the location of the ISR for IRQ #31
0x0000_00A0 40 24 USB on-the-go
0x0000_00A4 41 25 Digital to analog converter (vector #47). It will read the word starting
0x0000_00A8 42 26 Touch sense interface
0x0000_00AC 43 27 Main clock generator at address 0x0000_00BC and load it into
0x0000_00B0 44 28 Low power timer
the PC so the ISR starts. ➢ The Wakeup Interrupt Controller WIC duplicates the interrupt masking of NVIC which enables NVIC to be
0x0000_00B8 46 30 Port control module, Port A pin detect
0x0000_00BC 47 31 Port control module, Port D pin detect turned off when the system is idle or sleeping to reduce power.

The WIC will wake up the NVIC if new interrupts are requested, ensuring they are processed and not lost.

24
IRQ number = interrupt vector number ̶ 16:

NVIC Registers Interrupt Enable & Disable


Interrupts and other exceptions of configurable priority can be enabled or disabled globally or selectively.
(1) Globally:
➢ The CPU controls whether interrupts and other exceptions of configurable priority are recognized or not via
Size in bit zero (PM) of the programmable-interrupts mask core register PRIMASK:
Address Name bits Description Read/Write At RESET

Interrupt Set-Enable 0 No effect – PRIMASK.PM = 1: Disable interrupts


0xE000E100 NVIC_ISER 32 Register 1 Enable associated Interrupt 0x00000000
– PRIMASK.PM = 0: Enable interrupts
Interrupt Clear-Enable 0 No effect
0xE000E180 NVIC_ICER 32 Register 1 Disable associated Interrupt 0x00000000 – PRIMASK.PM bit is set to 0 on reset → Interrupts are enabled upon reset.
0 No effect The PRIMASK register is accessed by the move special register instructions, MSR or MRS:
Interrupt Set-Pending
0xE000E200 NVIC_ISPR 32 1 Change state of associated 0x00000000
Register • MSR primask,<Rn> ; reads the PRIMASK register into general purpose register Rn
interrupt to pending
0 No effect • MRS <Rd>,primask ; writes to the PRIMASK register from general purpose register Rd
Interrupt Clear-Pending
0xE000E280 NVIC_NCPR 32 1 Change state of associated 0x00000000
Register
interrupt to not pending
In addition, Change Processor State instruction (CPS) changes the PRIMASK (in privilege mode):
• CPSID i ; set PRIMASK.PM to 1 to disable interrupts globally.
0xE000E400- NVIC_IPR0- Eight interrupt Priority Each register has 4 fields to set or Each is zero • CPSIE i ; set PRIMASK.PM to 0 to enable interrupts globally.
32 each
0xE000E41C NVIC_IPR7 Registers read priorities of 4 IRQs. 0x00000000
CMSIS-CORE API
– void __enable_irq() - clears PM flag
– void __disable_irq() - sets PM flag Only NMI, Hardfault, and Reset
– uint32_t __get_PRIMASK() - returns value of PRIMASK exceptions can still occur.
– void __set_PRIMASK(uint32_t x) - sets PRIMASK to x
Interrupt Enable & Disable Pending Interrupt
(2) Selectively:
Pending Interrupt:
➢ Each interrupt source can be enabled or disabled separately using two NVIC registers:
It is an interrupt that has been requested by a peripheral but is not yet serviced.
• ISER: Interrupt Set-Enable Register and
A pending state can be requested by writing to NVIC Set-Pending register NVIC_ISPR.
• ICER: Interrupt Clear-Enable Register
A pending state can be cleared by writing to NVIC Set-Clear register NVIC_ICPR.
Each is 32 bits, with each bit corresponding to one IRQ, IRQ0 to IRQ31:
CMSIS Interface:
• To enable an interrupt source n, write a 1 to bit n in ISER. • Uint32_t NVIC_GetPendingIRQ(IRQnum) Returns 1 if interrupt from IRQnum is pending

• To disable an interrupt source n, write a 1 to bit n in ICER. • NVIC_SetPendingIRQ(IRQnum) Sets interrupt pending flag for IRQnum
• NVIC_ClearPendingIRQ(IRQnum) Clears interrupt pending flag for IRQnum
CMSIS Interface:
– NVIC_EnableIRQ(IRQn) to enable interrupt of type IRQn
– NVIC_DisableIRQ(IRQn) to disable interrupt of type IRQn

➢ Reading ISER or ICER will return the enabled/disabled state for all 32 IRQ sources.

Prioritizing Interrupts Setting/Changing Interrupt Priority


➢ Each exception source has a priority that determines the order in which simultaneous exception requests are ➢ The NVIC contains eight interrupt priority registers (IPR0-7).
handled.
➢ Four interrupt sources per register.
➢ The priority of each interrupt is determined by a priority number, set by software in an NVIC register.
➢ Each IPR has an 8-bit field for each interrupt sources, two of these bits specify the
➢ The requested exception with the lowest priority number (highest priority) will be handled first. priority level and six bits reserved.
➢ Multiple interrupt sources can have the same priority.
➢ Priority numbers of some exceptions are fixed
– Reset: −3, highest priority
31:30 29:24 23:22 21:16 15:14 13:8 7:6 5:0
– NMI: −2
– Hard Fault: −1 IPR0 IRQ3 reserved IRQ2 reserved IRQ1 reserved IRQ0 reserved

IPR1 IRQ7 reserved IRQ6 reserved IRQ5 reserved IRQ4 reserved


➢ The rest of the exceptions and interrupts have lower priorities and are programmable.
IPR2 IRQ11 reserved IRQ10 reserved IRQ9 reserved IRQ8 reserved
In Cortex-M0+, programmable priority levels range from 0 to 3, with 3 has the lowest priority.
All IRQn programmable priorities are set by writing to 8 interrupt priority registers: IPR0-7. IPR3 IRQ15 reserved IRQ14 reserved IRQ13 reserved IRQ12 reserved

IPR4 IRQ19 reserved IRQ18 reserved IRQ17 reserved IRQ16 reserved


➢ Only the higher priority interrupts ae allowed to preempt a lower priority ISR.
IPR5 IRQ23 reserved IRQ22 reserved IRQ21 reserved IRQ20 reserved
The programmer is responsible to assign the proper priority to each IRQ to determine which interrupt may
preempt other’s ISRs. IPR6 IRQ27 reserved IRQ26 reserved IRQ25 reserved IRQ24 reserved

IPR7 IRQ31 reserved IRQ30 reserved IRQ29 reserved IRQ28 reserved


➢ NVIC resolves priority and can capture the pending interrupts and keeps track of each one until all are serviced.
Setting/Changing Interrupt Priority Special Cases of Prioritization
➢ Simultaneous exception requests:
Values that can be stored in each 8-bit field in the interrupt priority register (IPR0-7)
– The exception with the lower priority number is serviced first, the other one is set pending.
– Priority level 0 0x00 0 (highest priority)
When the one with higher priority is finished, the one pending starts execution.
– Priority level 1 0x40 64
– If multiple interrupts have the same priority number, the one with the lowest IRQ number takes
– Priority level 2 0x80 128 precedence for example IRQ3 precedes IRQ5.
– Priority level 3 0xC0 192 (lowest)
➢ New exception requested while a handler is executing:
Only exceptions with a higher priority (lower priority number) can preempt an executing exception.
CMSIS Interface:
1. New exception has priority higher than current priority, then
NVIC_SetPriority(IRQnum, priority) » New exception handler preempts current exception handler.
After the new exception completes, preempted one resumes.

2. New exception has priority lower than or equal to current priority, then
» Hold new exception pending state.
» Current handler continues and completes execution.
» Previous priority level restored.
» Start new exception handler if its priority level allows.

Initializing the Interrupt Vector Table Initializing the Interrupt Vector Table
➢ CMSIS-CORE specifies standard names for system exception handlers.
➢ Different microcontrollers have different peripherals, so the interrupt handler’s names and vectors are
defined in the MCU-specific startup code.
➢ The Define Constant Data DCD symbol tells the assembler to define a constant data word with the value
specified. In this case it is the address of the specified handler (the interrupt vector).

The definition of the Interrupt Vector Table IVT in the KL25Z4 MCUs assembly language file startup_MKL25Z4.s (16 exceptions) The rest of the IVT in the KL25Z4 MCUs assembly language file startup_MKL25Z4.s (IRQ0-22 out of 32)
Initializing the Interrupt Vector Table Interrupt Configuration
➢ In order to use hardware interrupts from a peripheral module we must go through three steps to configure the
interrupt from that module :

11. The peripheral module to select which interrupt it generates.


• Different types of peripherals have interrupt configuration options. For example:
– ADC0 module can generate interrupt on conversion complete
– PORTD can generate interrupt on logical event on a pin

22. The NVIC to selectively enable and give priority to that IRQ

33. The core to let it accept programmable interrupts


After reset, the processor core is already set up to accept interrupts, as the PRIMASK.PM=0.

The rest of the IVT in the KL25Z4 MCUs assembly language file startup_MKL25Z4.s (IRQ23-31 out of 32) 1 2 3

Configuration: Level 1 ─ Peripheral Module Configuration: Level 1 ─ Peripheral Module


(Example PORTD) (Example PORTD)
Here we will examine the Kinetis KL25Z’s PORT module ➢ The port module Interrupt Status Flag Register (ISFR), 32-bit, indicates which interrupts have been detected for
1 this port.
with its pin control in the pin control register (PCR) .
A bit value of one indicates the corresponding interrupt has been detected.
The Interrupt Request Condition IRQC field in the PCR
controls the pin condition which will generate interrupt. ➢ The ISR needs to write a one to this bit to clear it to zero ! to prevent recurrent interrupts.
It should be set according to the table. Code Condition Selected – With CMSIS-CORE interface, the ISFR is accessed as PORTD->ISFR.
0 Interrupt/DMA request disabled
The ISFR is part of the PORT module. One register for each port e.g., PORTA_ISFR, PORTD_ISFR…
8 Interrupt when logic zero

9 Interrupt on rising edge

10 Interrupt on falling edge

11 Interrupt on either edge

12 Interrupt when logic one w1c means write one to clear.


Other Reserved, or for DMA ➢ Each ISF bit indicates the detection of the configured interrupt on the corresponding port bit number.
– 0 Configured interrupt is not detected.
CMSIS interface: – 1 Configured interrupt is detected.
PORTD->PCR[SW1_POS] = PORT_PCR_IRQC(9) | PORT_PCR_MUX(1) ;
➢ The corresponding bit is read only for pins that do not support interrupt generation.
Each port, PORTA or PORTD, is assigned only one IRQ number; IRQ30 for PORTA and IRQ31 for PORTD.
➢ The ISF bit for a pin is also visible in the corresponding PCR register. Each flag can be cleared in either location.
Therefore, when one of these IRQs occurs, the corresponding ISR should be able to identify which bit in the port
caused the interrupt. ➢ If the pin is configured for a level sensitive interrupt and the pin remains asserted, then the flag is set again
This information is found in the port module Interrupt Status Flag Register (ISFR) immediately after it is cleared (a should-be-avoided situation).
Configuration: Level 2 ─ NVIC Configuration Level 3 ─ Core
2 3

➢ Enable Selected Interrupt


We enable an interrupt source N by writing a 1 to bit N in the interrupt set enable register ISER. Finally, the processor core is configured to accept configurable interrupts by resetting the PRIMASK.PM flag to 0.
The CMSIS-CORE API interface: EnableIRQ(IRQnum)
Values for IRQnum are defined by the CMSIS-compliant device driver and are listed in the MKL25Z4.h header file. Note that when the CPU is reset or powers up, PM is set to zero, so interrupts are not ignored.
In our case PORTD_IRQHandler.
The PM bit is accessed:
➢ Set Interrupt Priority
We set the interrupt priority in the corresponding field in registers IPR0-7. 1) In assembly use the instructions:
The CMSIS-CORE API interface: NVIC_SetPriority(IRQnum, priority) CPSID i to disable interrupts
The priority parameter is set to 0, 1, 2, or 3. CPSIE I to enable interrupts
➢ Pending 2) CMSIS-CORE API provides these interfaces for accessing the PM flag:
The flag is set by hardware when the interrupt is requested. Software can also set the flag to request the interrupt.
The ISR must clear its source’s pending IRQ flag or else the handler will run repeatedly.
The CMSIS-CORE API provides this interface:

Interrupt or Exception Processing Sequence

Interrupt 1. Entering
occurs Exception Sequence

Main Code Hardwired CPU ISR 2. Executing


(Background) response activities (Foreground) ISR

ENTERING AN EXCEPTION HANDLER

time

3. Exiting Exception
Sequence

Code operations
Hardware operations (Done transparently)
42 43
[1] Entering an Exception Handler (Done Transparently) 1. Finish Current Instruction
1. Finish current instruction (except for lengthy instructions) ➢ Most instructions are short and finish quickly in one cycle

The hardware itself implements the ARM ➢ Some instructions may take many cycles to execute:
2. Push context (832-bit words) onto current stack (MSP or PSP)
Architecture Procedure Calling Standard (AAPCS).
Load Multiple (LDM), Store Multiple (STM), Push, Pop, MULS (32 cycles for some CPU core implementations)
3. Switch to handler/privileged mode, use main stack pointer MSP
Waiting for such instructions to complete will delay interrupt response significantly.
4. Load PC with address of exception handler from Interrupt Vector Table.
➢ If one of these instructions is executing when the interrupt is requested, the processor does the following:

5. Load LR with EXC_RETURN code. (Note LR does not hold the Return Address which is saved on the stack) ▪ abandons the instruction

▪ responds to the interrupt


6. Load IPSR with exception number and start executing code of exception handler.
▪ executes the ISR

▪ returns from interrupt


➢ Interrupt latency:
▪ restarts the abandoned instruction
It is defined as the time from the exception request to the execution of first instruction in handler.
Usually 16 cycles in the M0, and 15 cycles in the M0+.
44 45

2. Push Context onto Current Stack 3. Switch to Handler/Privileged Mode

Reset

Thread
Mode.
MSP or PSP.

▪ Handler mode always uses Main SP Exception Starting


, upon entering ISR Processing Exception
Completed Processing
▪ Push context (832-bit words) onto current stack (MSP or PSP) Following the AAPCS conventions,
(What about other registers: R4, R5, …?) exception handlers and thread mode Handler Mode
code can be regular C functions MSP
(Note Return Address now is on the stack)
▪ Two SPs: Main (MSP), process (PSP)
• Which is active depends on operating mode (Thread mode/Handler Mode): CONTROL register bit 1.
• When pushing context, the hardware decrements the stack pointer to the end of the new stack frame before
it stores data onto the stack. .
• When popping context, the hardware reads the data from the stack frame then increments the stack pointer.
46
▪ Stack grows toward smaller addresses 47
4. Load PC With Address Of Exception Handler 5. Load LR With EXC_RETURN Code
The INT# is multiplied by 4 to fetch the interrupt vector from IVT and load it in PC. ▪ EXC_RETURN value is generated by CPU and loaded into the LR so that upon executing a return instruction
at the end of the ISR and this code is loaded into the PC, it forces a return from exception sequence not a return
from a function call.
Reset Interrupt
Service Routine start
▪ EXC_RETURN value carries information on how to return:

Port D ISR
▪ Which SP to restore registers from? MSP (0) or PSP (1)
PORTD_IRQHandler
◦ Previous value of SPSEL
Port A ISR PORTA_IRQHandler
▪ Which mode to return to? Handler (0) or Thread (1)
◦ Another exception handler may have been running when this exception was requested
Non-maskable Interrupt
Service Routine NMI_IRQHandler
EXC_RETURN Return Mode Return Stack Description

Contains Port D Interrupt Vector 0x0000_00BC PORTD_IRQHandler 0xFFFF_FFF1 0 (Handler) 0 (MSP) Return to exception handler
Contains Port A Interrupt Vector 0x0000_00B8 PORTA_IRQHandler
0xFFFF_FFF9 1 (Thread) 0 (MSP) Return to thread with MSP
Contains Non-Maskable Interrupt Vector 0x0000_0008 NMI_IRQHandler
0x0000_0004 start
Contains Reset Interrupt Vector 0xFFFF_FFFD 1 (Thread) 1 (PSP) Return to thread with PSP

48 50

6. Start Executing Exception Handler

▪ IPSR is loaded with exception number and exception handler starts running, unless
preempted by a higher-priority exception

▪ Exception handler may save additional registers on stack


e.g. if handler may call a subroutine, LR and R4 must be saved
EXITING AN EXCEPTION HANDLER

51 52
[3] Exiting an Exception Handler 1. Execute Instruction for Exception Return
1. Execute instruction triggering exception return processing
There is no “RETURN FROM INTERRUPT” instruction. Instead use regular instruction: ➢ The processor saves an EXC_RETURN value to the LR on
i. BX LR - Branch to address in LR by loading PC with LR contents. exception entry. The exception mechanism relies on this value to
ii. POP …, PC - Pop address from stack into PC.
detect when the processor has completed an exception handler:
… with a special value EXC_RETURN loaded into the PC to trigger exception handling processing
i. BX LR used if EXC_RETURN is still in LR ▪Bits[31:4] of an EXC_RETURN value are 0xFFFFFFF.
ii. POP used if EXC_RETURN has been saved on stack EXC_RETURN Description
➢ When the processor loads a value matching this pattern to the PC it Return to Handler mode.
Exception return gets state from the
2. Select return stack, restore context from that stack detects that the operation is not a normal branch operation and, 0xFFFFFFF1
main stack MSP.
i. Check EXC_RETURN (bit 2) to determine from which SP to pop the context Execution uses MSP after return.
instead, that the exception is complete. As a result, it starts the
ii. Pop the registers from that stack Return to Thread mode.
SP points here after handler exception return sequence. 0xFFFFFFF9 Exception return gets state from MSP.
Execution uses MSP after return.
Return to Thread mode.
➢ Bits[3:0] of the EXC_RETURN value indicate the required return 0xFFFFFFFD Exception return gets state from PSP.
stack and processor mode, as in the table: Execution uses PSP after return.
All other values Reserved.
• Bit0 indicates thumb mode
SP points here during handler
• Bit2 indicates PSP
3. Resume execution of code at restored address • Bit3 indicates MSP
53 54

2. Select Stack, Restore Context

▪ Check EXC_RETURN (bit 2) to determine from which SP to pop the context

EXC_RETURN Return Stack Description


0xFFFF_FFF1 0 (MSP) Return to exception handler with MSP
0xFFFF_FFF9 0 (MSP) Return to thread with MSP
0xFFFF_FFFD 1 (PSP) Return to thread with PSP
▪ Pop the registers from that stack EXECUTING AN EXCEPTION HANDLER
SP points here after handler

SP points here during handler

55 56
[2] Executing The Exception Handler Differences Between Interrupt and Subroutine Call (BL)
Rules to write an exception handler:
➢ A BL instruction is used by the programmer in the sequence of instructions
▪ No arguments or return values – void is only valid type ➢ The interrupt is caused by a hardware event; it comes at any time.

▪ Name the ISR according to CMSIS-CORE system exception names, to ensure that the software toolchain places
ISR addresses in the IVT correctly. ➢ A BL instruction automatically saves only PC of the next instruction on the stack.
The linker will load the vector table with this handler rather than the default handler.
➢ Before servicing an interrupt, the LP, R12, R3–R0, xPSR (flag register) in addition to PC
Examples: are automatically saved on stack.
▪ void PORTA_IRQHandler(void); PORTA_IRQHandler,
▪ void RTC_IRQHandler(void); RTC_IRQHandler, etc.
➢ The BL instruction does not change the CPU execution mode.
▪ Keep it short and simple: Much easier to debug and improves system response time. ➢ An interrupt puts the CPU in the Handler Mode.

▪ In the start of the ISR, clear pending interrupt


▪ Call NVIC_ClearPendingIRQ(IRQnum) ➢ When returning from the subroutine that has been called by the BL instruction, the PC is
restored to the address of the next instruction after the BL instruction.
▪ In case this IRQn can possibly be caused by more than one event, identify the exact cause of the interrupt.
➢ When returning from the interrupt handler, the registers saved when the CPU entered into
▪ Complete the body of the ISR ISR (the xPSR, R15, R14, R12, R3–R0 registers) are restored from the top of stack.

▪ Make sure to clear interrupting flag at the end of the ISR before the “Return” instruction.
57 This step is essential to avoid recurrent interrupts from the same source. 58

You might also like