Course contentsShow
← Embedded Systems & Computer Architecture
Lesson 199 of 9363. Microcontroller Fundamentals and Bare-Metal CFree lesson

Enabling and Disabling Interrupts Globally

Utilize CMSIS intrinsic functions to safely control the processor's interrupt masking state during critical section code execution.

In this lesson, you will learn how to use CMSIS intrinsic functions to create "critical sections" by temporarily pausing all interrupts to protect shared data.

Why We Need Critical Sections

Up to this point, you have learned how to configure interrupts to respond to events. However, a problem arises when your main loop and an Interrupt Service Routine (ISR) both try to modify the same variable simultaneously. If an interrupt fires halfway through the main loop’s update, the variable might be left in a corrupted or inconsistent state.

To prevent this, we must create a critical section: a block of code that must complete execution without being interrupted.

Using CMSIS Intrinsics

The ARM Cortex-M architecture provides specialized assembly instructions to control the processor's interrupt masking state. Rather than writing assembly directly, we use CMSIS (Cortex Microcontroller Software Interface Standard) intrinsic functions. These act like "magic" C functions that the compiler translates into single-cycle hardware instructions.

To safely enter and exit a critical section, we use these two functions:

  1. __disable_irq(): Disables all configurable interrupts by setting the PRIMASK register.
  2. __enable_irq(): Re-enables all configurable interrupts by clearing the PRIMASK register.

Implementation Example

Suppose we are updating a 32-bit counter that is also accessed by a timer interrupt. We protect the update like this:

// Critical section: Protect the shared counter
__disable_irq();    // Stop interrupts from firing

// Perform the sensitive operation
shared_counter++;   

__enable_irq();     // Allow interrupts to resume

Considerations for Safety

When you disable interrupts, your microcontroller stops responding to external hardware events immediately. If you leave interrupts disabled for too long, you might miss time-sensitive inputs, causing your system to become unresponsive or behave erratically. Always keep the code inside your critical section as brief as possible—ideally, just the few lines needed to perform the atomic memory access.

By wrapping shared resource access in these functions, you ensure that the processor finishes its task before the hardware can jump to an ISR, maintaining the integrity of your data.

Key Takeaway: Use __disable_irq() and __enable_irq() to create brief critical sections that prevent race conditions by masking interrupts during sensitive operations.