SoC
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
  • Arm Cortex M3
  • Contact
Reading: How to properly enable/disable interrupts in ARM Cortex-M?
SUBSCRIBE
SoCSoC
Font ResizerAa
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Search
  • Home
  • Arm
  • Arm Cortex M0/M0+
  • Arm Cortex M4
Have an existing account? Sign In
Follow US
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
© S-O-C.ORG, All Rights Reserved.
Arm

How to properly enable/disable interrupts in ARM Cortex-M?

David Moore
Last updated: September 14, 2023 1:10 pm
David Moore 7 Min Read
Share
SHARE

Enabling and disabling interrupts is a critical aspect of working with ARM Cortex-M microcontrollers. Interrupts allow the processor to respond to events and requests from peripheral devices. However, incorrectly enabling or disabling interrupts can lead to issues like race conditions, deadlocks, and reduced performance. This article provides a step-by-step guide on how to properly enable and disable interrupts in ARM Cortex-M devices.

Contents
Overview of Interrupts in ARM Cortex-MKey Steps for Handling InterruptsHow to Enable Interrupts1. Enable Interrupts at the NVIC Level2. Enable Interrupts at Peripheral LevelHow to Disable Interrupts1. Disable Interrupts at Peripheral Level2. Disable Interrupts at NVIC LevelAdditional Best PracticesCommon Issues and DebuggingISR Not Being CalledMultiple Interrupts Blocking Each OtherRace ConditionsFaults or CrashesConclusion

Overview of Interrupts in ARM Cortex-M

The ARM Cortex-M processor has a Nested Vectored Interrupt Controller (NVIC) that handles interrupts from peripheral devices and exceptions. The NVIC allows interrupts to be prioritized, so that more critical events can be serviced first. It maintains an interrupt vector table, which contains the entry points for interrupt service routines. The processor also has special registers for enabling/disabling interrupts globally or individually.

When an enabled interrupt occurs, the processor completes execution of the current instruction, saves its context, and jumps to the corresponding interrupt service routine (ISR). During this time, other interrupts are disabled. Once the ISR finishes, the context is restored and interrupt handling resumes. So it’s important to enable only required interrupts and keep ISRs short.

Key Steps for Handling Interrupts

  1. Enable the peripheral clock before using any device that raises interrupts.
  2. Configure the peripheral to raise required interrupt requests.
  3. Define the interrupt service routines.
  4. Enable interrupts at the NVIC level.
  5. Enable peripheral interrupts at the device level.
  6. When servicing an ISR, clear the source of the interrupt.
  7. Avoid long ISRs to prevent blocking other interrupts.
  8. Disable peripheral interrupts when not needed.
  9. Disable NVIC interrupts if all peripherals are idle.

How to Enable Interrupts

Enabling interrupts is a two step process – enabling at the NVIC level and then at the peripheral level. Here are the steps:

1. Enable Interrupts at the NVIC Level

The NVIC has a register called NVIC_ISERx that allows enabling interrupts by setting bits that correspond to interrupt lines. For example, to enable interrupt line 5, set bit 5 of NVIC_ISER0. The steps are:

  1. Find the interrupt line number for the peripheral interrupt from the reference manual.
  2. Calculate the NVIC_ISERx register and bit position. (For lines 0-31, use NVIC_ISER0 and same bit position)
  3. Set the corresponding bit in the NVIC_ISERx register to 1.

For example, to enable interrupt line 42, the steps would be:

  1. Interrupt line 42 corresponds to bit 10 of NVIC_ISER1 (lines 32 to 63).
  2. Set bit 10 of NVIC_ISER1 to 1 to enable the interrupt.

2. Enable Interrupts at Peripheral Level

After enabling the interrupt line at the NVIC level, we need to enable the interrupt generation at the peripheral itself. This is done by:

  1. Finding the interrupt enable bit field for the peripheral from the reference manual.
  2. Setting the bit field to 1 to enable interrupt generation.

For example, to enable interrupts from TIM2 on a STM32 microcontroller:

  1. The TIM2_DIER register has an interrupt enable bit field.
  2. Set the UIE bit field to 1 to enable update interrupts from TIM2.

Once the peripheral and NVIC interrupts are enabled, the microcontroller will be able to respond to interrupts from that peripheral.

How to Disable Interrupts

Similar to enabling, disabling interrupts is also a two step process – disabling at the peripheral level and then at the NVIC level:

1. Disable Interrupts at Peripheral Level

This involves clearing the interrupt enable bits for that peripheral. For example with TIM2:

  1. Clear the UIE bit field in the TIM2_DIER register to 0.

This prevents the peripheral from generating further interrupts. But interrupts may still occur if they were pending before disabling.

2. Disable Interrupts at NVIC Level

To completely disable the interrupt line, it needs to be disabled at the NVIC as well. This can be done by:

  1. Finding the interrupt line number and corresponding NVIC_ICERx register.
  2. Clearing the corresponding bit in the NVIC_ICERx register to 0.

For example, to disable interrupt line 42, bit 10 of the NVIC_ICER1 register should be cleared to 0.

Once disabled at both levels, interrupts will no longer occur on that line. The interrupt service routine will not execute again until the interrupt is re-enabled.

Additional Best Practices

Here are some additional best practices to follow when dealing with interrupts:

  • Initialize the peripheral and interrupts early in the program before enabling.
  • Define interrupt service routines before enabling them at the NVIC.
  • Keep ISR code short, deterministic and efficient.
  • Avoid calling functions that disable or re-enable interrupts in ISRs.
  • Restore context properly before returning from ISR.
  • Minimize interrupts when they are not required to reduce latency.
  • Prioritize and nested interrupts carefully when using a RTOS.
  • Use peripherals that allow clearing pending interrupt bits.

Common Issues and Debugging

Here are some common issues faced when working with interrupts and how to debug them:

ISR Not Being Called

  • Use debugger or LED toggling to verify if interrupt is occurring.
  • Check if interrupt line or bit is enabled in NVIC_ISERx.
  • Verify peripheral interrupt generation is enabled.
  • Check for faults disabling all interrupts.

Multiple Interrupts Blocking Each Other

  • Avoid long ISRs to prevent blocking.
  • Set priorities so urgent interrupts preempt others.
  • Use pending interrupt bits to handle multiple interrupts.

Race Conditions

  • Use critical sections or disable preemption around shared resources.
  • Clear pending bits early in ISR before accessing shared variables.

Faults or Crashes

  • Double check context saving/restoring in ISRs.
  • Verify no stack or memory overflow due to interrupts.
  • Catch exceptions and faults within ISRs.

Conclusion

Interrupts provide an efficient way for microcontrollers to respond to real-time events and peripherals without constant polling. However, incorrect use of interrupt enabling/disabling can lead to unexpected behaviors and bugs. Following best practices such as proper peripheral configuration, short and focused ISRs, nested interrupt handling, reducing unnecessary interrupts, and debugging techniques can help harness the benefits of interrupts in ARM Cortex-M devices.

Newsletter Form (#3)

More ARM insights right in your inbox

 


Share This Article
Facebook Twitter Email Copy Link Print
Previous Article What are the core registers in the Cortex M0?
Next Article How can I decompile an ARM Cortex-M0 .hex file to C++?
Leave a comment Leave a comment

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

2k Followers Like
3k Followers Follow
10.1k Followers Pin
- Sponsored-
Ad image

You Might Also Like

ARM Cortex-M4 Interrupt Handling

The ARM Cortex-M4 processor has a flexible and configurable interrupt…

7 Min Read

What is the reset vector address of ARM Cortex-M0?

The reset vector address of ARM Cortex-M0 is 0x00000000. This…

6 Min Read

Stack Usage Reporting in Arm Development Tools

Understanding and optimizing stack usage is an important part of…

5 Min Read

What is the history of ARM microcontroller?

ARM microcontrollers have become ubiquitous in embedded systems and IoT…

9 Min Read
SoCSoC
  • Looking for Something?
  • Privacy Policy
  • About Us
  • Sitemap
  • Contact Us
Welcome Back!

Sign in to your account