Embedded System Design 22ECE61
MODULE 3
ARM EMBEDDED SYSTEMS
Overview of exceptions and interrupts, Exception types, Overview of
interrupt management, Definitions of priority, Vector table and vector table
relocation, Interrupt inputs and pending behaviours, Exception sequence
overview, Details of NVIC registers for interrupt control.
Exceptions and Interrupts
Overview of exceptions and interrupts
Interrupts are a common feature available in almost all microcontrollers. Interrupts are events
typically generated by hardware (e.g., peripherals or external input pins) that cause changes in
program flow control outside a normal programmed sequence (e.g., to provide service to a
peripheral). When a peripheral or hardware needs service from the processor, typically the
following sequence would occur: 1. The peripheral asserts an interrupt request to the processor
2. The processor suspends the currently executing task 3. The processor executes an Interrupt
Service Routine (ISR) to service the peripheral, and optionally clear the interrupt request by
software if needed 4. The processor resumes the previously suspended task All Cortex-M
processors provide a Nested Vectored Interrupt Controller (NVIC) for interrupt handling. In
addition to interrupt requests, there are other events that need servicing and we called them
“exceptions.” In ARM terminology, an interrupt is one type of exception. Other exceptions in
Cortex-M processors included fault exceptions and other system exceptions to support the OS
(e.g., SVC instruction). The pieces of program code that handle exceptions are often called
exception handlers. They are part of the compiled program image. In a typical Cortex-M
microcontroller, the NVIC receives interrupt requests from various sources, as shown in Figure
7.1.
Embedded System Design 22ECE61
The Cortex-M3 and Cortex-M4 NVIC supports up to 240 IRQs (Interrupt Requests), a Non-
Maskable Interrupt (NMI), a SysTick (System Tick) timer interrupt, and a number of system
exceptions. Most of the IRQs are generated by peripherals such as timers, I/O ports, and
communication interfaces (e.g., UART, I2C). The NMI is usually generated from peripherals
like a watchdog timer or Brown-Out Detector (BOD). The rest of the exceptions are from the
processor core. Interrupts can also be generated using software.
Exception types
The Cortex-M processors provide a feature-packed exception architecture that supports a
number of system exceptions and external interrupts. Exceptions are numbered 1e15 for system
exceptions and 16 and above for interrupt inputs (inputs to the processor, but not necessarily
accessible on the I/O pins of the package).
Most of the exceptions, including all interrupts, have programmable priorities, and a few
system exceptions have fixed priority. Different Cortex-M3 or Cortex-M4 microcontrollers can
have different numbers of interrupt sources (from 1e240) and different numbers of priority
levels. This is because chip designers can configure the Cortex-M3 or Cortex-M4 design source
code for different application requirements.
Embedded System Design 22ECE61
Embedded System Design 22ECE61
The reason for using a different number system in CMSIS-Core access functions is to allow
slightly better efficiency in some of these API functions (e.g., when setting up priority levels).
The interrupt number and enumeration definitions of interrupts are device-specific, and are
defined in device-specific header files provided by microcontroller vendors, in a “typedef”
section called “IRQn.” The enumeration definitions are used by various NVIC access functions
in the CMSIS-Core.
Overview of interrupt management
The Cortex-M processors have a number of programmable registers for managing interrupts
and exceptions. Most of these registers are inside the NVIC and System Control Block (SCB).
(Physically the SCB is implemented as part of the NVIC but the CMSIS-Core defines the
registers in separated data structures.) There are also special registers inside the processor core
for interrupt masking (e.g., PRIMASK, FAULTMASK, and BASEPRI).
To make it easier to manage interrupts and exceptions, the CMSIS-Core provides a number of
access functions. The NVIC and SCB are located inside the System Control Space (SCS)
address range from 0xE000E000, with a size of 4KB. The SCS also contains registers for the
SysTick timer, Memory Protection Unit (MPU), debug registers, etc. Almost all of the registers
in this address range can only be accessed by code running in privileged access level. The only
exception is a register called the Software Trigger Interrupt Register (STIR), which can be set
up to be accessible in unprivileged mode.
Embedded System Design 22ECE61
For general application programming, the best practice is to use the CMSIS-Core access
functions. For example, the most commonly used interrupt control functions are shown in Table
7.4.
After reset, all interrupts are disabled and given a priority-level value of 0. Before using any
interrupts, you need to:
• Set up the priority level of the required interrupt (this step is optional)
• Enable the interrupt generation control in the peripheral that triggers the interrupt
• Enable the interrupt in the NVIC
Definitions of priority
In the Cortex-M processors (both ARMv6-M and ARMv7-M), whether and when an exception
can be accepted by the processor and get its handler executed can be dependent on the priority
of the exception and the current priority of the processor. A higher-priority (smaller number in
priority level) exception can pre-empt a lower-priority (larger number in priority level)
exception; this is the nested exception/interrupt scenario. Some of the exceptions (reset, NMI,
and HardFault) have fixed priority levels.
Embedded System Design 22ECE61
Their priority levels are represented with negative numbers to indicate that they are of higher
priority than other exceptions. Other exceptions have programmable priority levels, which
range from 0 to 255.
The design of the Cortex-M3 and Cortex-M4 processors support three fixed highest-priority
levels and up to 256 levels of programmable priority (with a maximum of 128 levels of pre-
emption). The actual number of available programmable priority levels is decided by silicon
chip designers. Most Cortex-M3 or Cortex-M4 chips have fewer supported levels.
Interrupt-priority levels are controlled by priority-level registers, with width of 3 bits to 8 bits.
For example, if only 3 bits of priority level are implemented in the design, a priority-level
configuration register will look like Figure 7.2.
For the example in Figure 7.2, because bit 4 to bit 0 are not implemented, they are always read
as zero, and writes to these bits will be ignored. With this setup, we have possible priority levels
of 0x00 (high priority), 0x20, 0x40, 0x60, 0x80, 0xA0, 0xC0, and 0xE0 (the lowest) (Figure
7.4). Similarly, if 4 bits of priority level are implemented in the design, a priority-level
configuration register will look like Figure 7.3.
This allows 16 levels of programmable priority level (also illustrated in Figure 7.4). The more
bits are implemented, the more priority levels will be available. However, more priority bits
can also increase gate counts and hence the power consumption of the silicon designs.
For ARMv7-M architecture, the minimum number of implemented priority register widths is
3 bits (eight levels). In Cortex-M3 and Cortex-M4 processors, all the priority-level registers
have a reset value of 0.
Embedded System Design 22ECE61
The reason for removing the least significant bit (LSB) of the priority-level registers instead of
the most significant bit (MSB) is to make it easier to port software from one Cortex-M device
to another. In this way, a program written for devices with 4-bit priority configuration registers
is likely to be able to run on devices with 3-bit priority configuration registers.
If the MSB is removed instead of the LSB, you might get an inversion of the priority
arrangement when porting an application from one Cortex-M chip to another. For example, if
an application uses priority level 0x05 for IRQ #0 and level 0x03 for IRQ #1, IRQ #1 should
have higher priority. But when MSB bit 2 is removed, IRQ #0 will become level 0x01 and have
a higher priority than IRQ #1.
Embedded System Design 22ECE61
For example, if the width of the configuration registers is 3 (bit 7 to bit 5 are available) and
priority group is set to 5, you can have four levels of group/ pre-empt priority levels (bit 7 to
bit 6), and inside each group/pre-empt level there are two levels of sub-priority (bit 5) (Figure
7.5). With settings as shown in Figure 7.5, the available priority levels are illustrated in Figure
7.6.
Embedded System Design 22ECE61
For the same design, if the priority group is set to 0x1, there can be only eight group priority
levels and no further sub-priority levels inside each pre-empt level. (Bit [1:0] of priority level
register is always 0.) The definition of the priority level configuration registers is shown in
Figure 7.7, and the available priority levels are illustrated in Figure 7.8.
Embedded System Design 22ECE61
If a Cortex-M3/M4 device has implemented all 8 bits in the priority-level configuration
registers, the maximum number of pre-emption levels it can have is only 128, using a priority
group setting of 0. The priority fields definition is shown in Figure 7.9. When two interrupts
are asserted at the same time with exactly the same group/ pre-empt priority level and sub-
priority level, the interrupt with the smaller exception number has higher priority. (IRQ #0 has
higher priority than IRQ #1.)
Embedded System Design 22ECE61
Vector table and vector table relocation
When the Cortex-M processor accepts an exception request, the processor needs to determine
the starting address of the exception handler (or ISR if the exception is an interrupt). This
information is stored in the vector table in the memory. By default, the vector table starts at
memory address 0, and the vector address is arranged according to the exception number times
four (Figure 7.10). The vector table is normally defined in the startup codes provided by the
microcontroller vendors.
The vector table used in startup also contains the initial value of the main stack pointer (MSP).
It is needed because some exception such as NMI could happen as the processor just came out
from reset and before any other initialization steps are executed.
arting addresses of exception handlers. Usually, the starting address (0x00000000) should be
boot memory, and it will usually be either flash memory or ROM devices, and the value cannot
be changed at run-time. However, in some applications it is useful to be able to modify or
define exception vectors at run-time.
Embedded System Design 22ECE61
In order to handle this, the Cortex-M3 and Cortex-M4 processors support a feature called
Vector Table Relocation. The Vector Table Relocation feature provides a programmable register
called the Vector Table Offset Register (VTOR).
This register defines the starting address of the memory being used as the vector table (Figure
7.11). Please note that this register is slightly different between Cortex-M3 revision r2p0 and
revision r2p1. In CortexM3 r2p0 or older versions, the vector table can only be in the CODE
region or the SRAM region. This restriction is removed from Cortex-M3 r2p1 and Cortex-M4.
Example 1: 32 interrupt sources in the microcontroller The vector table size is (32 (for
interrupts) þ16 (for system exception space)) x 4 (bytes for each vector) ¼ 192 (0xC0).
Extending it to the next power of two makes it 256 bytes. So the vector table base address can
be programmed as 0x00000000, 0x00000100, 0x00000200, and so on.
Example 2: 75 interrupt sources in the microcontroller The vector table size is (75 (for
interrupts) þ16 (for system exception space)) x 4 (bytes for each vector) ¼ 364 (0x16C).
Extending it to the next power of two makes it 512 bytes. So the vector table base address can
be programmed as 0x00000000, 0x00000200, 0x00000400, and so on.
Since the minimum number of interrupt is 1, the minimum vector table alignment is 128 bytes.
Therefore the lowest 7 bits of the VTOR are reserved and forced to zero. The vector table
relocation feature can be useful in a number of cases:
1. Devices with boot loader (Figure 7.12) In some microcontrollers there are multiple
program memories: boot ROM and user flash memory. The boot loaders are often pre-
programmed in the boot ROM by the microcontroller manufacturer. When the
microcontrollers start, they first execute the boot loader code in the boot ROM, and
before branching to the user application
2. Applications load into RAM (Figure 7.13) In some situations, the application could be
loaded from an external source to the RAM and then get executed. It could have been
stored on an SD card, or even need to be transferred through a network. In this case, a
program stored in onchip memory for booting will need to initialize some hardware,
Embedded System Design 22ECE61
copy the externally stored application into RAM, update the VTOR and then execute
the externally stored application.
3. Dynamic changing of vector In some cases, you might want to have multiple
implementations of an interrupt handler in ROM and want to switch between them at
different stages of the application. In this case, you can copy the vector table from the
program memory to SRAM, and program the VTOR to point to the vector table in
SRAM. Since the contents in SRAM can be modified at any time, you can then modify
the interrupt vector easily at different stages of the application.
In a minimal setup, the vector table needs to provide the initial MSP value and the reset
vector for the system to boot up. In addition, depending on your application, you might
also need to include the NMI vector, as some devices could have NMI triggered as soon
as it started, and the HardFault vector for error handling.
Embedded System Design 22ECE61
Interrupt inputs and pending behaviors
There are various status attributes applicable to each interrupt:
• Each interrupt can either be disabled (default) or enabled
• Each interrupt can either be pending (a request is waiting to be served) or not pending
• Each interrupt can either be in an active (being served) or inactive state
To support this, the NVIC contains programmable registers for interrupt enable control,
pending status, and read-only active status bits.
Different combinations of these status attributes are possible. For example, while you
are serving an interrupt (active), you can disable it, and then a new request for the same
interrupt arrives again before the interrupt exits, causing the interrupt to be disabled
while active and with a pending status. An interrupt request can be accepted by the
processor if:
• The pending status is set,
• The interrupt is enabled, and
• The priority of the interrupt is higher than the current level (including interrupt
masking register configuration).
The NVIC is designed to support peripherals that generate pulsed interrupt requests as
well as peripherals with high level interrupt request. There is no need to configure any
NVIC register to select either interrupt type.
For pulsed interrupt requests, the pulse must be at least one clock cycle long. For level
triggered interrupts, the peripheral requesting service asserts the request signal until it
is cleared by an operation inside the ISR (e.g., write to a register to clear the interrupt
request). The request signals received by the NVIC are active high, although the
external interrupt request at the I/O pin level could be active low.
The pending status of the interrupts are stored in programmable registers in the NVIC.
When an interrupt input of the NVIC is asserted, it causes the pending status of the
interrupt to be asserted.
The pending status remains high even if the interrupt request is de-asserted. In this way,
the NVIC can work with pulsed interrupt requests. The pending status means it is put
into a state of waiting for the processor to serve the interrupt. In some cases, the
processor serves the request as soon as an interrupt becomes pending.
However, if the processor is already serving another interrupt of higher or equal
priority, or if the interrupt is masked by one of the interrupt masking registers, the
pended request will remain until the other interrupt handler is finished, or when the
interrupt masking is cleared.
This is different from traditional ARM processors. Previously, the devices that generate
interrupts, such as interrupt request (IRQ)/fast interrupt request (FIQ), must hold the
request until they are served. Now, with the pending status registers in the NVIC
holding the requests, an occurred interrupt will be handled even if the source requesting
the interrupt deserts its request signal.
When the processor starts to process an interrupt request, the pending status of the
interrupt is cleared automatically, as shown in Figure 7.14.
Embedded System Design 22ECE61
When the interrupt is being served, it is in the active state. Please note that in the
interrupt entry sequence, a number of registers are pushed onto the stack automatically.
This is called stacking. Meanwhile, the starting address of the ISR is fetched from the
vector table.
In many microcontroller designs, the peripherals operate with level-triggered interrupts
and therefore the ISR will have to clear the interrupt request manually; for example, by
writing to a register in the peripheral. After the interrupt service is completed, the
processor carries out an exception return (covered in section 7.7.4). The registers that
were automatically stacked are restored and the interrupted program is resumed. The
active status of the interrupt is also cleared automatically.
When an interrupt is active, you cannot accept the same interrupt request again until it
has completed and terminated with an exception return (sometimes called an exception
exit).
The pending status of interrupts are stored in interrupt pending status registers, which
are accessible from software code. So you can clear the pending status of an interrupt
or set it manually. If an interrupt request arrives when the processor is serving another
higher-priority interrupt and the pending status is cleared before the processor starts
responding to the pending request, the request is cancelled and will not be served
(Figure 7.15).
If a peripheral continuously asserts the interrupt request, and the software attempts to
clear the pending status, the pending status will be set again (Figure 7.16).
If an interrupt source continues to assert its interrupt request after it has been serviced,
the interrupt will be in the pending state again and will get serviced by the processor
again. This is shown in Figure 7.17.
For pulsed interrupt requests, if an interrupt request signal is pulsed several times
before the processor starts processing, the request will be treated as one single interrupt
request, as illustrated in Figure 7.18.
Embedded System Design 22ECE61
Embedded System Design 22ECE61
The pending status of an interrupt can be set again when it is being served. For example, in
Figure 7.19 a new interrupt request arrived while the previous request was still being served,
and this caused a new pending status and therefore the processor needs to serve this interrupt
again after the first ISR is completed.
Please note that the pending status of an interrupt can be set even when the interrupt is disabled.
In this case, when the interrupt is enabled later, it can be triggered and get served. In some cases
this might not be desirable, so in this case you will have to clear the pending status manually
before enabling the interrupt in the NVIC.
In general the NMI request behavior is the same as interrupts. Unless an NMI handler is already
running, or the processor is halted or in a locked up state, a NMI request will be executed
almost immediately because it has the highest priority and cannot be disabled.
Embedded System Design 22ECE61
Exception sequence overview
Acceptance of exception request
The processor accepts an exception if the following conditions are met:
• The processor is running (not halted or in reset state)
• The exception is enabled (with special cases for NMI and HardFault exceptions, which are
always enabled) • The exception has higher priority than the current priority level
• The exception is not blocked by an exception masking register (e.g., PRIMASK)
Note that for the SVC exception, if the SVC instruction is accidentally used in an exception
handler that has the same or higher priority than the SVC exception itself, it will cause the
HardFault exception handler to execute.
Exception entrance sequence
An exception entrance sequence contains several operations:
• Stacking of a number of registers, including return address to the currently selected stack.
This enables an exception handler to be written as a normal C function. If the processor was in
Thread mode and was using the Process Stack Pointer (PSP), the stack area pointed to by the
PSP will be used for this stacking. Otherwise the stack area pointed to by the Main Stack
Pointer (MSP) will be used.
• Fetching the exception vector (starting address of the exception handler/ISR). This can
happen in parallel to the stacking operation to reduce latency
. • Fetching the instructions for the exception handler to be executed. After the starting address
of the exception handler is determined, the instructions can be fetched.
Embedded System Design 22ECE61
• Update of various NVIC registers and core registers. This includes the pending status and
active status of the exception, and registers in the processor core including the Program Status
Register (PSR), Link Register (LR), Program Counter (PC), and Stack Pointer (SP).
Depending on which stack was used for stacking, either the MSP or PSP value would be
adjusted accordingly just before the exception handler starts. The PC is also updated to the
starting address of the exception handler and the Link Register (LR) is updated with a special
value called EXC_RETURN. This value is 32-bit, and the upper 27 bits are set to 1. Some of
the lower 5 bits are used to hold status information about the exception sequence (e.g., which
stack was used for stacking). This value is to be used in the exception return.
Exception handler execution
Within the exception handler, you can carry out services for the peripheral that requires service.
The processor is in Handler mode when executing an exception handler. In Handler mode:
• The Main Stack Pointer (MSP) is used for stack operations
• The processor is executing in privileged access level
If a higher-priority exception arrives during this stage, the new interrupt will be accepted, and
the currently executing handler will be suspended and pre-empted by the higher-priority
handler. This is called a nested exception.
If another exception with the same or lower priority arrives during this stage, the newly arrived
exception will stay in the pending state and will be serviced when the current exception handler
is completed.
At the end of the exception handler, the program code executes a return that causes the
EXC_RETURN value to be loaded into the Program Counter (PC). This triggers the exception
return mechanism.
Exception return
In some processor architectures, a special instruction is used for exception return. However,
this means that the exception handlers cannot be written and compiled as normal C code. In
ARM Cortex-M processors, the exception return mechanism is triggered using a special return
address called EXC_RETURN. This value is generated at exception entrance and is stored in
the Link Register (LR). When this value is written to the PC with one of the allowed exception
return instructions, it triggers the exception return sequence.
The exception return can be generated by the instructions shown in Table 7.8. When the
exception return mechanism is triggered, the processor accesses the previously stacked register
values in the stack memory during exception entrance and restores them back to the register
bank. This is called unstacking.
Embedded System Design 22ECE61
In parallel to the unstacking operation, the processor can start fetching the instructions of the
previously interrupted program to allow the program to resume operation as soon as possible.
The use of the EXC_RETURN value for triggering exception returns allows exception handlers
(including Interrupt Service Routines) to be written as a normal C function/subroutine. In code
generation, the C compiler handles the EXC_RETURN value in LR as a normal return address.
Due to the EXC_RETURN mechanism, it is impossible to have a normal function return to
address 0xF0000000 to 0xFFFFFFFF. However, since the architecture specified that this
address range cannot be used for program code (has the Execute Never (XN) memory
attribute), it does not create any confusion.
Details of NVIC registers for interrupt control
Summary
There are a number of registers in the NVIC for interrupt control (exception type 16 up to 255).
These registers are located in the System Control Space (SCS) address range. Table 7.9 shows
a summary of these registers.
All of these registers, with the exception of the Software Trigger Interrupt Register (STIR),
can only be accessed in privileged access level. By default STIR can only be accessed in
privileged access level, but can be configured to be accessed in unprivileged access level. By
default, after a system reset:
• All interrupts are disabled (enable bit ¼ 0)
• All interrupts have priority level of 0 (highest programmable level)
• All interrupt pending statuses are cleared
Embedded System Design 22ECE61
Interrupt enable registers
The Interrupt Enable register is programmed through two addresses. To set the enable bit, you
need to write to the NVIC->ISER[n] register address; to clear the enable bit, you need to write
to the NVIC->ICER[n] register address. In this way, enabling or disabling an interrupt will not
affect other interrupt enable states. The ISER/ICER registers are 32-bits wide; each bit
represents one interrupt input.
As there could be more than 32 external interrupts in the Cortex-M3 or CortexM4 processors,
you often find more than one ISER and ICER register e for example, NVIC->ISER[0], NVIC-
>ISER[1], and so on (Table 7.10). Only the enable bits for interrupts that exist are implemented.
So, if you have only 32 interrupt inputs, you will only have ISER and ICER. Although the
CMSIS-Core header file defines the ISER and ICER as words (32-bit), these registers can be
accessed as word, half word, or byte. As the first 16 exception types are system exceptions,
external Interrupt #0 has a start exception number of 16 (see Table 7.1).
The CMSIS-Core provides the following functions for accessing Interrupt Enable registers:
void NVIC_EnableIRQ (IRQn_Type IRQn); // Enable an interrupt
void NVIC_DisableIRQ (IRQn_Type IRQn); // Disable an interrupt
Interrupt set pending and clear pending
If an interrupt takes place but cannot be executed immediately (for instance, if another higher-
priority interrupt handler is running), it will be pended.
Embedded System Design 22ECE61
The interrupt-pending status can be accessed through the Interrupt Set Pending (NVIC-
>ISPR[n]) and Interrupt Clear Pending (NVIC->ICPR[n]) registers. Similarly to the enable
registers, the pending status controls might contain more than one register if there are more
than 32 external interrupt inputs. The values of the pending status registers can be changed by
software, so you can cancel a current pended exception through the NVIC->ICPR[n] register,
or generate software interrupts through the NVIC->ISPR[n] register (Table 7.11).
Embedded System Design 22ECE61
The CMSIS-Core provides the following functions for accessing Interrupt Pending registers:
void NVIC_SetPendingIRQ(IRQn_Type IRQn); // Set the pending status of an interrupt
void NVIC_ClearPendingIRQ(IRQn_Type IRQn); // Clear the pending status of an interrupt
uint32_t NVIC_GetPendingIRQ(IRQn_Type IRQn); // Get the pending status of an interrupt
Additional functions for handling priority grouping are listed in Table 7.7. If you need to
determine the number of priority levels available in the NVIC, you can use the
“__NVIC_PRIO_BITS” directive provided in the CMSIS-Core header file provided by your
microcontroller supplier. Alternatively you can write 0xFF to one of the Interrupt Priority-
Level registers and read back to see how many bits are set. In the case that the device
implemented eight levels of interrupt priority levels (3-bits), the read back value would be
0xE0.
Software trigger interrupt register
Besides using NVIC-ISPR[n] registers, you can also use a Software Trigger Interrupt Register
(NVIC->STIR, see Table 7.14) to trigger an interrupt using software
Embedded System Design 22ECE61
Interrupt controller type register
The NVIC also have an Interrupt Controller Type Register in address 0xE000E004. This read-
only register gives the number of interrupt inputs supported by the NVIC in granularities of 32
(Table 7.15).
In the CMSIS device-driver library, you can access this read-only register using SCnSCB-
>ICTR. (SCnSCB refers to “System Control Registers not in SCB”). While the Interrupt
Controller Type register can give you an approximate number of interrupts available, you can
obtain the exact number of interrupts available by writing to interrupt control registers such as
interrupt enable/pending registers while the PRIMASK register is set (to disable the interrupt
from taking place), and read back to see exactly how many bits are implemented in the interrupt
enable/pending registers.
Embedded System Design 22ECE61
Questions
1. What is the difference between an exception and an interrupt?
2. How are synchronous and asynchronous events related to exceptions and interrupts?
3. What is the role of the processor mode during exception handling?
4. How does the processor prioritize multiple simultaneous exceptions?
5. What are the different types of exceptions in ARM Cortex-M architecture?
6. What is a Hard Fault and when does it occur?
7. Explain the use of Sys Tick as an exception source.
8. What is the difference between fault exceptions and system exceptions?
9. How does the NVIC (Nested Vectored Interrupt Controller) manage interrupts?
10. What is the purpose of interrupt masking in ARM Cortex-M?
11. What is the difference between pre-emptive and non-pre-emptive interrupt handling?
12. What are the advantages of vectored interrupts over polling?
13. How is interrupt priority defined in the NVIC?
14. What is the difference between pre-emption priority and sub priority?
15. How does the priority grouping affect the behaviour of nested interrupts?
16. What happens if two interrupts with the same priority occur simultaneously?
17. What is stored in the vector table?
18. Where is the vector table located by default?
19. How can the vector table be relocated to a different memory address?
20. Why might you want to relocate the vector table in an embedded system?
21. What does it mean for an interrupt to be pending?
22. What is the difference between active, pending, and enabled states of an interrupt?
23. How can software set or clear the pending status of an interrupt?
24. What are the key steps in the exception/interrupt handling sequence?
25. What is automatic stacking and unstacking in the exception sequence?