0% found this document useful (0 votes)
171 views76 pages

Lec - 6 Interrupts

The document discusses interrupts and exceptions in ARM Cortex-M0+ systems, including how peripheral devices can trigger interrupts to request service, how the Nested Vector Interrupt Controller prioritizes and directs interrupt requests to the appropriate interrupt service routines, and how software must handle sharing data safely between interrupt service routines and other code. It provides examples of interrupt sources for Cortex-M0+ and the basic questions to consider when implementing interrupt-driven programs.

Uploaded by

jarvis 1011
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
171 views76 pages

Lec - 6 Interrupts

The document discusses interrupts and exceptions in ARM Cortex-M0+ systems, including how peripheral devices can trigger interrupts to request service, how the Nested Vector Interrupt Controller prioritizes and directs interrupt requests to the appropriate interrupt service routines, and how software must handle sharing data safely between interrupt service routines and other code. It provides examples of interrupt sources for Cortex-M0+ and the basic questions to consider when implementing interrupt-driven programs.

Uploaded by

jarvis 1011
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 76

Interrupts

Topic Outlines:

➢ Exceptions and Interrupts

➢ Real Time I/O Synchronization by: Delay loops / Polling / Interrupts

➢ Cortex-M0+ Interrupt Sources

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

➢ Interrupt Enable/Disable

➢ Interrupt Priorities

➢ Sequence to servicing an interrupts

➢ Sequence to return from an interrupt

➢ Example using port module

➢ Sharing data safely between ISRs and other threads


Terminology Confusion
➢ The term “interrupt” usually refers to an event that is external to the CPU such as I/O device
request or timer overflow, but there is wide disagreement on the terms “exception” and “trap”.

➢ 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 event whether initiated by the
program executing specific instructions or by an exceptional condition:

▪ The term “trap” or “software interrupt” is defined as programmer initiated and expected
transfer of control to a special routine. It is an instruction known by various mnemonics:
▸ SVC (supervisor call) and SWI (software interrupt) by ARM
▸ INT (interrupt) by Intel (x86)
▸ TRAP by Motorola (HC12)

▪ Automatically generated trap (coerced rather than requested) due to an exceptional


condition such as unidentified instruction or bus fault.

The term exception in ARM definition is general.


We will not consider core exceptions in our lectures; only interrupts from peripheral modules.
Both terms, exception and interrupt will be used interchangeably.
Real Time I/O Synchronization
➢ At startup, the CPU configures its peripherals.

➢ An I/O operation can be initiated either by the (1) the CPU or (2) the peripheral module:
1) The CPU requests a sample from the ATD module and reads it when ready.
2) The SCI receives a byte and signals the CPU for data ready.

➢ Typically CPUs are much faster than the I/O peripherals serving it.

➢ Due to this speed mismatch, a CPU and its peripherals must be synchronized using
SOFTWARE and HARDWARE techniques
1. Software synchronization
– Delay loops (Blind cycles)
– Polling
2. Interrupts (Hardware + Software)
– An I/O device causes a software routine to execute upon request
– Periodic interrupts check the I/O status (Periodic polling) and act accordingly
3. Direct Memory Access (DMA) (Hardware)
An I/O device interface can be configured for transfer of data to/from memory
directly not through data transfer instructions executed by the CPU.
Synchronization
by Software (1) Delay Loops

Delay loops used by the CPU to perform I/O with a Initiate I/O
peripheral module takes the following steps: Operation

1. Initialize the I/O task with the peripheral module. COUNT = Max

2. Start a delay loop by counting for a time that is COUNT = COUNT − 1

sufficient for the module to finish the task.

COUNT = 0
?
3. Perform the I/O operation. N
Y

Transfer
I/O Data
Synchronization
by Software (2) Polling
CPU initializes the peripheral module and selects suitable configuration.
CPU initiates CPU initiates CPU initiates
input operation output operation output operation

Wait until the output Perform the write


peripheral is ready before operation then wait until
starting the write operation. the peripheral is ready for
Necessity for interrupts: next write.
Using polling to synchronize I/O operations consumes the CPU time as it always waits
for the peripheral READY FLAG.
➢ Use interrupts instead. CPU initiates I/O operation and goes back to normal work.
When the I/O device completes the operation it interrupts the CPU for its attention.
Synchronization
by Software & Hardware Interrupts
▪ The startup code configures the peripheral (and an interrupt controller) to let it cause an interrupt on a specific event.

▪ A code (background) starts executing main function and other tasks.

▪ When the specified event occurs, an interrupt occurs triggering the following sequence:

1) CPU does some hard-wired processing to save its current context, to be able to come back, and identify what to
execute to service the interrupt.
2) CPU executes the identified interrupt service routine ISR which includes a return instruction at its end.

3) CPU resumes the interrupted code. 1


Main Code Hardwired CPU ISR
(Background) response activities (Foreground)

time

3
Basic GPIO Example

Input from a switch Output to LEDs

▪ Goal: light either LED1 or LED2 based on switch SW1 position pressed/not
pressed.

▪ We can achieve that by letting the CPU execute an infinite loop of instructions that
keeps polling the state of the switch and change the LEDs accordingly.
▪ This polling scheme is wasteful to the CPU time as the CPU becomes unavailable to
do anything else useful.
▪ Try interrupts: Use special hardware in MCU to detect event, run specific code
(interrupt service routine - ISR) in response.
7
Basic Questions when Considering Interrupts

➢ Which peripherals can cause interrupts, or more fundamentally do we allow interrupts?

➢ How does the interrupting source identify itself to the CPU to get the service in case we have many sources
of interrupt?

➢ Which code should the CPU execute to service the identified interrupt?

➢ How is the interrupted code status saved so that the CPU is able to resume it after the interrupt is serviced?

➢ What does the CPU do if an interrupt is requested while servicing another interrupt?

➢ What does the CPU do if multiple interrupts are requested simultaneously?

➢ How to share data between different pieces of code in a system that allows interrupts?

8
CORTEX-M0+ INTERRUPTS

9
ARM Interrupts
➢ In the ARM programmer’s model, interrupts are a type of exception.

➢ Interrupts are caused by an event in the peripheral which is asynchronous to the CPU.
It can be caused by:
1. A condition in an on-chip peripheral module such as Timer, ADC, UART …
2. A signal on a pin of the MCU.
➢ An event is logical: a signal level or edge (sometimes software selectable)
— High level
— Low level
— Positive edge
— Negative edge

➢ The ARM core uses vectored interrupts which means that each interrupt source has:
• An interrupt request number identifying itself
• A vector (an address) to tell the CPU where to go to execute the service to the interrupt

➢ The ARM core uses prioritized interrupts: it uses priority numbers to assign precedence to different sources.
Priority means which interrupt is serviced first when simultaneous requests are made, or 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 interrupt
generation behavior. It employs a priority resolution that can be customized by software.
Cortex-M0+ Exception Sources
➢ The Cortex-M has an on-chip interrupt controller called Nested Vector Interrupt Controller (NVIC) to interface the
CPU to different interrupt sources. It allows some degree of standardization among the ARM Cortex-Mx (M0, M1,
M3, and M4) family members.

➢ The NVIC of the ARM Cortex-M has room for the total of 255 interrupts and exceptions.

➢ The Cortex-M0+ CPU supports up to 32 non-core sources and 16 core sources.

▪ Core exception examples:


• when the CPU starts up (Power-up reset or RESET pin signal)

• when errors occur e.g., when the code tries to access a peripheral that hadn’t been enabled yet through
clock gating).
• when system services are requested. (Supervisor call; SVC instruction)
▪ Non-Core 32 interrupt sources (IRQ0-IRQ31):
• These interrupts are caused by peripheral modules, so they are manufacturer dependent.

➢ The lowest 1024 bytes (256 × 4 = 1024) of memory space are set aside for the interrupt vector table that maps
the interrupt request number IRQn to the interrupt vector and must not be used for any other function.
11
Selected Cortex-M0+ Core Exception Sources
Vector Address Vector # Source Description Priority
0x0000_0004 1 Reset CPU reset −3
Priority:
0x0000_0008 2 NMI Nonmaskable interrupt −2 The lower the number, the
0x0000_000C 3 HardFault Hard fault error −1 higher the priority

0x0000_002C 11 SVCall Call to supervisor with SVC instruction Programmable Programmable:


Means can be changed by
0x0000_0038 14 PendSV System-level service request Programmable program.
0x0000_003C 15 SysTick System timer tick Programmable
Reset: is caused by
• Asserting RESET pin which wakes the device from any mode.
• Power-on reset beginning with the on-chip regulator in full regulation and system clocking
generation from an internal reference.
Reset provides a way to start processing from a known set of initial conditions:
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
• LR is set to 0xFFFF_FFFF
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.

NMI: The non-maskable interrupt request to the NVIC is controlled by the external NMI signal.
The pin the NMI signal is multiplexed on, must be configured for the NMI function to generate
12
the non-maskable interrupt request.
Selected Cortex-M0+ Core Exception Sources
Vector Address Vector # Source Description Priority
0x0000_0004 1 Reset CPU reset −3
Priority:
0x0000_0008 2 NMI Nonmaskable interrupt −2 The lower the number, the
0x0000_000C 3 HardFault Hard fault error −1 higher the priority

0x0000_002C 11 SVCall Call to supervisor with SVC instruction Programmable Programmable:


Means can be changed by
0x0000_0038 14 PendSV System-level service request Programmable program.
0x0000_003C 15 SysTick System timer tick Programmable

HardFault: The catchall for assorted system failures that can take place such as accesses to bad memory, divide-by-zero errors
and illegal unaligned accesses.

SVCall: Exception handler invoked when a Supervisor Call (svc) instruction is executed.
PendSV & SysTick: System level interrupts triggered by software. They are typically used when running a RTOS to manage
when the scheduler runs and when context switches take place.

Beside these core exceptions, there are interrupts that are external to the core itself.

These interrupt lines are usually routed to vendor-specific peripherals on the MCU such as DMA engines or GPIOs.

All of these interrupts are configured via a peripheral known as the Nested Vectored Interrupt Controller (NVIC).

13
KL25Z Interrupt Sources and Interrupt Vector table
Vector address Vector # IRQ Description
0x0000_0040, 44, 48, 4C 16–19 0–3 Direct memory access controller Mapping IRQ number to interrupt vector:
0x0000_0058 22 6 Power management controller For example, if PORTD requests an interrupt:
1. The port control module signals the
0x0000_005C 23 7 Low leakage wake up
2
NVIC.
0x0000_0060, 64 24–25 8–9 I C communications 2. The NVIC will issue interrupt request
0x0000_0068, 6C 26–27 10–11 SPI communications #31 to the CPU.
0x0000_0070, 74, 78 28–30 12–14 UART communications 3. The CPU will read the vector table to
find the location of the ISR for IRQ #31
0x0000_007C 31 15 Analog to digital converter
(vector #47). In particular, it will read the
0x0000_0080 32 16 Comparator word starting at address 0x0000_00BC
0x0000_0084, 88, 8C 33–35 17–19 Timers and pulse-width modulation and load it into the PC so the ISR will
0x0000_0090, 94 36–37 20–21 Real-time clock alarm and seconds execute.
0x0000_0098 38 22 Programmable interval timer
0x0000_00A0 40 24 USB on-the-go
0x0000_00A4 41 25 Digital to analog converter
0x0000_00A8 42 26 Touch sense interface
0x0000_00AC 43 27 Main clock generator
0x0000_00B0 44 28 Low power timer
0x0000_00B8 46 30 Port control module, Port A pin detect
0x0000_00BC 47 31 Port control module, Port D pin detect

14
ARM Cortex-M NVIC
➢ If any enabled interrupts are requested, the NVIC selects the one with the highest priority and directs the CPU to start executing its ISR.

➢ The NVIC supports the 32 interrupt sources IRQ0 through IRQ31.

➢ Each source can be configured individually:


– Enabled or disabled
– Prioritized
– Set as pending; requested but not yet serviced

➢ Interrupt processing status can be read and modified

➢ The Wakeup Interrupt Controller WIC duplicates the interrupt masking of NVIC which enables NVIC to be 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.
NVIC Registers

Size in
Address Name bits Description Read/Write At RESET

Interrupt Set-Enable 0 No effect


0xE000E100 NVIC_ISER 32 Register 1 Enable associated Interrupt 0x00000000

Interrupt Clear-Enable 0 No effect


0xE000E180 NVIC_ICER 32 Register 1 Disable associated Interrupt 0x00000000

0 No effect
Interrupt Set-Pending
1 Change state of associated
0xE000E200 NVIC_ISPR 32 Register interrupt to pending
0x00000000

0 No effect
Interrupt Clear-Pending
1 Change state of associated
0xE000E280 NVIC_NCPR 32 Register interrupt to not pending
0x00000000

0xE000E400- NVIC_IPR0- 32 Eight interrupt Priority Each register has 4 fields to set Each is zero
0xE000E41C NVIC_IPR7 each Registers or read priorities of 4 IRQs. 0x00000000
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
bit zero (PM) of the programmable-interrupts mask core register PRIMASK:
– A PRIMASK.PM value of one prevents them.

– A PRIMASK.PM value of zero allows those exceptions.

– PRIMASK.PM bit is set to 0 on reset → Interrupts are enabled upon reset.

The PRIMASK register is accessed by the move special register instructions, MSR or MRS:
• MSR primask,<Rn> ; reads the PRIMASK register into general purpose register Rn
• MRS <Rd>,primask ; writes to the PRIMASK register from general purpose register Rd
In addition, Change Processor State instruction (CPS) changes the PRIMASK (in privilege mode):
• CPSID i ; set PRIMASK.PM to 1 to disable interrupts globally.
• CPSIE i ; set PRIMASK.PM to 0 to enable interrupts globally.
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
(2) Selectively:
➢ Each interrupt source can be enabled or disabled separately using two NVIC registers:

• Interrupt Set-Enable Register (ISER) and

• Interrupt Clear-Enable Register (ICER)

Each is 32 bits, with each bit corresponding to one IRQ, IRQ0 to IRQ31:

• To enable an interrupt source n, write a 1 to bit n in ISER.

• To disable an interrupt source n, write a 1 to bit n in ICER.

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.
Pending Interrupt
Pending Interrupt:
It is an interrupt that has been requested by a peripheral but is not yet serviced.

A pending state can be requested by writing to NVIC Set-Pending register NVIC_ISPR.

A pending state can be cleared by writing to NVIC Set-Clear register NVIC_ICPR.

CMSIS Interface:
• Uint32_t NVIC_GetPendingIRQ(IRQnum) Returns 1 if interrupt from IRQnum is pending
• NVIC_SetPendingIRQ(IRQnum) Sets interrupt pending flag for IRQnum
• NVIC_ClearPendingIRQ(IRQnum) Clears interrupt pending flag for IRQnum
Prioritizing Interrupts
➢ Each exception source has a priority that determines the order in which simultaneous exception requests are
handled.

➢ The priority of each interrupt is determined by a priority number, set by software in an NVIC register.

➢ The requested exception with the lowest priority number (highest priority) will be handled first.

➢ Priority numbers of some exceptions are fixed


– Reset: −3, highest priority
– NMI: −2
– Hard Fault: −1

➢ The rest of the exceptions and interrupts have lower priority and are programmable.
Programmable priority levels range from 0 to 3, with 3 has the lowest priority.
All IRQn have lower priorities that are programmable and stored in the 8 interrupt priority registers IPR0-7.

➢ Only the higher priority interrupts ae allowed to preempt a lower priority ISR.
The programmer is responsible to assign the proper priority to each IRQ to determine which interrupt may
preempt other’s ISRs.

➢ NVIC resolves priority and has the ability to capture the pending interrupts and keeps track of each one until
all are serviced.
Setting/Changing Interrupt Priority
➢ The NVIC contains eight interrupt priority registers (IPR0-7).
➢ Four interrupt sources per register.
➢ Each IPR has an 8-bit field for each interrupt sources, two of these bits specify the
priority level and six bits reserved.
➢ Multiple interrupt sources can have the same priority.

31:30 29:24 23:22 21:16 15:14 13:8 7:6 5:0

IPR0 IRQ3 reserved IRQ2 reserved IRQ1 reserved IRQ0 reserved

IPR1 IRQ7 reserved IRQ6 reserved IRQ5 reserved IRQ4 reserved

IPR2 IRQ11 reserved IRQ10 reserved IRQ9 reserved IRQ8 reserved

IPR3 IRQ15 reserved IRQ14 reserved IRQ13 reserved IRQ12 reserved

IPR4 IRQ19 reserved IRQ18 reserved IRQ17 reserved IRQ16 reserved

IPR5 IRQ23 reserved IRQ22 reserved IRQ21 reserved IRQ20 reserved

IPR6 IRQ27 reserved IRQ26 reserved IRQ25 reserved IRQ24 reserved

IPR7 IRQ31 reserved IRQ30 reserved IRQ29 reserved IRQ28 reserved


Setting/Changing Interrupt Priority

Values that can be stored in each 8-bit field in the interrupt priority register (IPR0-7)
– Priority level 0 0x00 0 (highest priority)
– Priority level 1 0x40 64
– Priority level 2 0x80 128
– Priority level 3 0xC0 192 (lowest)

CMSIS Interface:

NVIC_SetPriority(IRQnum, priority)
Special Cases of Prioritization
➢ Simultaneous exception requests:
– The exception with the lower priority number is serviced first, the other one is set pending.
When the one with higher priority is finished, the one pending starts execution.

– If multiple interrupts have the same priority number, the one with the lowest IRQ number takes
precedence for example IRQ3 precedes IRQ5.

➢ New exception requested while a handler is executing:


Only exceptions with a higher priority (lower priority number) can preempt an executing exception.

1. New exception has priority higher than current priority, then


» 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
➢ 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)
Initializing the Interrupt Vector Table

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

The rest of the IVT in the KL25Z4 MCUs assembly language file startup_MKL25Z4.s (IRQ23-31 out of 32)
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 on three levels :

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


• Different types of peripherals have interrupt configuration options. For example:
– DAC0 module can generate interrupts on buffer pointer limits
– PORTD can generate interrupt on logical event on a pin

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

3. The core to let it accept configurable interrupts


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

1 2 3
Configuration: Level 1 ─ Peripheral Module
(Example PORTD)
Here we will examine the Kinetis KL25Z’s PORT module
1
with its pin control in the pin control register (PCR) .
The Interrupt Request Condition IRQC field in the PCR
controls the pin condition which will generate interrupt. It
should be set according to the table. Code Condition Selected
0 Interrupt/DMA request disabled

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

Other Reserved, or for DMA

CMSIS interface:
PORTD->PCR[SW1_POS] = PORT_PCR_IRQC(9) | PORT_PCR_MUX(1) ;

Each port, PORTA or PORTD, is assigned only one IRQ number; IRQ30 for PORTA and IRQ31 for PORTD.
Therefore, when one of these IRQs occurs, the corresponding ISR should be able to identify which bit in the port
caused the interrupt.
This information is found in the port module Interrupt Status Flag Register (ISFR)
Configuration: Level 1 ─ Peripheral Module
(Example PORTD)
➢ The port module Interrupt Status Flag Register (ISFR), 32-bit, indicates which interrupts have been detected for
this port.
A bit value of one indicates the corresponding interrupt has been detected.
➢ The ISR needs to write a one to this bit to clear it to zero ! to prevent recurrent interrupts.
– With CMSIS-CORE interface, the ISFR is accessed as PORTD->ISFR.
The ISFR is part of the PORT module. One register for each port e.g., PORTA_ISFR, PORTD_ISFR…

w1c means write one to clear.


➢ Each ISF bit indicates the detection of the configured interrupt on the corresponding port bit number.
– 0 Configured interrupt is not detected.
– 1 Configured interrupt is detected.

➢ The corresponding bit is read only for pins that do not support interrupt generation.

➢ The ISF bit for a pin is also visible in the corresponding PCR register. Each flag can be cleared in either location.
➢ If the pin is configured for a level sensitive interrupt and the pin remains asserted, then the flag is set again
immediately after it is cleared (a should-be-avoided situation).
Configuration: Level 2 ─ NVIC
2

➢ Enable Selected Interrupt


We enable an interrupt source N by writing a 1 to bit N in the interrupt set enable register ISER.
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.
In our case PORTD_IRQHandler.

➢ Set Interrupt Priority


We set the interrupt priority in the corresponding field in registers IPR0-7.
The CMSIS-CORE API interface: NVIC_SetPriority(IRQnum, priority)
The priority parameter is set to 0, 1, 2, or 3.

➢ Pending
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:
Configuration Level 3 ─ Core
3

Finally, the processor core is configured to accept configurable interrupts by resetting the PRIMASK.PM flag to 0.

Note that when the CPU is reset or powers up, PM is set to zero, so interrupts are not ignored.

The PM bit is accessed:


1) In assembly use the instructions:
CPSID i to disable interrupts
CPSIE I to enable interrupts

2) CMSIS-CORE API provides these interfaces for accessing the PM flag:


Interrupt or Exception Processing Sequence

Interrupt 1. Entering
occurs Exception Sequence

Main Code Hardwired CPU ISR 2. Executing


(Background) response activities (Foreground) ISR

time

3. Exiting Exception
Sequence

Code operations
Hardware operations (Done transparently)
32
ENTERING AN EXCEPTION HANDLER

33
[1] Entering an Exception Handler (Done Transparently)
1. Finish current instruction (except for lengthy instructions)

The hardware itself implements the ARM


2. Push context (832-bit words) onto current stack (MSP or PSP)
Architecture Procedure Calling Standard (AAPCS).

3. Switch to handler/privileged mode, use main stack pointer MSP

4. Load PC with address of exception handler from Interrupt Vector Table.

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

6. Load IPSR with exception number and start executing code of exception handler.

➢ Interrupt latency:
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+.
34
1. Finish Current Instruction
➢ Most instructions are short and finish quickly in one cycle

➢ Some instructions may take many cycles to execute:

Load Multiple (LDM), Store Multiple (STM), Push, Pop, MULS (32 cycles for some CPU core implementations)
Waiting for such instructions to complete will delay interrupt response significantly.

➢ If one of these instructions is executing when the interrupt is requested, the processor does the following:

▪ abandons the instruction

▪ responds to the interrupt

▪ executes the ISR

▪ returns from interrupt

▪ restarts the abandoned instruction

35
2. Push Context onto Current Stack

, upon entering ISR

▪ 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
code can be regular C functions
(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.
36
▪ Stack grows toward smaller addresses
3. Switch to Handler/Privileged Mode

Reset

Thread
Mode.
MSP or PSP.

▪ Handler mode always uses Main SP Exception Starting


Processing Exception
Completed Processing

Handler Mode
MSP

37
4. Load PC With Address Of Exception Handler
The INT# is multiplied by 4 to fetch the interrupt vector from IVT and load it in PC.

Reset Interrupt
Service Routine start

Port D ISR PORTD_IRQHandler

Port A ISR PORTA_IRQHandler

Non-maskable Interrupt
Service Routine NMI_IRQHandler

Contains Port D Interrupt Vector 0x0000_00BC PORTD_IRQHandler


Contains Port A Interrupt Vector 0x0000_00B8 PORTA_IRQHandler

Contains Non-Maskable Interrupt Vector 0x0000_0008 NMI_IRQHandler


0x0000_0004 start
Contains Reset Interrupt Vector

38
Can Examine Vector Table With Debugger

▪ PORTD ISR is IRQ #31 (0x1F), so vector to handler


begins at 0x40+4*0x1F = 0xBC
▪ Why is the vector odd (0x0000_0455)?
▪ LSB of address indicates that handler uses Thumb code

39
5. Load LR With EXC_RETURN Code
▪ 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.

▪ EXC_RETURN value carries information on how to return:

▪ Which SP to restore registers from? MSP (0) or PSP (1)


◦ Previous value of SPSEL
▪ Which mode to return to? Handler (0) or Thread (1)
◦ Another exception handler may have been running when this exception was requested

EXC_RETURN Return Mode Return Stack Description

0xFFFF_FFF1 0 (Handler) 0 (MSP) Return to exception handler

0xFFFF_FFF9 1 (Thread) 0 (MSP) Return to thread with MSP

0xFFFF_FFFD 1 (Thread) 1 (PSP) Return to thread with PSP

40
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

41
EXITING AN EXCEPTION HANDLER

42
[3] Exiting an Exception Handler
1. Execute instruction triggering exception return processing
There is no “RETURN FROM INTERRUPT” instruction. Instead use regular instruction:
i. BX LR - Branch to address in LR by loading PC with LR contents.
ii. POP …, PC - Pop address from stack into PC.
… 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
ii. POP used if EXC_RETURN has been saved on stack

2. Select return stack, restore context from that stack


i. Check EXC_RETURN (bit 2) to determine from which SP to pop the context
ii. Pop the registers from that stack
SP points here after handler

SP points here during handler

3. Resume execution of code at restored address


43
1. Execute Instruction for Exception Return

➢ The processor saves an EXC_RETURN value to the LR on


exception entry. The exception mechanism relies on this value to
detect when the processor has completed an exception handler:
▪Bits[31:4] of an EXC_RETURN value are 0xFFFFFFF.
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
0xFFFFFFF1
detects that the operation is not a normal branch operation and, main stack MSP.
Execution uses MSP after return.
instead, that the exception is complete. As a result, it starts the
Return to Thread mode.
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
• Bit2 indicates PSP
• Bit3 indicates MSP
44
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

SP points here after handler

SP points here during handler

45
EXECUTING AN EXCEPTION HANDLER

46
[2] Executing The Exception Handler
Rules to write an exception handler:
▪ No arguments or return values – void is only valid type

▪ Name the ISR according to CMSIS-CORE system exception names, to ensure that the software toolchain places
ISR addresses in the IVT correctly.
The linker will load the vector table with this handler rather than the default handler.
Examples:
▪ void PORTA_IRQHandler(void); PORTA_IRQHandler,
▪ void RTC_IRQHandler(void); RTC_IRQHandler, etc.

▪ Keep it short and simple: Much easier to debug and improves system response time.

▪ In the start of the ISR, clear pending interrupt


▪ Call NVIC_ClearPendingIRQ(IRQnum)

▪ In case this IRQn can possibly be caused by more than one event, identify the exact cause of the interrupt.

▪ Complete the body of the ISR

▪ Make sure to clear interrupting flag at the end of the ISR before the “Return” instruction.
47 This step is essential to avoid recurrent interrupts from the same source.
Differences Between Interrupt and Subroutine Call (BL)
➢ A BL instruction is used by the programmer in the sequence of instructions
➢ The interrupt is caused by a hardware event; it comes at any time.

➢ A BL instruction automatically saves only PC of the next instruction on the stack.


➢ Before servicing an interrupt, the LP, R12, R3–R0, xPSR (flag register) in addition to PC
are automatically saved on stack.

➢ The BL instruction does not change the CPU execution mode.


➢ An interrupt puts the CPU in the Handler Mode.

➢ 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.
➢ When returning from the interrupt handler, the registers saved when the CPU entered into
ISR (the xPSR, R15, R14, R12, R3–R0 registers) are restored from the top of stack.

48
EXAMPLE USING PORT MODULE AND
EXTERNAL INTERRUPTS

49
Example System with Interrupt

▪ Goal: Change color of RGB LED each time the switch is pressed

▪ We can achieve that by letting the CPU execute an infinite loop of instructions that keeps polling the state of
the switch and change the LED accordingly. (We did that before in GPIO lecture)

▪ This polling scheme is wasteful to the CPU time as the CPU becomes unavailable to do anything else useful.

▪ Try interrupts: Use special hardware in MCU to detect event, run specific code (interrupt service routine - ISR)
in response.

50
KL25Z GPIO Ports with Interrupts
▪ The KL25Z has five GPIO ports: Port A (PTA)
through Port E (PTE).

▪ Not all port bits are available on the MCU pins


(package-dependent).

▪ For the KL25Z, only PORTA and PORTD are


capable of generating interrupts.

▪ Some peripherals have optional wakeup capability.


A wakeup interrupt controller (WIC) enables the
NVIC to be turned off to reduce power when
the system is idle or sleeping.
The WIC duplicates the interrupt masking of the
NVIC and wakes up the NVIC if a connected
interrupt is requested, ensuring it is processed
and not lost.

51
FREEDOM KL25Z Physical Set-up for The Example

Switch Input

Ground

52
Program Requirements & Design
RGB
LED
SW ISR count Main

(does initialization,
then updates LED
ISR Task
based on count)
Global Variable

▪ Req1: When Switch SW is pressed, ISR will increment count variable

▪ Req2: Main code will light LEDs according to count value in binary sequence (Blue: 4, Green: 2, Red: 1)

▪ Req3: Main code will toggle its debug line DBG_MAIN each time it executes

▪ Req4: ISR will raise its debug line DBG_ISR (and lower main’s debug line DBG_MAIN) whenever it is
executing
▪ The ISR and the main code share the count value.

53
Building a Program – Break into Pieces
▪ First break into threads, then break thread into steps

▪ Main thread:
◦ First initialize system:
 initialize switch: configure the pin connected to the switch to be input
 initialize LEDs: configure the pins connected to the LEDs to be outputs
 initialize interrupts: initialize the interrupt controller
◦ Then repeat
 Update LEDs based on count
▪ Switch ISR:
◦ Update count

▪ Determine which variables ISRs will share with main thread


▪ This is how ISR will send information to main thread
▪ Mark these shared variables as volatile (more details ahead)
▪ Ensure access to the shared variables is atomic (more details ahead)
54
Where Do the Pieces Go?

▪ main
▪ top level of main thread code
▪ switches
▪ #defines for switch connections
▪ declaration of count variable
▪ Code to initialize switch and interrupt hardware
▪ ISR for switch

▪ LEDs
▪ #defines for LED connections
▪ Code to initialize and light LEDs

▪ debug_signals
▪ #defines for debug signal locations
▪ Code to initialize and control debug lines

55
Configure MCU to Respond to the Interrupt

1) Set up peripheral module to generate interrupt


▪ We’ll use PORTA Module in this example

2) Set up NVIC

3) Set global interrupt enable


▪ Use CMSIS Macro: __enable_irq();

56
Set Up Port Module

Port Module

▪ Port Module connects external pins to NVIC (and other devices)


▪ Relevant registers
▪ PCR - Pin control register (one per pin, 32 per port)
◦ Each register corresponds to an input pin
▪ ISFR - Interrupt status flag register (one per port)
◦ Each bit corresponds to an input pin
◦ Bit is set to 1 if an interrupt has been detected

57
Pin Control Register

▪ ISF indicates if interrupt has been detected - different way IRQC Configuration
to access same data as ISFR 0000 Interrupt Disabled
…. DMA, reserved
▪ IRQC field of PCR defines behavior for external hardware
1000 Interrupt when logic zero
interrupts
1001 Interrupt on rising edge

▪ Can also trigger direct memory access (not covered here) 1010 Interrupt on falling edge
1011 Interrupt on either edge
1100 Interrupt when logic one
… reserved

58
Switch Interrupt Initialization
void init_switch(void) {
/* enable clock for port A */
SIM->SCGC5 |= SIM_SCGC5_PORTA_MASK;
/* Select GPIO and enable pull-up resistors and interrupts
on falling edges for pin connected to switch */
PORTA->PCR[SW_POS] |= PORT_PCR_MUX(1) |
PORT_PCR_PS_MASK | PORT_PCR_PE_MASK |
PORT_PCR_IRQC(0x0a);
/* Set port A switch bit to input */
PTA->PDDR &= ~MASK(SW_POS);
/* Enable Interrupts */
NVIC_SetPriority(PORTA_IRQn, 128);
NVIC_ClearPendingIRQ(PORTA_IRQn);
NVIC_EnableIRQ(PORTA_IRQn);
61
}
Main Function
int main (void) {
init_switch();
init_RGB_LEDs();
init_debug_signals();
__enable_irq(); // enable interrupts globally

while (1) {
DEBUG_PORT->PTOR = MASK(DBG_MAIN_POS);
control_RGB_LEDs(count&1, count&2, count&4);
__wfi(); // sleep now, wait for interrupt
}
}
The wfi instruction suspends execution until interrupt occurs.
The wfi instruction suspends execution until one of the following events occurs:
▪ An exception

▪ An interrupt becomes pending that would preempt if PRIMASK.PM was clear

▪ A Debug Entry request, regardless of whether debug is enabled

It is intended for power saving only.


When writing software assume that wfi might behave as a NOP operation.
62
ISR
void PORTA_IRQHandler(void) {
DEBUG_PORT->PSOR = MASK(DBG_ISR_POS);
// clear pending interrupt from PORTA in NVIC
NVIC_ClearPendingIRQ(PORTA_IRQn);
// if the interrupt was caused by the switch, increment count
if ((PORTA->ISFR & MASK(SW_POS))) {
count++;
}
// clear status flags in PORTA to prevent recurrent interrupts
PORTA->ISFR = 0xffffffff;
DEBUG_PORT->PCOR = MASK(DBG_ISR_POS);
}

63
SHARING DATA SAFELY BETWEEN ISRs
AND OTHER THREADS

64
Overview

▪ Volatile data:
Can be updated outside of the program’s immediate control

▪ Non-atomic shared data:


Can be interrupted partway through read or write.
It is vulnerable to race conditions.

65
Volatile Data
▪ Cases of volatile data:
▪ Memory-mapped peripheral register – register changes on its own
▪ Global variables modified by an ISR – ISR changes the variable
▪ Global variables in a multithreaded application – another thread or ISR changes the variable

▪ Compilers assume that variables in memory do not change spontaneously, and


optimize based on that belief so they generate code that:
▪ Don’t reload a variable from memory if current function hasn’t changed it
▪ Read variable from memory into register (faster access) and keep using register not memory.
▪ Write back to memory at end of the procedure, or before a procedure call, or when compiler
runs out of free registers.

▪ This optimization can fail


▪ Example: reading from input port, polling for key press (SW_0)
▪ while (SW_0) ;
Will read from SW_0 once and reuse that value, while the value changes outside the
executing function.
This behavior will generate an infinite loop triggered by SW_0 being true.
66
The Volatile Directive

▪ Need to tell compiler which variables may change outside of its control.
▪ Use volatile keyword in the variable definition to force compiler to reload these variables from memory for each use:
Example:
volatile unsigned int num_ints;

▪ Pointer to a volatile int


Example:
volatile int * var; // or
int volatile * var;

Now each C source reference to the variable (e.g., status register) will result in an assembly language load instruction.

67
Atomic Operations
▪ An atomic operation is a sequence that once started cannot be interrupted until completion.
Examples:
• Execution of a single instruction
• A sequence of actions completed in hardware

▪ Instructions on the ARM Cortex-M processor are atomic except for some instructions like store and load multiple,
STM, LDM, PUSH, and POP.

▪ To make a section of code atomic, we can run that code with PRIMASK.PM=1.
In this way, interrupts will not be able to break apart the sequence.
Interrupts that are requested while PRIMASK.PM =1 are not dismissed, but simply be pending until PRIMASK.PM=0.
Make sure the atomic section is short as it blocks interrupts and slows down system response.

▪ To implement an atomic operation, we will


1. save the current value of the PRIMASK register,
2. disable interrupts by setting PRIMASK.PM =1,
3. execute the operation, and
4. restore the PRIMASK back to its previous value.
68
Non-Atomic Shared Data
Examples:
▪ Accessing changing hardware values, e.g., getting all 16 bits of timer value through 8-bit bus
(may change between byte reads).

▪ Accessing values changed by ISRs, e.g. getting time of day that is updated by ISR.

▪ Accessing a variable shared among tasks e.g., a single counter of errors or events incremented
by more than one task.

69
Non-Atomic Shared Data Example
void GetDateTime(DateTimeType * DT){
▪ Want to keep track of current time and date DT->day = TimerVal.day;
DT->hour = TimerVal.hour;
DT->minute = TimerVal.minute;
▪ Use 1 Hz interrupt from timer
DT->second = TimerVal.second;
}
▪ System
▪ TimerVal structure tracks time and days since
void DateTimeISR(void){
some reference event TimerVal.second++;
▪ TimerVal’s fields are updated by periodic 1 Hz if (TimerVal.second > 59){
TimerVal.second = 0;
timer ISR
TimerVal.minute++;
if (TimerVal.minute > 59) {
TimerVal.minute = 0;
TimerVal.hour++;
if (TimerVal.hour > 23) {
TimerVal.hour = 0;
TimerVal.day++;
… etc.
}

70
Non-Atomic Shared Data Example Problem: Checking the Time
▪ Problem
▪ An interrupt at the wrong time will lead to half-updated data in DT

▪ Failure Case
▪ TimerVal is {10, 23, 59, 59} … (10th day, time is 23:59:59)
▪ Task code calls GetDateTime(), which starts copying the TimerVal fields to DT: day = 10, hour = 23
▪ A timer interrupt occurs, which updates TimerVal to {11, 0, 0, 0}
▪ GetDateTime() resumes executing, copying the remaining TimerVal fields to DT: minute = 0, second = 0
▪ DT now has a time stamp of {10, 23, 0, 0}.
▪ The system thinks time just jumped backwards one hour!

▪ Fundamental problem – “race condition”


▪ Preemption enables ISR to interrupt other code and possibly overwrite data
▪ Must ensure atomic (indivisible) access to the object
◦ Native atomic object size depends on processor’s instruction set and word size.
Is 32 bits for ARM

71
Examining the Problem More Closely

▪ Must protect any data object which both


▪ (1) requires multiple instructions to read or write (non-atomic access), and
▪ (2) is potentially written by an ISR

▪ How many tasks/ISRs can write to the data object?


▪ One? Then we have one-way communication
◦ Must ensure the data isn’t overwritten partway through being read
 Writer and reader don’t interrupt each other
▪ More than one?
◦ Must ensure the data isn’t overwritten partway through being read
 Writer and reader don’t interrupt each other
◦ Must ensure the data isn’t overwritten partway through being written
 Writers don’t interrupt each other

72
Definitions

▪ Race condition:
Anomalous behavior due to unexpected critical dependence on the relative timing of
events. Result of example code depends on the relative timing of the read and write
operations.

▪ Critical section:
A section of code which creates a possible race condition. The code section can only
be executed by one process at a time. Some synchronization mechanism is required at
the entry and exit of the critical section to ensure exclusive use.

73
Solution: Briefly Disable Preemption
▪ Prevent preemption within
critical section. Use disable interrupt to void GetDateTime(DateTimeType * DT){
prevent data race conditions with code uint32_t m;
needing atomicity
▪ If an ISR can write to the shared data m = __get_PRIMASK();
object, need to disable interrupts __disable_irq();
▪ save current interrupt
masking state in m
DT->day = TimerVal.day;
▪ disable interrupts
DT->hour = TimerVal.hour;
▪ Restore previous state afterwards because
interrupts may have already been disabled DT->minute = TimerVal.minute;
for another reason DT->second = TimerVal.second;
▪ Use CMSIS-CORE to save, control and __set_PRIMASK(m);
restore interrupt masking state }

▪ Avoid if possible
▪ Disabling interrupts delays response to all
other processing requests
▪ Make this time as short as possible (e.g. a
few instructions)

74
Summary for Sharing Data

▪ Identify shared data

▪ Determine which shared data is too large to be handled atomically by default


▪ This needs to be protected from preemption, e.g. disable interrupt(s).

▪ Declare (and initialize) shared variables as volatile in main file (or globals.c)
▪ volatile int my_shared_var=0;

▪ Update extern.h to make these variables available to functions in other files


▪ volatile extern int my_shared_var;
▪ #include “extern.h”  Should appear in every file which uses these shared variables

▪ When using long (non-atomic) shared data, save, disable and restore interrupt masking status
▪ CMSIS-CORE interface:
 __disable_irq()
 __get_PRIMASK()
 __set_PRIMASK()

75
Interrupt Jargon
• Interrupt Request (IRQ): This is the signal with which some device, such as a timer
overflow flag or an external signal, requests that it be serviced.

• Asynchronous Event: An event that can happen at any time in the MCU instruction execution
cycle.

• Peripheral Interrupt Enable: A bit in an interrupting peripheral that enables the peripheral
to generate an interrupt request.

• Interrupt Service Routine (ISR) / Interrupt Handler : The software written to deal with
the interrupt request for a particular interrupt source.

• Interrupt Flag Clearing: When an interrupt occurs (an interrupt flag is raised), the ISR
must clear the flag that caused the interrupt.

▪ Interrupt Mask: A control bit that stops (masks) interrupt requests from being acted
upon by the CPU. The CPU will have instructions that can mask or unmask interrupts.

▪ Interrupt Prioritization: When multiple interrupts occur simultaneously the system must
have a way to establish which of them is the most important and should be serviced first.
Also, it determines whether a new interrupt can pre-empt a running ISR.
76
Interrupt Jargon

▪ Interrupt Vector: When an interrupt occurs the CPU fetches the starting address of
the ISR from a specific and dedicated location in memory. The ISR starting address is
called the vector and the memory location where it is stored is called the vector location
or vector address.

▪ Interrupt Vector Table: The interrupt vectors are stored in a table in memory called
the interrupt vector table IVT.

• Interrupt Latency: The time between the moment when the interrupt request is
asserted and the moment the CPU starts to execute the ISR. Three factors may
contribute o the interrupt latency:
1. The number of clock cycles needed to complete the interrupted instruction if it should
be completed
2. The number of clock cycles needed to push the necessary registers onto the stack
3. The interrupt priority in case of simultaneous higher priority interrupts

77
Interrupt Jargon

▪ Pending Interrupt: When an interrupt request has occurred and the ISR for that interrupt
has not been entered, the interrupt is said to be pending.
• Nested Interrupts: While executing an ISR, another interrupt is activated. If the new
interrupt has a higher priority, it will preempt the lower priority interrupt.
If the new interrupt has a lower or equal priority it will not get service and will be pending
until ISR completes.

78

You might also like