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.
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.
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;
}
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.
VBAT.>> 32) y guardarlas cruzando múltiples registros RTC->BKPxR consecutivos.