DÍA 183 DE 365

Fase 4: FreeRTOS y Conectividad IoT

📖 Teoría a Estudiar

La Anatomía de FreeRTOS

Cuando descargas FreeRTOS, te encuentras con cientos de archivos. Pero en realidad, el núcleo mágico de este RTOS cabe en solo tres archivos principales de C:

La Capa "Port" (El Puente al Hardware)

Los tres archivos de arriba son código C universal; funcionan igual en una tostadora que en un misil. Pero para que el RTOS haga el Cambio de Contexto (pausar una tarea y guardar sus registros), necesita saber exactamente cómo funciona la CPU física. Para ello, FreeRTOS incluye una carpeta llamada portable. Aquí seleccionamos el archivo port.c específico para nuestra arquitectura: el **ARM Cortex-M4F** (nuestro STM32F4).

El Panel de Control: `FreeRTOSConfig.h`

FreeRTOS es altamente personalizable. No quieres compilar funciones que no vas a usar porque desperdician memoria Flash. El archivo FreeRTOSConfig.h es tu consola de mandos. Aquí defines la velocidad de tu CPU, cuánta RAM cederle al RTOS (Heap) y si quieres usar Preempción o no.

ARQUITECTURA DE INTEGRACIÓN: BARE-METAL A FREERTOS Capa de Aplicación (Tus Archivos) main.c metrologia.c wifi_iot.c FreeRTOS Core (Universal C) tasks.c (Scheduler) queue.c (IPC) heap_4.c (Memory Mgmt) FreeRTOSConfig.h Configuración RTOS Capa Port (Específica del Chip) port.c (Para ARM Cortex-M4F) HARDWARE: STM32 (SysTick, PendSV, SVC)

⚙️ Ejercicios Prácticos

Ejercicio 1: El secuestro de las interrupciones. En nuestros días de Bare-Metal, nosotros configurábamos el SysTick_Handler para contar milisegundos. Ahora, **debemos cederle el control de esas interrupciones al RTOS**. Editaremos el archivo FreeRTOSConfig.h para parametrizar el núcleo de nuestro Despachador de Gas LP, y mapearemos las rutinas de hardware a las funciones del Kernel de FreeRTOS mediante directivas #define.

Archivo: FreeRTOSConfig.h (Tu panel de mando del RTOS)


/**
 * @file FreeRTOSConfig.h
 * @brief Configuración maestra del Sistema Operativo para el Despachador
 */

#ifndef FREERTOS_CONFIG_H
#define FREERTOS_CONFIG_H

// =========================================================================
// 1. CONFIGURACIÓN DEL NÚCLEO
// =========================================================================

// Activar la Preempción. (Si pones 0, el RTOS será cooperativo, 
// y las tareas deberán ceder la CPU manualmente. ¡Nosotros queremos 1!).
#define configUSE_PREEMPTION                    1

// Frecuencia real del procesador. El RTOS la necesita para calcular los tiempos.
#define configCPU_CLOCK_HZ                      ( 84000000UL ) // 84 MHz

// Frecuencia del Tick del Sistema. 1000 Hz significa que el Scheduler 
// revisa qué tarea debe ejecutarse cada 1 milisegundo.
#define configTICK_RATE_HZ                      ( ( TickType_t ) 1000 )

// Prioridades máximas disponibles. (0 es la más baja, 4 es la más alta).
#define configMAX_PRIORITIES                    ( 5 )

// Tamaño mínimo de Stack (en Words de 32-bits, no en bytes). 
// 128 words = 512 bytes de RAM por tarea mínima.
#define configMINIMAL_STACK_SIZE                ( ( uint16_t ) 128 )

// =========================================================================
// 2. GESTIÓN DE MEMORIA (El Heap del RTOS)
// =========================================================================

// El STM32F401 tiene 96 KB de SRAM total.
// Le cederemos 30 KB exclusivos al RTOS para que él reparta esta memoria 
// dinámicamente entre las tareas que vayamos creando. Los otros 66 KB
// quedan libres para nuestros Framebuffers de la pantalla y variables estáticas.
#define configTOTAL_HEAP_SIZE                   ( ( size_t ) ( 30 * 1024 ) )

// =========================================================================
// 3. SECUESTRO DE INTERRUPCIONES (El Enlace al Hardware)
// =========================================================================
// FreeRTOS utiliza 3 interrupciones crudas de la arquitectura ARM Cortex-M:
// 1. SVC (Supervisor Call): Para iniciar la primera tarea.
// 2. PendSV (Pendable Service): Para ejecutar el Cambio de Contexto de registros.
// 3. SysTick: Para marcar el pulso del tiempo (El Tick).

// Aquí hacemos un "mapeo" redefiniendo los nombres que espera FreeRTOS 
// hacia los nombres físicos que usa el compilador (CMSIS) de STM32.

#define vPortSVCHandler    SVC_Handler
#define xPortPendSVHandler PendSV_Handler
#define xPortSysTickHandler SysTick_Handler

#endif /* FREERTOS_CONFIG_H */
        

Modificación Crítica en main.c (El abandono del Súper Bucle)

Una vez que el FreeRTOSConfig.h está listo y los archivos fuente están en nuestro proyecto, nuestro main.c cambia radicalmente su propósito. Ya no hace el trabajo; solo inicializa el hardware y contrata a los "trabajadores" (Tareas).


#include "stm32f401xe.h"
#include "FreeRTOS.h"
#include "task.h"

// Función dummy para representar una tarea
void Tarea_Parpadeo_LED(void *pvParameters) {
    while(1) {
        // En lugar de usar for() gastando energía, el RTOS bloquea la tarea.
        HAL_GPIO_Invertir(pin_led);
        vTaskDelay(pdMS_TO_TICKS(500)); // Dormir exactamente 500 Ticks (500 ms)
    }
}

int main(void) {
    
    // 1. Inicializa el Hardware (Relojes, Pines, UART)
    SystemClock_Config(); 
    
    // NOTA CRÍTICA BARE-METAL:
    // Ya NO configuramos nosotros el SysTick (SysTick_Config).
    // FreeRTOS lo configurará automáticamente cuando arranquemos el Scheduler.
    
    // 2. Crear las Tareas
    xTaskCreate(Tarea_Parpadeo_LED, "Blinky", 128, NULL, 1, NULL);
    
    // 3. Encender el Sistema Operativo (Punto de no retorno)
    // Esta función configura el SysTick, levanta la primera tarea y nunca regresa.
    vTaskStartScheduler();
    
    // Si llegas aquí, el RTOS colapsó por falta de RAM en el Heap.
    while(1);
    
    return 0;
}
        

🚀 Avance del Proyecto Tesis: Despachador de Gas LP

Objetivo del día: Integración del RTOS y Particionamiento de Memoria.

Tu Despachador tiene recursos limitados: 96 KB de RAM. En la Fase 3, apartamos unos cuantos KB para dibujar la pantalla a color sin parpadeos (Framebuffers). Hoy, al compilar FreeRTOS en tu proyecto, hemos configurado la directiva `configTOTAL_HEAP_SIZE` a 30 KB. Esto es crucial.

Al hacer esto, has creado una **Frontera de Memoria**. FreeRTOS toma esos 30 KB y crea su propio administrador interno de memoria (`heap_4.c`). Cuando crees la Tarea de Metrología y la Tarea de WiFi, el RTOS tomará pedacitos de esos 30 KB para darles una "Pila" (Stack) privada a cada tarea. Si la Tarea WiFi tiene un error e intenta pedir más RAM de la permitida, fallará de forma controlada sin invadir la RAM donde guardamos el precio y los litros despachados. Has logrado aislamiento lógico dentro del mismo chip.

📝 Resumen del Día