DÍA 258 DE 365

Fase 5: Diseño Industrial y Proyecto Final

📖 Teoría a Estudiar

El Proceso de Construcción (Build Process)

Cuando le das al botón de "Compilar", ocurren tres cosas:

  1. El Compilador (gcc): Traduce tus archivos .c a código Ensamblador (Assembly) creando archivos objeto (.o). Hasta este momento, las funciones no tienen una dirección de memoria fija.
  2. El Enlazador (Linker - ld): Toma todos los archivos .o, los une y les asigna direcciones físicas reales (ej. 0x08010A42) basándose en las reglas de un archivo de texto llamado Linker Script (.ld).
  3. El Archivo Binario (.bin / .hex): Es el producto final, una imagen idéntica bloque por bloque de lo que se planchará en el silicio.

Secciones y Direcciones Absolutas

El código C tiene diferentes tipos de datos que deben mapearse a hardware distinto:

Reubicación FOTA en el STM32F401RE (512 KB Flash)

El STM32F401 tiene sectores de diferentes tamaños. No puedes borrar "medio sector", la borradura de Flash funciona por páginas o sectores completos. El particionamiento ideal es:

ARQUITECTURA DE ENLAZADO: LINKER SCRIPT Y MAPA DE SECTORES rtos_tasks.o metrologia.o rfid_crypto.o LINKER (ld) STM32_FLASH.ld MEMORY { FLASH : ORIGIN=0x08010000 LENGTH=192K RAM : ORIG=0x2000.. } Asigna Dir. MEMORIA FÍSICA (STM32F401 - 512KB) 0x0800 0000 BOOTLOADER Sectores 0-3 (64 KB) 0x0801 0000 APLICACIÓN ACTIVA Sector 4 (64 KB) Sector 5 (128 KB) .isr_vector (VTOR) .text / .rodata 0x0804 0000 OTA DOWNLOAD SLOT Sector 6 (128 KB) Sector 7 (128 KB) 0x0808 0000 FIN DE LA FLASH (512 KB)

⚙️ Ejercicios Prácticos

Ubicando el Archivo: Si utilizas STM32CubeIDE o un Makefile generado por CubeMX, busca un archivo con la extensión .ld (por ejemplo, STM32F401RETX_FLASH.ld). Este es el mapa maestro que dicta el destino final de cada variable de tu RTOS.

Ejercicio 1: Modificación del Linker Script. Vamos a modificar el archivo .ld de nuestra Aplicación Principal (el código de la Fase 5). Cambiaremos el ORIGIN de la FLASH para que empiece en el Sector 4, y limitaremos su LENGTH para que el compilador nos lance un error inmediato (Memory Overflow) si nuestro código crece demasiado y amenaza con invadir el Slot de Descargas OTA.


/* ========================================================================= */
/* ARCHIVO: STM32F401RETX_FLASH.ld (Para la Aplicación FOTA)                 */
/* ========================================================================= */

/* Puntos de Entrada y Pila (Stack) */
ENTRY(Reset_Handler)
_estack = 0x20018000;    /* Final de los 96K de RAM (Puntero inicial) */

/* Cantidad mínima garantizada para Heap y Stack local */
_Min_Heap_Size = 0x200;  /* 512 Bytes */
_Min_Stack_Size = 0x400; /* 1024 Bytes */

/* 
 * ========================================================================= 
 * PARTICIONAMIENTO DE MEMORIA (MEMORY MAPPING)
 * ========================================================================= 
 * Memoria Total Flash : 512 KB (0x08000000 a 0x0807FFFF)
 * RAM Total           : 96 KB  (0x20000000 a 0x20017FFF)
 * 
 * - BOOTLOADER: 0x08000000, LENGTH = 64K  (Sectores 0 a 3)
 * - APP ACTIVA: 0x08010000, LENGTH = 192K (Sectores 4 y 5)  <-- ESTAMOS AQUÍ
 * - OTA SLOT:   0x08040000, LENGTH = 256K (Sectores 6 y 7)
 * ========================================================================= 
 */
MEMORY
{
  /* Deshabilitamos la dirección base original. Esto obliga al Linker 
     a reubicar todas las funciones C a partir del Offset 0x10000 */
  /* FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 512K  (ORIGINAL) */
  
  /* NUEVA CONFIGURACIÓN FOTA APP */
  FLASH (rx)      : ORIGIN = 0x08010000, LENGTH = 192K
  
  /* La RAM no cambia, ambos (Bootloader y App) la comparten en momentos 
     diferentes del tiempo (No se ejecutan simultáneamente) */
  RAM (xrw)       : ORIGIN = 0x20000000, LENGTH = 96K
}

/* ========================================================================= */
/* SECCIONES (SECTIONS)                                                      */
/* ========================================================================= */
SECTIONS
{
  /* 
   * 1. TABLA DE VECTORES
   * Esta sección debe ir obligatoriamente al inicio de la FLASH asiganda.
   * El hardware del NVIC la buscará aquí gracias al SCB->VTOR modificado en C.
   */
  .isr_vector :
  {
    . = ALIGN(4);
    KEEP(*(.isr_vector)) /* 'KEEP' evita que el optimizador la borre */
    . = ALIGN(4);
  } >FLASH

  /* 
   * 2. CÓDIGO EJECUTABLE (Texto)
   * Aquí va tu lógica de RTOS, drivers HAL y el código C compilado.
   */
  .text :
  {
    . = ALIGN(4);
    *(.text)           /* .text sections (code) */
    *(.text*)          /* .text* sections (code) */
    *(.glue_7)         /* glue arm to thumb code */
    *(.glue_7t)        /* glue thumb to arm code */

    KEEP (*(.init))
    KEEP (*(.fini))

    . = ALIGN(4);
    _etext = .;        /* Marca el fin de la sección de texto */
  } >FLASH

  /* 
   * 3. DATOS DE SOLO LECTURA (Constantes)
   * Arreglos de melodías del buzzer, certificados AWS, strings de LCD.
   */
  .rodata :
  {
    . = ALIGN(4);
    *(.rodata)         /* .rodata sections (constants, strings, etc.) */
    *(.rodata*)        /* .rodata* sections (constants, strings, etc.) */
    . = ALIGN(4);
  } >FLASH

  /* 
   * 4. DATOS INICIALIZADOS (.data) y NO INICIALIZADOS (.bss)
   * Se almacenan en RAM para ser modificables. El código de arranque 
   * copia los valores iniciales desde la FLASH a la RAM al encender.
   */
  .data : 
  {
    /* ... (Configuración estándar de data) ... */
  } >RAM AT> FLASH

  .bss :
  {
    /* ... (Configuración estándar de bss) ... */
  } >RAM

  /* Validaciones finales de Stack y Heap */
  ._user_heap_stack :
  {
    . = ALIGN(8);
    PROVIDE ( end = . );
    PROVIDE ( _end = . );
    . = . + _Min_Heap_Size;
    . = . + _Min_Stack_Size;
    . = ALIGN(8);
  } >RAM
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Particionamiento Estático y Protección contra Memory Overflows.

Implementar FOTA no se trata solo de descargar un archivo binario; se trata de gestión del riesgo. En sistemas industriales, no puedes permitir que tu aplicación crezca indefinidamente hasta colisionar con la memoria del Bootloader o con el espacio reservado para la actualización. Un desbordamiento físico arruinaría la integridad del sistema.

Al editar manualmente el **Linker Script (`.ld`)**, has implementado un "Contrato de Espacio" a nivel de compilador. Le dijiste a GCC: *"Tienes exactamente 192 Kilobytes para el código de este Despachador; ni un byte más"*. Si mañana importas una librería criptográfica gigante (como mbedTLS) y el código supera los 192KB, el proceso de construcción (Build Process) abortará con un error contundente (`region FLASH overflowed by X bytes`) en lugar de compilar un binario defectuoso. Además, aseguraste que la **Tabla de Vectores (.isr_vector)** se coloque milimétricamente en el Offset cero del Sector 4 (`0x08010000`), permitiendo que el hardware ARM Cortex-M4 encuentre las interrupciones del Caudalímetro sin fallar. Has convertido la geografía de tu memoria en una fortaleza estática.

📝 Resumen del Día