DÍA 259 DE 365

Fase 5: Diseño Industrial y Proyecto Final

📖 Teoría a Estudiar

El System Control Block (SCB) y el Registro VTOR

En el núcleo de la arquitectura ARM Cortex-M4 existe un área de memoria altamente privilegiada llamada System Control Block (SCB). Es aquí donde residen los registros que controlan el alma misma del procesador: la unidad de protección de memoria (MPU), los manejadores de fallos (Fault Handlers) y, críticamente, el Vector Table Offset Register (VTOR).

El VTOR le dice al Controlador de Interrupciones (NVIC): "Cuando ocurra un evento de hardware (Timer, UART, GPIO), no busques la lista de respuestas en 0x08000000. Súmale este Offset (desplazamiento) y búscalo allá".

¿Por qué no hacerlo en el main()?

Muchos tutoriales básicos te dirán que pongas SCB->VTOR = 0x08010000; como la primera línea de tu main(). Esto es una negligencia industrial. El compilador en C ejecuta tareas invisibles antes de llegar a la palabra main. Llama al código de ensamblador de arranque (startup_stm32.s) el cual inicializa la memoria estática y copia datos de Flash a RAM.

Si ocurre un fallo de bus, o un pulso espurio activa una interrupción en ese milisegundo anterior al main(), el procesador se colgará eternamente. La modificación del VTOR debe hacerse en la función pre-principal: SystemInit().

REUBICACIÓN DEL CONTROLADOR DE INTERRUPCIONES (NVIC Y VTOR) Caudalímetro Pulso (EXTI) IRQ Signal CORTEX-M CORE NVIC Interrupt Controller SCB->VTOR Valor: 0x08000000 Valor: 0x08010000 Si no modificamos VTOR ÁREA DEL BOOTLOADER Vector Base: 0x08000000 CRASH! (No hay handler de Gas) VTOR Offset Aplicado ÁREA DE LA APLICACIÓN Vector Base: 0x08010000 SysTick_Handler (RTOS) EXTI_IRQHandler (Suma 1 Litro)

⚙️ Ejercicios Prácticos

El Archivo Oculto: system_stm32f4xx.c. Este archivo, generado automáticamente por el entorno de ST, es responsable de configurar los relojes iniciales y el SCB. Normalmente, los desarrolladores no entran aquí por temor a romper el proyecto. Nosotros sí entraremos. Es aquí donde activaremos una macro predefinida diseñada específicamente para particionamiento de memoria en arquitecturas FOTA.

Ejercicio 1: Modificación del núcleo (Core modification). Abriremos el archivo system_stm32f4xx.c (Ubicado usualmente en la carpeta Core/Src/) y localizaremos la macro `USER_VECT_TAB_ADDRESS`. Descomentaremos esa línea y especificaremos el Offset (`0x10000`) correspondiente al Sector 4, donde inicia nuestra aplicación.


/**
 * @file system_stm32f4xx.c
 * @brief Modificación para FOTA: Habilitación de Relocación Vectorial Temprana
 */

#include "stm32f4xx.h"

// =========================================================================
// DESBLOQUEO DE LA MACRO DE USUARIO
// =========================================================================
/* 
 * Por defecto, STMicroelectronics comenta esta línea. 
 * Para habilitar el ajuste del VTOR, DEBEMOS descomentarla.
 */
#define USER_VECT_TAB_ADDRESS 

#if defined(USER_VECT_TAB_ADDRESS)
/*!< Descomente la línea siguiente si necesita redireccionar la tabla
     de vectores en la memoria SRAM (nosotros la dejamos en FLASH) */
/* #define VECT_TAB_SRAM */

/*!< Ingrese el Offset (Desplazamiento) de su aplicación.
     Nuestro Linker Script empieza en 0x08010000. 
     Por lo tanto, el offset desde 0x08000000 es 0x10000.
     ATENCIÓN: Este valor debe ser un múltiplo de la alineación estricta 
     requerida por el Cortex-M (usualmente múltiplo de 0x200). */
#define VECT_TAB_OFFSET  0x10000U 
#endif /* USER_VECT_TAB_ADDRESS */

// ... (Omitimos variables globales de sistema) ...

// =========================================================================
// SYSTEM INIT: LA PRIMERA FUNCIÓN EN EJECUTARSE
// =========================================================================
/**
  * @brief  Setup the microcontroller system
  *         Initialize the FPU setting, vector table location and the PLL configuration.
  * @note   This function is called by the startup_stm32f401xe.s file BEFORE main()
  */
void SystemInit(void)
{
    /* Habilitación del FPU (Floating Point Unit) si está activado */
    #if (__FPU_PRESENT == 1) && (__FPU_USED == 1)
        SCB->CPACR |= ((3UL << 10*2)|(3UL << 11*2));  /* set CP10 and CP11 Full Access */
    #endif
  
    /* Configuración original de resets de hardware ... */
  
    /* --------------------------------------------------------------------- */
    /* LA MAGIA DEL VTOR SE EJECUTA AQUÍ AUTOMÁTICAMENTE                     */
    /* --------------------------------------------------------------------- */
#if defined(USER_VECT_TAB_ADDRESS)

  #if defined(VECT_TAB_SRAM)
    SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Reubicación en RAM (No lo usamos) */
  #else
    // Esta es la línea que salvará nuestra vida industrial:
    // SCB->VTOR = 0x08000000 | 0x10000 = 0x08010000;
    SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; 
  #endif
  
#endif /* USER_VECT_TAB_ADDRESS */
}
        

Verificación en Assembly: Para entender por qué esto es tan crítico, mira cómo arranca el procesador según el archivo de ensamblador startup_stm32f401xe.s:


/* Fragmento de startup_stm32f401xe.s */
Reset_Handler:
  ldr   sp, =_estack      /* 1. Asigna Puntero de Pila (MSP) */
  bl    SystemInit        /* 2. Llama a nuestra función modificada C */
  bl    __libc_init_array /* 3. Inicializa las variables estáticas C */
  bl    main              /* 4. Finalmente, llama a tu main() */
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Alineación del Hardware (NVIC) y Despliegue de Código Particionado.

Muchos tutoriales de YouTube sobre Bootloaders y OTA cometen el error cardinal de modificar el registro `SCB->VTOR` como primera instrucción de la función `main()`. En un banco de trabajo, a veces funciona. Pero en tu Despachador de Gas LP, los motores y relés generan pulsos parásitos (ruido) que pueden entrar por los pines de interrupción en los microsegundos previos al `main()`. Si un pin configurado previamente por el Bootloader detecta ruido e intenta saltar a su interrupción, pero la tabla antigua ya fue borrada, la máquina colapsará (HardFault).

Al adentrarte en las entrañas del Core del Cortex-M4 y habilitar `USER_VECT_TAB_ADDRESS` en `system_stm32f4xx.c`, has aplicado un nivel de disciplina que se exige en el desarrollo aeroespacial y automotriz. Tu tabla de interrupciones se reubica instantáneamente en el "Paso 2" del diagrama de arranque, mucho antes de que el compilador C siquiera termine de crear sus variables. Cuando el Kernel de FreeRTOS despierte en el `main()` y configure el SysTick (el reloj vital del sistema operativo), el procesador sabrá exactamente en qué dirección física buscar las instrucciones. La arquitectura de tu software ahora es completamente FOTA-Compliant.

📝 Resumen del Día