Desbordamiento de Temporizador: Mecanismo, Consecuencias y Manejo en Sistemas Embebidos

Desbordamiento de Temporizador: Mecanismo, Consecuencias y Manejo en Sistemas Embebidos

Un **desbordamiento de temporizador** ocurre cuando un registro de contador/temporizador de hardware alcanza su valor máximo ($2^N - 1$ para N bits) y se reinicia a cero en el siguiente ciclo de reloj. Es un evento periódico fundamental en prácticamente todos los microcontroladores (MCU), SoCs y núcleos de RTOS.

El Mecanismo

  • Contador: Registro de ejecución libre incrementado por fuente de reloj ($f_{clk}$ o $f_{clk}/\text{Prescaler}$).
  • Ancho: 8 bits (256), 16 bits (65,536), 32 bits (4.29B), 64 bits.
  • Período ($T_{ovf}$): $T_{ovf} = \frac{2^N}{f_{count}}$.
    • Ejemplo: 16 bits, reloj 1 MHz $\rightarrow$ $T_{ovf} = 65.536 \text{ ms}$.
    • Ejemplo: 32 bits, 100 MHz $\rightarrow$ $T_{ovf} = 42.9 \text{ s}$.
  • Bandera/Interrupción: El hardware establece la **Bandera de Desbordamiento (TOV / UIF)**. Genera una **Solicitud de Interrupción (IRQ)** si está habilitada (TOIE).

Consecuencias de un Desbordamiento No Manejado

Dominio Modo de Fallo
Cronometraje (RTC / SysTick) El tiempo salta hacia atrás / se envuelve. `millis()` se envuelve (Arduino: 49.7 días). `gettimeofday()` corrompido si se pierde la ISR.
PWM / Comparación de Salida Falla si el valor TOP no se actualiza atómicamente con búfer. Error de ciclo de trabajo por un período.
Captura de Entrada / Ancho de Pulso Período medido $>$ $T_{ovf}$ $\rightarrow$ Ambigüedad (conteo de desbordamientos perdido). Requiere extensión de contador por software.
Programador RTOS (SysTick) Pérdida de ticks $\rightarrow$ Deriva de tiempo de tareas, plazos perdidos, inversión de prioridad.
Seguridad / Cripto Falla de fuente de entropía. Fugas de temporización por canal lateral si el desbordamiento es predecible.
Y2K38 / `time_t` de 32 bits Desbordamiento de época Unix 19 de enero de 2038. No es temporizador HW, pero misma matemática.

Estrategias de Manejo (Firmware)

1. Extender Ancho en Software (Práctica Estándar)

// Temporizador HW de 16 bits $\rightarrow$ Tiempo del Sistema de 32/64 bits
volatile uint32_t overflow_count = 0;

ISR(TIMER_OVF_vect) {
  overflow_count++;
}

uint64_t get_time_us() {
  uint8_t sreg = SREG; cli();
  uint16_t hw = TCNT1;
  uint32_t ovf = overflow_count;
  SREG = sreg;
  // Manejar carrera: if (TIFR & TOV) ovf++; hw = TCNT1;
  return ((uint64_t)ovf << 16) | hw;
}

2. Reinicio Periódico / Recarga (Modo Auto-Recarga / Periódico)

  • Establecer **Registro de Auto-Recarga (ARR / TOP / PRD)** = Período Deseado - 1.
  • El temporizador cuenta 0 $\rightarrow$ ARR $\rightarrow$ 0. **Sin bandera de desbordamiento** (o bandera = Coincidencia de Período).
  • Usado para: **SysTick (1 ms), Período PWM, Disparo ADC, Tick RTOS.**
  • Elimina la ambigüedad del desbordamiento; define un período exacto.

3. Captura de Entrada con Conteo de Desbordamientos

  • En Evento de Captura: Leer Temporizador ($T_{cap}$) + Leer/Incrementar Contador de Desbordamientos ($N_{ovf}$).
  • Tiempo Total = $(N_{ovf} \times 2^N + T_{cap}) / f_{count}$.
  • Lectura atómica de (Contador + Desbordamiento) crítica (Soporte HW: registro de captura de 32 bits incluyendo bits de desbordamiento, o doble lectura con verificación de bandera).

4. Contadores Libres de Alta Resolución / 64 bits

  • ARM Cortex-M **DWT CYCCNT** (32 bits @ frecuencia de CPU).
  • RISC-V **`mtime` / `mtimeh`** (64 bits mapeado en memoria).
  • x86 **TSC (Time Stamp Counter)** (64 bits, invariante).
  • Período de desbordamiento = Siglos. Efectivamente "sin desbordamiento" para la vida del sistema.

5. Compensación de Deriva de Reloj (Calibración)

  • Tolerancia del oscilador ($\pm 50$ ppm cristal, $\pm 1–2\%$ RC).
  • Sincronización periódica con referencia externa (PPS GPS, NTP, PTP IEEE 1588, Cruce por Cero de Red Eléctrica).
  • Ajustar `ARR` o factor de escala por software dinámicamente.

Mejores Prácticas

  1. Use Modo Auto-Recarga para tareas periódicas (SysTick, PWM, Bucles de Control). Evite el desbordamiento libre a menos que mida intervalos largos.
  2. Lecturas Atómicas: Deshabilite interrupciones / Use LDREX/STREX / Lea dos veces con verificación de bandera para valores de varios registros.
  3. Volatile + Barreras de Memoria: Variables compartidas ISR/Principal.
  4. Pruebe el Rollover: Simule desbordamiento (establezca contador cerca de MAX) en CI/HIL. Verifique manejo de rollover de `millis()` (historia de errores de rollover de `millis()` en Arduino).
  5. Watchdog: Watchdog de ventana independiente (IWDT/WWDT) — dominio de reloj separado — detecta falla del temporizador principal.

Conclusión

El desbordamiento de temporizador no es un error—es una **restricción de diseño**. Los contadores libres modernos de 32/64 bits lo hacen insignificante para el cronometraje. Para temporizadores de 8/16 bits, **extensión por software (contador de desbordamientos) + acceso atómico** es el patrón estándar. Para tareas periódicas, el **modo Auto-Recarga elimina el concepto por completo.**