(T) EE2028 Topic 9B Interrupt Programming
(T) EE2028 Topic 9B Interrupt Programming
Interrupt Programming
Rajesh Panicker
[T]EE2028
Acknowledgement:
- Slides modified from the original slides by A/Prof. C K Tham, ECE, NUS
Interrupt Configuration
◼ Each external interrupt has several associated registers
◼ Set Enable and Clear Enable Registers
◼ Set Pending and Clear Pending Registers
◼ Priority Registers
◼ Active Bit Registers
◼ A number of other registers affect int. processing
◼ Exception-masking registers (PRIMASK, FAULTMASK, and
BASEPRI)
◼ Vector Table Offset Register
◼ Software Trigger Interrupt Register (STIR)
◼ Priority group in Application Interrupt & Reset Control
Register
2
Interrupt Set Enable Registers (ISER) and
Interrupt Clear Enable Registers (ICER)
3
Interrupt Set Pending Registers (ISPR) &
Interrupt Clear Pending Registers (ICPR)
◼ NVIC_ISPR (32 bits) register is used to
◼ Force interrupts into pending state
◼ Determine which interrupts are currently pending (R/W)
◼ NVIC_ICPR (32 bits) register is used to
◼ Clear pending interrupts
◼ Determine which interrupts are currently pending (R/W)
◼ NVIC can have more than one NVIC_ISPR/NVIC_ICPR.
Each bit is corresponding to one interrupt input
◼ Interrupt pending status can be accessed through
NVIC_ISPR/NVIC_ICPR
◼ To pend an interrupt, write 1 to corresponding bit in NVIC_ISPR
◼ To cancel a current interrupt pending, write 1 to corresponding bit in
NVIC_ICPR
◼ Writing to NVIC_ISPR has no effect on an int. which is already pending or is
disabled
◼ Writing to NVIC_ICPR has no effect on an active int., unless it is also pending
4
Interrupt Priority Registers (IPR),
Interrupt Active Bit Registers (IABR)
◼ NVIC Interrupt Priority Registers (IPRs) are 8-bit registers, though
only some of the MSBs are implemented depending on the SoC
◼ Accessible as IP[i], where i=0 to 81 for STM32 as there are 82
external interrupts
◼ Each register is used to assign a priority level (from 0 to 255) to
interrupts: 0 is the highest priority
◼ So far, we saw the various Ixx registers which deals with external
interrupts. For system exceptions, the corresponding controls are
considered a part of the System Control Block (SCB) rather than NVIC
◼ Priority of system exceptions with programmable priority levels are
set in System Handler Priority Registers (SHPRs), accessible as
SHP[i], where i=0 to 11 for all CM4 chips
◼ The Interrupt control and state register (ICSR) can be to
◼ Set and clear the pending status of system exceptions including SysTick,
PendSV, and NMI
◼ Determine the currently executing exception/interrupt number by
reading VECTACTIVE
◼ System handler control and state register (SHCSR)
◼ Usage faults, memory management (MemManage) faults, and bus fault
exceptions are enabled by the SHCSR
◼ The pending status of faults and active status of most system exceptions
are also available from this register
6
PRIMASK, FAULTMASK and BASEPRI
7
Accessing Cortex-M4 NVIC registers
CMSIS functions Description
void NVIC_EnableIRQ(IRQn_Type IRQn) Enables an interrupt or exception.
void NVIC_DisableIRQ(IRQn_Type IRQn) Disables an interrupt or exception.
void NVIC_SetPendingIRQ(IRQn_Type IRQn) Sets the pending status of interrupt or exception to 1.
void NVIC_ClearPendingIRQ(IRQn_Type IRQn) Clears the pending status of interrupt or exception to 0.
Reads the pending status of interrupt or exception. This
uint32_t NVIC_GetPendingIRQ(IRQn_Type
function returns non-zero value if the pending status is
IRQn)
set to 1.
uint32_t NVIC_GetActive(IRQn_Type IRQn); Read the active bit for an external interrupt
void NVIC_SetPriority(IRQn_Type IRQn, Sets the priority of an interrupt or exception with
uint32_t priority) configurable priority level to 1.
Reads the priority of an interrupt or exception with
uint32_t NVIC_GetPriority(IRQn_Type IRQn) configurable priority level. This function return the
current priority level.
void NVIC_SetPriorityGrouping(uint32_t
Set the Priority Grouping in NVIC Interrupt Controller
PriorityGroup);
uint32_t NVIC_EncodePriority (uint32_t Encode the priority for an interrupt. The returned
PriorityGroup, uint32_t PreemptPriority, priority value can be used for NVIC_SetPriority(...)
uint32_t SubPriority); function
The input parameter IRQn is the IRQ number
8
Interrupt Programming Steps
1. Set up the priority group setting
◼ By default priority group setting is zero (7 MSBs used for preempt priority)
2. Set up the priority level of the interrupt
◼ By default, all interrupts are at priority level 0 (highest)
3. Implement the ISR (details 2 slides later)
4. The interrupting device/peripheral should be configured
to generate an interrupt for the specific condition of interest
◼ The interrupt should be enabled inside the interrupting device - the exact
way in which this is done is device dependent
◼ If the interrupt is from an external device (e.g. a sensor) which is routed
to NVIC through an EXTI, we will need to enable both EXTI interrupts and
the device interrupts
◼ EXTI interrupts are enabled by writing to EXTI_IMR, EXTI_RTSR / EXTI_FTSR
etc.
◼ External device (e.g. sensor) interrupt is enabled by writing to the
appropriate register through the normal data channel connecting the
device to the processor (e.g. I2C) Not to be confused with the interrupts generated
by the I2C interface (I2C_EV and I2C_ER) 9
Interrupt Programming Steps
5. Clear the pending status
◼ This step is optional, but desirable in many circumstances
6. Enable the interrupt at NVIC
◼ The interrupt for the device/peripheral should be enabled in NVIC so that
NVIC can deal with the interrupt when it occurs
◼ Else, the interrupt can go pending, but will not become active
◼ Once everything is set up, interrupt triggering itself typically does
not require any action from software
◼ The interrupt service routine is invoked automatically by the
hardware provided appropriate conditions are met
◼ It is not ‘called’ explicitly from the main program
◼ However, there are circumstances where the software triggers an
interrupt explicitly (e.g. for testing). An external interrupt can be triggered
artificially by
◼ Writing to ISPR
◼ via Software Trigger Interrupt Register (STIR) in NVIC
Exceptions such as SVC (supervisor call) are triggered by software. SVC is used to transfer control to the Operating System (OS) 10
ISR Implementation
1. PUSH all the registers modified by the handler, other than those which are
automatically pushed by the hardware before the handler is invoked (R0–R3, R12,
LR, PC, and xPSR)
◼ If ISR is implemented in C, this is taken care of implicitly
2. If a peripheral generates interrupts due to multiple causes which go into NVIC as a
single interrupt (i.e., the interrupt status bits are OR-ed together internally), identify
the exact cause / reason for the interrupt
◼ This can typically be done by checking the interrupt status bit(s) of the peripherals
◼ EXTI 5-9 are or-ed together and is recognized by NVIC as a single interrupt. Further,
each pin can trigger an interrupt because of rising edge and/or falling edge
◼ Identification of EXTI triggered and cause (rising/falling) can be done by reading EXTI_PR
◼ I2C_EV interrupt can be triggered due to several conditions such as RXNE, TXIS etc.
◼ The exact condition can be determined by checking I2C_ISR
◼ If the interrupt is from an external device (e.g. a sensor) which is routed to NVIC
through an EXTI, we might need to read appropriate register(s) within the device to
find out the cause
◼ This is done through the normal data channel connecting the external device to the
processor – there is no NVIC involvement
◼ The cause of interrupt from accelerometer is identified by reading appropriate registers
through the I2C interface
11
ISR Implementation …
3. Do the BARE MINIMUM required to deal with the cause
◼ If the interrupt was triggered because a new data is available - grab the data
and store it in a buffer
◼ You might also want to set a boolean flag to indicate that a new data is
available. This flag can be polled in the main program, which then does further
processing on the data and clears the flag
◼ As a general rule, the higher the priority/urgency of the interrupt, the more
effort you should put in to make the ISR shorter (execution time)
◼ Generally, an interrupt which has a lower inter-arrival time is more urgent, as
12
ISR Implementation …
4. Clear the interrupt
◼ Clearing an interrupt is the process of telling/causing the interrupting device to
de-assert the interrupt. The exact way in which it is done is dependent on the
specific peripheral, and on the specific condition inside the peripheral which
triggered the interrupt. This typically involves one of the following
◼ reading a data register within the interrupting device (for data-ready type interrupts)
◼ writing a data register within the device (for transmit register empty type interrupts)
◼ reading a status register (for errors/status interrupts)
◼ writing to an interrupt clear register (for errors/status interrupts)
◼ Some interrupts arrive as pulses of finite duration; doesn’t require any explicit clearing
◼ If the interrupt is from an external device (e.g. a sensor) which is routed to NVIC
through an EXTI, both EXTI int. and the external device int. should be cleared
◼ The clearing process is done through the normal data channel connecting the
external device to the processor – there is no NVIC involvement
◼ The interrupt from accelerometer is cleared by reading / writing appropriate registers
within the accelerometer through I2C interface
◼ Clearing the EXTI interrupt is done by writing to EXTI_PR through the internal bus
◼ Clearing pending status ≠ disabling an interrupt ≠ clearing an interrupt
5. POP all the registers pushed at the beginning of the handler before exiting
13
Only the NVIC side (dealing with interrupts) configuration is shown.
EXTI configuration (generation of interrupts) was covered in Chapter 6
Example (Demo)
SetPriority() expects right-aligned priority, but IPR is left-aligned
NVIC_SetPriorityGrouping(5);
◼ PriorityGroup=5
NVIC_SetPriority(EXTI15_10_IRQn, 0x0C);
◼ PreemptPriority=0b11 // Set priority level to 0xC0 = 1100 0000
◼ SubPriority=0b00 NVIC_ClearPendingIRQ(EXTI15_10_IRQn);
◼ Full IPR contents: NVIC_EnableIRQ(EXTI15_10_IRQn);
◼ 0b11000000 = 0xC0
15
THE END
Questions?
16