DÍA 355 DE 365

Fase 5: Diseño Industrial y Hardware

📖 Teoría a Estudiar

La Verdad sobre el Silicio: Silicon Errata

Los ingenieros novatos creen ciegamente en la Hoja de Datos (Datasheet). Si el manual dice que el módulo I2C del STM32 funciona a 400 kHz, asumen que es verdad. Pero fabricar silicio a nivel nanométrico es imperfecto. A veces, las compuertas lógicas dentro del microcontrolador tienen errores de diseño físicos irresolubles. Para no retirar millones de chips del mercado, los fabricantes publican un documento sombrío llamado Errata Sheet.

Una Hoja de Erratas detalla exactamente en qué condiciones físicas el microcontrolador fallará catastróficamente y proporcionará un "Software Workaround" (Una trampa en código) para evadir el error físico. Si no lees este documento, pasarás semanas depurando tu firmware creyendo que tú eres el problema, cuando en realidad el Hardware está defectuoso.

Product Change Notifications (PCN)

Imagínate que mandas fabricar 1,000 placas base y te llegan microcontroladores ST que no corren tu código. Resulta que hace dos meses, la fábrica en Taiwán cambió el material de empaquetado del chip, alterando ligeramente la impedancia térmica, o actualizaron la "Revisión de Silicio" de la versión 'A' a la 'Z'. Los fabricantes notifican esto mediante boletines PCN (Product Change Notification). Estar suscrito a estas alertas es el trabajo real de un Director de Tecnología (CTO).

EL CICLO DE VIDA DEL HARDWARE Y LAS ERRATAS DE SILICIO FABRICANTE DE SILICIO Publica Datasheet (Rev 1) Produce Chip (Rev A) TU CÓDIGO (C / RTOS) Basado al 100% en la teoría de la Hoja de Datos EL SISTEMA COLAPSA (Ej. Bus I2C se congela) "Debe ser mi código" (Semanas de depuración) ERRATA SHEET (ST) Fallo Físico Reportado "Bug en silicio I2C Rev A" SOFTWARE WORKAROUND Tú inyectas una trampa en C Resuelve el problema sin cambiar el Hardware

⚙️ Procedimiento Práctico: Implementando un Workaround

Paso 1: Localizar y Leer la Errata Sheet.
Ve al sitio de STMicroelectronics, busca "STM32F4xx Errata Sheet". Verás una tabla inmensa listando qué fallos afectan a la revisión de silicio 'A', 'Z' o '1'. Las herramientas como STM32CubeProgrammer te permiten leer el "Device ID" y la "Revision ID" de tu chip físico conectándolo por SWD, para saber qué tan defectuoso está tu procesador exactamente.

Paso 2: Aplicar el Parche de Hardware en Software.
Uno de los bugs más famosos en la industria (presente en múltiples familias STM32) es el congelamiento de la bandera BUSY del I2C. Si ocurre un reset mientras el esclavo enviaba datos, la línea SDA se queda en estado bajo. El hardware I2C del STM32 asume que otro dispositivo está usando el bus y se niega a transmitir para siempre. La solución oficial de la Hoja de Erratas no es reiniciar el módulo, es apagar el hardware I2C, configurar los pines como salidas estándar (GPIO), generar 9 pulsos de reloj (SCL) manualmente ("Bit-Banging") para engañar al esclavo, y luego encender el hardware I2C de nuevo.

💻 Firmware: Purgando un "Silicon Bug" (I2C Busy Lockup)

Este código no se basa en lo que el procesador "debería" hacer según la teoría académica, sino en lo que tienes que hacer para obligar a un hardware defectuoso a volver a la vida en el mundo real.


/**
 * @file i2c_errata_workaround.c
 * @brief Implementación de parche (Workaround) para el fallo físico de "I2C Busy Lockup"
 * Documentado en la Hoja de Erratas de STM32
 */

#include "stm32f4xx_hal.h"
#include <stdio.h>

extern I2C_HandleTypeDef hi2c1; // Manejador de la pantalla LCD / Sensores

// =========================================================================
// SOFTWARE WORKAROUND PARA FALLO DE SILICIO (I2C)
// =========================================================================
/**
 * @brief Fuerza la liberación del bus I2C cuando el Hardware entra en 
 * un estado anómalo permanente (Bandera BUSY congelada).
 */
void I2C_Errata_Clear_Busy_Flag_Workaround(void) {
    GPIO_InitTypeDef GPIO_InitStruct = {0};

    printf("[ERRATA] Detectado bloqueo de hardware I2C. Aplicando Workaround...\r\n");

    // 1. Apagar el periférico I2C (El Hardware defectuoso)
    __HAL_I2C_DISABLE(&hi2c1);

    // 2. Reconfigurar temporalmente los pines I2C (SCL y SDA) como salidas manuales (GPIO)
    // En lugar de funciones alternativas, tomamos control absoluto de los pines.
    GPIO_InitStruct.Pin = GPIO_PIN_6 | GPIO_PIN_7; // Asumiendo PB6=SCL, PB7=SDA
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_OD;    // Open Drain (Crucial para I2C)
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // 3. Forzar el Bus a un estado inactivo.
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6 | GPIO_PIN_7, GPIO_PIN_SET);
    HAL_Delay(1);

    // 4. GENERAR 9 PULSOS CLOCK FALSOS (Bit-Banging)
    // Si un esclavo I2C se congeló en medio de una transmisión y mantiene 
    // la línea de datos (SDA) en estado bajo, debemos enviarle pulsos de reloj
    // hasta que el esclavo termine de vaciar su bit y suelte la línea SDA.
    for (uint8_t i = 0; i < 9; i++) {
        // Bajar Clock (SCL)
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET);
        HAL_Delay(1); 
        
        // Subir Clock (SCL)
        HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);
        HAL_Delay(1);
        
        // Revisar si el esclavo ya soltó la línea de datos (SDA == 1)
        if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_SET) {
            break; // Bus liberado. Podemos salir del bucle.
        }
    }

    // 5. Generar un pulso de STOP falso manual
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_RESET); // SCL Low
    HAL_Delay(1);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_RESET); // SDA Low
    HAL_Delay(1);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_6, GPIO_PIN_SET);   // SCL High
    HAL_Delay(1);
    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_7, GPIO_PIN_SET);   // SDA High (Condición STOP)

    // 6. Restaurar los pines a Modo Alterno (I2C) y revivir el Hardware
    GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
    GPIO_InitStruct.Alternate = GPIO_AF4_I2C1;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    // Reseteo forzado del módulo a nivel de registro de reloj (RCC)
    __HAL_RCC_I2C1_FORCE_RESET();
    HAL_Delay(2);
    __HAL_RCC_I2C1_RELEASE_RESET();

    // Re-Inicializar el HAL y encender
    HAL_I2C_Init(&hi2c1);
    printf("[ERRATA] Bus I2C purgado y reiniciado. Resumiendo operaciones.\r\n");
}
        

🚀 Impacto en el Proyecto: Mantenimiento y Madurez

Objetivo del día: Asumir que el hardware comercial es inherentemente defectuoso y debe mitigarse.

Durante la construcción de tu Despachador de Gas LP, integramos una pantalla LCD mediante I2C (Día 340) para mostrar el volumen despachado. Imagina este escenario en campo: Un apagón menor (Brown-out) hace que el regulador caiga durante 50 milisegundos. El STM32 sobrevive gracias a los capacitores, pero la pantalla pierde sincronización y deja la línea I2C congelada en un cero lógico. El hardware I2C del STM32 se bloquea. A pesar de que programaste un código C matemáticamente perfecto, la pantalla de la bomba de gas jamás vuelve a actualizarse. El usuario asume que la máquina "murió".

Un programador inexperto culparía a sus variables o reiniciaría violentamente toda la máquina con el Watchdog perdiendo el progreso del despacho de gas. Un Arquitecto maduro aplica el *Workaround* de la Hoja de Erratas. Al inyectar 9 pulsos de reloj manuales simulados, engañas al chip de la pantalla para que libere el bus, reinicias la conexión I2C en caliente y la venta continúa sin inmutarse. Al incluir este nivel de introspección física y soluciones en tu código, has superado la etapa académica y estás operando en Grado Comercial Senior.

📝 Resumen del Día