MCU & FPGA RTOS Padrões de Projeto Aplicados a RTOS (FreeRTOS)

Padrões de Projeto Aplicados a RTOS (FreeRTOS)

Padrões de Exclusão Mútua, Proteção de Recursos e Prevenção de Deadlock

Em FreeRTOS, concorrência não controlada não falha sempre — falha quando você menos espera. Esta seção trata de padrões que evitam corrupção de dados, inversão de prioridade e deadlocks, sem sacrificar o determinismo.


3.1 Mutex com Priority Inheritance

Problema resolvido:
Duas ou mais tarefas acessam o mesmo recurso (UART, I²C, SPI, memória compartilhada).

Risco clássico:
🔴 Priority Inversion — tarefa de baixa prioridade bloqueia uma de alta.

Ideia do padrão:
Usar Mutex (não semáforo) para herança de prioridade automática.

SemaphoreHandle_t uartMutex;

uartMutex = xSemaphoreCreateMutex();

Uso correto:

void UartTask(void *pvParameters)
{
    for (;;)
    {
        if (xSemaphoreTake(uartMutex, portMAX_DELAY))
        {
            UART_Write("Hello RTOS\n");
            xSemaphoreGive(uartMutex);
        }
    }
}

Por que não semáforo binário?

  • Semáforos não fazem herança de prioridade
  • Mutexes são projetados para exclusão mútua real

Regra de ouro:
🔒 Mutex protege recurso, não evento.


3.2 Gatekeeper Task (Padrão Fundamental em FreeRTOS)

Problema resolvido:
Múltiplas tarefas acessando um único periférico (UART, Flash, Display).

Ideia do padrão:
Apenas uma tarefa é dona do recurso. As demais pedem serviço via fila.

Este é um dos padrões mais importantes para firmware de produção.


Estrutura:

Tasks ──► Request Queue ──► Gatekeeper Task ──► Hardware

Mensagem de requisição:

typedef struct {
    char message[64];
} UartRequest;

Gatekeeper:

void UartGatekeeperTask(void *pvParameters)
{
    UartRequest req;

    for (;;)
    {
        if (xQueueReceive(UartQueue, &req, portMAX_DELAY))
        {
            UART_Write(req.message);
        }
    }
}

Cliente:

UartRequest req = { .message = "Log message\n" };
xQueueSend(UartQueue, &req, portMAX_DELAY);

Vantagens:

  • Elimina mutexes
  • Elimina deadlocks
  • Simplifica drivers

Trade-off:
Leve aumento de latência → ganho enorme em robustez.


3.3 Critical Section (Uso cirúrgico)

Problema resolvido:
Trechos extremamente curtos que não podem ser interrompidos.

taskENTER_CRITICAL();
sharedCounter++;
taskEXIT_CRITICAL();

O que acontece:

  • Desabilita interrupções (localmente)
  • Bloqueia escalonamento

Quando usar:

  • Incrementos atômicos
  • Flags simples
  • Estruturas lock-free auxiliares

Quando NÃO usar:
🚫 Código longo
🚫 Acesso a drivers
🚫 Comunicação entre tarefas

Se você precisa de printf() dentro de critical section, algo está errado.


3.4 Read–Modify–Write protegido (Anti-pattern clássico)

Problema comum (ERRADO):

if (flag == 0)
{
    flag = 1;
}

Correção com mutex:

xSemaphoreTake(flagMutex, portMAX_DELAY);
if (flag == 0)
{
    flag = 1;
}
xSemaphoreGive(flagMutex);

Ou melhor ainda:
Substituir flag por task notification ou event group.


3.5 Event Groups como Padrão de Coordenação

Problema resolvido:
Sincronizar múltiplas tarefas com condições compostas.

EventGroupHandle_t systemEvents;

#define EVT_NET_READY   (1 << 0)
#define EVT_SENSOR_OK   (1 << 1)

Sinalização:

xEventGroupSetBits(systemEvents, EVT_NET_READY);

Aguardar múltiplas condições:

xEventGroupWaitBits(
    systemEvents,
    EVT_NET_READY | EVT_SENSOR_OK,
    pdFALSE,
    pdTRUE,
    portMAX_DELAY
);

Uso típico:

  • Startup sequencial
  • Estados globais do sistema
  • Dependências entre subsistemas

Vantagem:
Muito mais expressivo que flags globais.


3.6 Deadlock Avoidance (Padrões de Prevenção)

Causa clássica de deadlock:

  • Ordem inconsistente de aquisição de mutexes

Padrão de prevenção:
📐 Sempre adquirir recursos na mesma ordem

xSemaphoreTake(mutexA, portMAX_DELAY);
xSemaphoreTake(mutexB, portMAX_DELAY);

/* uso */

xSemaphoreGive(mutexB);
xSemaphoreGive(mutexA);

Alternativa mais segura:
Eliminar múltiplos mutexes → usar Gatekeeper.

0 0 votos
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários

Related Post

0
Adoraria saber sua opinião, comente.x