Imagina que tienes tres tareas en tu Despachador de Gas LP:
Ahora, visualiza este escenario catastrófico:
osMutexAcquire(). Pero el candado lo tiene la Tarea L. Como está ocupado, la Tarea H es puesta en estado BLOCKED.¡Una tarea de prioridad baja terminó bloqueando a una tarea de prioridad alta a través de una tarea de prioridad media! A esto se le conoce como Inversión de Prioridad.
Para solucionar este defecto lógico, los creadores de FreeRTOS implementaron el algoritmo de Herencia de Prioridad. Cuando activas esta propiedad al crear un Mutex, el Kernel hace lo siguiente:
En el momento exacto en que la Tarea H (Alta) intenta tomar un Mutex que está retenido por la Tarea L (Baja), el RTOS **eleva temporalmente la prioridad de la Tarea L** para que coincida con la prioridad de la Tarea H.
Como la Tarea L ahora tiene la máxima prioridad del sistema, la Tarea M (Normal) ya no puede interrumpirla. La Tarea L termina su transacción de I2C a toda velocidad, libera el Mutex, y en ese instante su prioridad regresa a la normalidad. La Tarea H toma el candado y salva el día. El orden del universo se restaura.
Ejercicio 1: Configuración del Mutex con Herencia en CMSIS-OS v2. Veremos cómo la macro `osMutexPrioInherit` le indica al Kernel de FreeRTOS que administre automáticamente los aumentos de prioridad ante colisiones de recursos físicos.
/**
* @file priority_inheritance.c
* @brief Creación segura de un Mutex con Herencia de Prioridad en FreeRTOS
*/
#include "stm32f401xe.h"
#include "cmsis_os2.h"
// ID Global del Mutex Protegido
osMutexId_t mutex_i2c_seguro;
void Sistema_Init_Mutexes(void) {
// Atributos del Mutex
const osMutexAttr_t mutex_attributes = {
.name = "I2C_Protected_Mutex",
// ===================================================================
// LA LÍNEA MÁGICA: Activa la Herencia de Prioridad
// ===================================================================
// Si no colocas esto, estás usando un Mutex básico plano propenso
// a bloqueos mortales por Inversión de Prioridad.
.attr_bits = osMutexPrioInherit
};
// Crear el Mutex utilizando el estándar CMSIS-OS v2
mutex_i2c_seguro = osMutexNew(&mutex_attributes);
if (mutex_i2c_seguro == NULL) {
// Error crítico: No hay suficiente RAM en el Heap del RTOS para el Mutex
Error_Handler();
}
}
// Ejemplo de uso dentro de una tarea de Baja Prioridad
void Thread_Mantenimiento_EEPROM(void *argument) {
for (;;) {
// Al adquirir este Mutex, si la Tarea de Seguridad (Alta Prioridad)
// lo llega a necesitar mientras nosotros lo tenemos, el RTOS elevará
// nuestra prioridad instantáneamente para sacarnos de la CPU rápido.
osMutexAcquire(mutex_i2c_seguro, osWaitForever);
Escribir_Log_Lento_En_EEPROM(); // Sección crítica
osMutexRelease(mutex_i2c_seguro);
osDelay(10000);
}
}
Objetivo del día: Blindaje Definitivo contra Bloqueos Sistémicos en Concurrencia.
Has equipado a tu Despachador de Gas LP con la más alta sofisticación conceptual de los sistemas operativos en tiempo real. En la industria, hay sistemas que fallan inexplicablemente cada 30 días sin dejar rastro en los registros (Logs); la causa raíz suele ser una Inversión de Prioridad no resuelta donde una tarea de fondo estrangula a una tarea de seguridad.
Al configurar sistemáticamente todos tus Mutexes con la propiedad **osMutexPrioInherit**, has dotado a FreeRTOS de la capacidad de autodefensa matemática. Tu máquina de despacho maneja la pantalla, el WiFi, la EEPROM y las válvulas PID de manera concurrente, sabiendo que si los hilos compiten por el hardware, el Kernel reorganizará la jerarquía al vuelo para asegurar que los procesos de vida o muerte jamás sufran retrasos. Tu arquitectura ha alcanzado la madurez industrial total.
osMutexPrioInherit durante la instanciación del Mutex mediante osMutexNew(), siendo una norma obligatoria de desarrollo embebido seguro.