DÍA 142 DE 365

Fase 3: Comunicaciones y Redes Industriales

📖 Teoría a Estudiar

El Dilema del Desgaste (Write Endurance)

En el Día 122 resolvimos el problema de guardar ventas usando el detector de caídas de voltaje (PVD). Esto es perfecto para la venta actual. Pero en metrología industrial existe un valor sagrado llamado el Odómetro o Totalizador Histórico. Es el registro de cada litro que ha pasado por la máquina desde que salió de la fábrica, tal como el kilometraje de un automóvil.

Este valor se actualiza varias veces por segundo mientras el gas fluye. Si intentas guardarlo en una memoria Flash o EEPROM (que soportan típicamente ~100,000 ciclos de escritura), destruirás físicamente la memoria en cuestión de semanas.

Backup Registers (BKP): La Solución Elegante

Alojados junto al Reloj de Tiempo Real (RTC) en el Dominio de Respaldo, los procesadores STM32F4 cuentan con 20 registros de 32 bits (80 Bytes en total) de memoria RAM especial. Al ser SRAM de hardware, soportan billones de escrituras instantáneas (0 ciclos de espera). Pero a diferencia de la RAM normal, están colgados eléctricamente del pin VBAT. Si la energía principal falla, la diminuta batería de litio mantiene los transistores "vivos", congelando los datos en su interior durante años.

JERARQUÍA DE MEMORIAS Y EL DOMINIO BKP SRAM Principal (VDD) Variables Globales Alta Velocidad (Ilimitadas escrituras) VOLÁTIL (Muere en Apagón) Flash / Ex-EEPROM Lenta (Bloqueante al escribir) VIDA LIMITADA (100k Ciclos) CPU Cortex-M PWR_CR_DBP (Unlock) Backup Domain (VBAT) BAT RTC Core (TR / DR) BKP Registers BKP0R: 4,500,210 BKP1R: ... BKP2R: ... BKP19R Propiedades: - Lectura 1 Ciclo - Vida Infinita - Sobrevive VDD

⚙️ Ejercicios Prácticos

Ejercicio 1: Utilizaremos la función de desbloqueo del bloque de Poder (PWR) que aprendimos en el Día 141. Esta vez, nos centraremos en el arreglo de hardware RTC->BKPxR. Crearemos la rutina de inicialización que lee el odómetro general al arrancar el Súper Bucle, y la rutina de actualización que salva la métrica en la bóveda asíncronamente.


/**
 * @file bkp_registers.c
 * @brief Gestión Bare-Metal de RAM de Respaldo para Odómetros (Totalizadores)
 */

#include "stm32f401xe.h"

// Variable de RAM Principal (Velocidad extrema para el Súper Bucle)
// Guarda los mililitros totales despachados en la vida útil de la estación.
volatile uint64_t totalizador_historico_ml = 0;

/**
 * @brief Abre las puertas del Dominio de Respaldo
 */
void habilitar_acceso_backup_domain(void) {
    // 1. Activar el reloj del periférico de Poder (PWR)
    RCC->APB1ENR |= RCC_APB1ENR_PWREN;
    
    // 2. Levantar el bit DBP (Disable Backup Domain Protection)
    // Esto desarma el firewall de hardware y permite escritura en RTC y BKP.
    PWR->CR |= PWR_CR_DBP;
}

/**
 * @brief Recupera los valores críticos almacenados en la batería VBAT
 *        Debe ejecutarse como primer paso del main() al encender.
 */
void cargar_variables_desde_bkp(void) {
    
    habilitar_acceso_backup_domain();
    
    // Los registros BKP son de 32 bits (4 bytes).
    // Nuestro Totalizador es de 64 bits para evitar que se desborde con millones de litros.
    // Usamos dos registros BKP para almacenar un número gigante de 64 bits.
    
    uint32_t parte_alta = RTC->BKP0R;
    uint32_t parte_baja = RTC->BKP1R;
    
    // Reensamblamos el número de 64 bits con bitwise shifting
    totalizador_historico_ml = ((uint64_t)parte_alta << 32) | parte_baja;
    
    // Si la placa es completamente nueva de fábrica (o se quitó la pila CR2032), 
    // la SRAM BKP iniciará con basura. Aquí se suele agregar una "Firma Digital" 
    // en el BKP2R (ej. 0xCAFE) para saber si la memoria es válida.
    if (RTC->BKP2R != 0xCAFE) {
        // Primera vez que se enciende la máquina (Fábrica)
        totalizador_historico_ml = 0;
        RTC->BKP2R = 0xCAFE; // Marcar como inicializado
    }
}

/**
 * @brief Salva el Odómetro en la SRAM respaldada.
 *        Al ser RAM pura, toma menos de 3 ciclos de reloj en ejecutarse.
 *        Cero esperas, cero bloqueos, infinito Endurace.
 */
void respaldar_totalizador_vivo(void) {
    
    // Romper el entero de 64 bits en dos trozos de 32 bits
    uint32_t parte_alta = (uint32_t)(totalizador_historico_ml >> 32);
    uint32_t parte_baja = (uint32_t)(totalizador_historico_ml & 0xFFFFFFFF);
    
    // Escribir directamente en los registros del Dominio VBAT
    // A diferencia de la EEPROM, esto NO requiere secuencias de comandos.
    RTC->BKP0R = parte_alta;
    RTC->BKP1R = parte_baja;
}

int main(void) {
    
    // 1. RUTINA DE ARRANQUE CRÍTICO
    cargar_variables_desde_bkp();
    
    while(1) {
        
        // Simulación: Un pulso del sensor EXTI añade 10 mililitros
        if (bandera_pulso_sensor) {
            totalizador_historico_ml += 10;
            bandera_pulso_sensor = false;
            
            // Podemos guardar en CADA PULSO porque la SRAM BKP no se desgasta jamás.
            respaldar_totalizador_vivo();
        }
        
        // (El resto del sistema... I2C LCD, RS485 Modbus, PVD_EEPROM)
    }
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Totalizador Metrológico y Resistencia al Desgaste.

El estándar internacional API (American Petroleum Institute) estipula que toda computadora de flujo debe tener un Odómetro Incorruptible. No se puede borrar, y debe actualizarse en tiempo real. Si usaras una memoria Flash convencional para actualizar el odómetro cada vez que giran los engranajes de la turbina, alcanzarías el límite de escritura (100k ciclos) en unos pocos días y arruinarías la placa para siempre.

Gracias a los **Backup Registers (BKP)** dentro del dominio `VBAT`, has transferido la variable del Totalizador a una celda de memoria que combina la velocidad e infinitud de la RAM con la permanencia a largo plazo de un disco duro (mientras la batería CR2032 tenga carga). Si la CFE corta la luz a mitad de un despacho, no tienes que preocuparte de que el sistema de emergencia PVD (Día 122) logre salvar el totalizador en la EEPROM a tiempo, porque el totalizador *ya estaba guardado* desde el nanosegundo anterior en la bóveda de BKP.

📝 Resumen del Día