How to Enable and Disable Interrupts in Embedded C
In embedded C, interrupts are enabled or disabled by setting or clearing specific bits in control registers, often using
sei() to enable and cli() to disable global interrupts. Alternatively, you can manipulate interrupt mask registers directly to control specific interrupts.Syntax
To control interrupts globally in embedded C, you typically use the following functions or register operations:
sei();- Enables global interrupts.cli();- Disables global interrupts.- Direct register manipulation, e.g., setting or clearing bits in
INTERRUPT_MASK_REGISTERto enable/disable specific interrupts.
These functions are often macros defined in microcontroller-specific header files.
c
sei(); // Enable global interrupts cli(); // Disable global interrupts
Example
This example shows how to enable and disable global interrupts on an AVR microcontroller using sei() and cli(). It toggles an LED only when interrupts are enabled.
c
#include <avr/io.h> #include <avr/interrupt.h> int main(void) { DDRB |= (1 << PB0); // Set PB0 as output (LED) cli(); // Disable global interrupts // Setup code here (e.g., timer or external interrupt setup) sei(); // Enable global interrupts while (1) { PORTB ^= (1 << PB0); // Toggle LED for (volatile int i = 0; i < 100000; i++); // Delay } return 0; }
Output
The LED connected to PB0 toggles on and off repeatedly when interrupts are enabled.
Common Pitfalls
Common mistakes when enabling/disabling interrupts include:
- Forgetting to re-enable interrupts after disabling them, causing the system to stop responding to events.
- Disabling interrupts for too long, which can cause missed events or timing issues.
- Using
cli()andsei()without understanding their global effect, which disables/enables all interrupts, not just one. - Not using atomic operations when modifying interrupt-related registers, leading to race conditions.
c
// Wrong: Disabling interrupts and never enabling them again cli(); // critical code // forgot to call sei(); interrupts remain disabled // Correct: cli(); // critical code sei(); // Re-enable interrupts
Quick Reference
| Operation | Function or Register Action | Description |
|---|---|---|
| Enable global interrupts | sei(); | Sets the global interrupt enable bit |
| Disable global interrupts | cli(); | Clears the global interrupt enable bit |
| Enable specific interrupt | Set bit in interrupt mask register | Allows a specific interrupt source to trigger |
| Disable specific interrupt | Clear bit in interrupt mask register | Prevents a specific interrupt source from triggering |
Key Takeaways
Use
sei() to enable and cli() to disable global interrupts in embedded C.Always re-enable interrupts after critical sections to avoid system lockup.
Disabling interrupts globally affects all interrupt sources, so use carefully.
Modify specific interrupt mask registers to control individual interrupts.
Avoid long periods with interrupts disabled to prevent missed events.