Máscara de interrupción en sistemas embebidos: Qué, por qué y cómo

¿Qué es una máscara de interrupción?

Una máscara de interrupción es un mecanismo de hardware o software que desactiva temporalmente (enmascara) una o más fuentes de interrupción, impidiendo que interrumpan a la CPU. Actúa como un portero: cuando el bit de máscara de una interrupción está activado, la CPU ignora esa solicitud de interrupción; cuando se desactiva, la interrupción se habilita y puede disparar una rutina de servicio de interrupción (ISR).

¿Por qué es necesario el enmascaramiento?

El enmascaramiento de interrupciones es esencial en varios escenarios críticos:

  • Protección de secciones críticas: Al ejecutar código que no debe ser interrumpido (por ejemplo, actualizar estructuras de datos compartidas, modificar registros de hardware, cambio de contexto), el enmascaramiento garantiza una ejecución atómica.
  • Manejo predecible de interrupciones: Al enmascarar selectivamente interrupciones de menor prioridad durante la ejecución de una ISR de alta prioridad, se impone un esquema de prioridad determinista.
  • Gestión de recursos: Evita condiciones de carrera en periféricos compartidos o búferes de memoria accedidos tanto por el código principal como por las ISR.
  • Gestión de energía: El enmascaramiento de interrupciones de activación innecesarias durante modos de bajo consumo evita despertares espurios.
  • Depuración y pruebas: Permite a los desarrolladores aislar rutas de código desactivando temporalmente fuentes de interrupción específicas.

¿Cómo funcionan las máscaras de interrupción?

Típicamente, cada fuente de interrupción tiene un bit correspondiente en un Registro de máscara de interrupción (IMR) o Registro de habilitación de interrupción (IER):

  • Bit de máscara = 1 (activado) → Interrupción deshabilitada (enmascarada).
  • Bit de máscara = 0 (desactivado) → Interrupción habilitada.

La CPU verifica este registro antes de reconocer una interrupción. En muchas arquitecturas (ARM Cortex-M, AVR, x86), existen tanto instrucciones globales de habilitación/deshabilitación de interrupciones (por ejemplo, CPSID I/CPSIE I, cli/sti) como registros de máscara por interrupción para un control detallado.

¿Qué interrupciones se pueden enmascarar?

La granularidad del enmascaramiento varía según la arquitectura:

  • Enmascaramiento global: Deshabilita todas las interrupciones enmascarables a la vez (las interrupciones no enmascarables, NMI, no se pueden enmascarar).
  • Enmascaramiento a nivel de periférico: Cada periférico (UART, temporizador, ADC, GPIO, etc.) tiene su propio bit de habilitación en un controlador de interrupciones central (por ejemplo, NVIC en ARM, PIC/APIC en x86).
  • Enmascaramiento basado en prioridad: Algunos controladores (como el NVIC de ARM) permiten enmascarar por nivel de prioridad (por ejemplo, registro BASEPRI), habilitando todas las interrupciones por encima de cierta prioridad mientras deshabilitan las de menor prioridad.

Mejores prácticas

  • Mantén las regiones enmascaradas lo más cortas posible para minimizar la latencia de interrupción.
  • Prefiere el enmascaramiento por interrupción sobre la deshabilitación global cuando solo se necesite bloquear fuentes específicas.
  • Siempre vuelve a habilitar (desenmascarar) las interrupciones en la misma ruta de ejecución, incluidos los manejadores de error y excepciones.
  • Usa lectura-modificación-escritura atómica o registros dedicados de configuración/limpieza para evitar condiciones de carrera al modificar bits de máscara.

El enmascaramiento adecuado de interrupciones es una piedra angular del diseño de firmware embebido en tiempo real confiable.