Guia Completo para Multitarefa com FreeRTOS em STM32

Em sistemas embarcados, a capacidade de executar múltiplas tarefas simultaneamente é essencial para aplicações complexas, como drones que precisam ler sensores, controlar motores e transmitir dados simultaneamente. Um RTOS (Real-Time Operating System), como o FreeRTOSIntrodução ao FreeRTOS no STM32Introdução ao FreeRTOS no STM32Descubra como otimizar projetos STM32 usando FreeRTOS com exemplos práticos de tarefas, sincronização, comunicação e gestão de recursos., permite gerenciar tarefas, prioridades e recursos de forma eficiente no STM32. Este artigo combina fundamentos teóricos e exemplos práticos avançados, desde a configuração do ambiente até técnicas de sincronização e otimização, oferecendo um guia completo para desenvolvedores que desejam migrar de código sequencial ("bare-metal") para sistemas multitarefa robustos.

Índice🔗

Por que usar RTOS no STM32?🔗

Os microcontroladores STM32Famílias de microcontroladores STM32: Uma visão geralFamílias de microcontroladores STM32: Uma visão geralProfundo mergulho nas famílias STM32, explorando arquitetura, aplicações e desempenho. Descubra dicas e casos práticos para projetos embarcados., embora poderosos, possuem recursos limitados. Um RTOS como o FreeRTOS oferece:

Sem um RTOS, aplicações complexas exigiriam superloops difíceis de manter, com riscos de latência inconsistente e deadlocks.

Conceitos Básicos do FreeRTOS🔗

Configurando o FreeRTOS no STM32🔗

Método 1: Via STM32CubeMX

1. Selecione o modelo do STM32O que é STM32 e por que usá-lo?O que é STM32 e por que usá-lo?Descubra os principais benefícios, arquitetura ARM Cortex-M e aplicações práticas dos microcontroladores STM32. Comece a inovar agora. (ex: STM32F407VG).

2. Em Middleware, ative o FreeRTOSIntrodução ao FreeRTOS no STM32Introdução ao FreeRTOS no STM32Descubra como otimizar projetos STM32 usando FreeRTOS com exemplos práticos de tarefas, sincronização, comunicação e gestão de recursos. e escolha a interface (CMSIS_V1 ou V2).

3. Configure clock, pinos e periféricos necessários.

Método 2: Configuração Manual

#include "FreeRTOS.h"
#include "task.h"
int main(void) {
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  xTaskCreate(task1, "Task1", 128, NULL, 2, NULL);
  xTaskCreate(task2, "Task2", 128, NULL, 1, NULL);
  vTaskStartScheduler();
  while (1);
}

Criação e Gerenciamento de Tarefas🔗

Cada tarefa é uma função com loop infinito. Prioridades definem a ordem de execução:

void task_sensor(void *pvParameters) {
  while (1) {
    float temp = read_sensor();
    xQueueSend(sensor_queue, &temp, 0);
    vTaskDelay(pdMS_TO_TICKS(1000));
  }
}

Dicas:

  • Ajuste configMAX_PRIORITIES no FreeRTOSConfig.h.
  • Use vTaskDelay() para liberar a CPU.
  • Monitore o uso da stack com uxTaskGetStackHighWaterMark().

Sincronização com Semáforos e Mutexes🔗

Semáforos Binários

Sinalizam eventos únicos (ex: interrupção concluída):

SemaphoreHandle_t interrupt_sem = xSemaphoreCreateBinary();
// Em uma ISR (Interrupt Service Routine):
xSemaphoreGiveFromISR(interrupt_sem, pdFALSE);

Mutexes

Protegem recursos críticos:

SemaphoreHandle_t uart_mutex = xSemaphoreCreateMutex();
void task_uart(void *pvParameters) {
  xSemaphoreTake(uart_mutex, portMAX_DELAY);
  HAL_UART_Transmit(&huart2, "Dados", 5, 100);
  xSemaphoreGive(uart_mutex);
}

Comunicação entre Tarefas usando Queues🔗

Queues garantem transmissão segura de dados entre tarefas:

QueueHandle_t sensor_queue = xQueueCreate(10, sizeof(float));
// Tarefa produtora:
void task_sensor(void *pvParameters) {
  float data;
  while (1) {
    data = read_sensor();
    xQueueSend(sensor_queue, &data, 0);
  }
}
// Tarefa consumidora:
void task_processor(void *pvParameters) {
  float received_data;
  while (1) {
    if (xQueueReceive(sensor_queue, &received_data, pdMS_TO_TICKS(2000))) {
      process_data(received_data);
    }
  }
}

Gerenciamento de Recursos e Armadilhas Comuns🔗

1. Priority Inversion:

Ocorre quando uma tarefa de baixa prioridade retém um mutexSincronização e comunicação entre tarefas no STM32Sincronização e comunicação entre tarefas no STM32Aprenda a implementar mecanismos de sincronização com semáforos, mutexes, filas e event groups em sistemas embarcados com STM32 e FreeRTOS. necessário por uma de alta prioridade. Solução: Use mutexesSincronização e comunicação entre tarefas no STM32Sincronização e comunicação entre tarefas no STM32Aprenda a implementar mecanismos de sincronização com semáforos, mutexes, filas e event groups em sistemas embarcados com STM32 e FreeRTOS. com prioridade inheritance.

2. Stack Overflow:

Defina o tamanho da stack com margem de segurança:

$$ \text{Stack Size} = (\text{Variáveis Locais} + \text{Contexto da Tarefa}) \times 1.5 $$

3. Deadlocks:

Evite múltiplos locks em ordem inconsistente.

Integração com Modos de Baixo Consumo🔗

O FreeRTOS permite entrar em modos de baixo consumoGerenciamento de energia e modos de baixo consumo no STM32Gerenciamento de energia e modos de baixo consumo no STM32Aprenda a reduzir o consumo de energia com os modos STM32, garantindo eficiência e prolongando a vida útil de baterias em sistemas embarcados. (ex: STOP Mode) sem interromper o scheduler:

void task_low_power(void *pvParameters) {
  while (1) {
    xEventGroupWaitBits(power_events, LOW_POWER_FLAG, pdTRUE, pdTRUE, portMAX_DELAY);
    HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
    SystemClock_Config(); // Reconfigura clock após wakeup
  }
}

Exemplo Prático 1: Sistema de Log de Dados com Multitarefa🔗

Implementa coleta de dados, armazenamento em SDData Logger com STM32: Armazenamento em SD card e transmissão via Wi-FiData Logger com STM32: Armazenamento em SD card e transmissão via Wi-FiDescubra como construir data loggers robustos com STM32, integrando cartão SD e Wi-Fi, para monitoramento contínuo em aplicações industriais e ambientais. e transmissão Wi-Fi:

graph TD A[Task Sensor] -->|Queue| B[Task SD] A -->|Queue| C[Task Wi-Fi] B -->|Semáforo| D[SD Card] C -->|Semáforo| E[Wi-Fi Module]

Código:

xTaskCreate(task_sensor, "Sensor", 256, NULL, 3, NULL);
xTaskCreate(task_sd, "SD", 512, NULL, 2, NULL);
xTaskCreate(task_wifi, "WiFi", 512, NULL, 2, NULL);
QueueHandle_t data_queue = xQueueCreate(10, sizeof(float));
SemaphoreHandle_t sd_semaphore = xSemaphoreCreateBinary();

Exemplo Prático 2: Monitoramento de Sensores e Atuação🔗

Sistema com três tarefas: leitura de sensores, controle de atuadores e comunicação UARTUART no STM32: Comunicação serial básica para debug e integraçãoUART no STM32: Comunicação serial básica para debug e integraçãoDescubra os segredos da UART no STM32 com exemplos práticos, configuração via HAL, DMA e dicas de troubleshooting para comunicação serial eficiente.:

void task_temp(void *pvParameters) {
  float temp;
  while (1) {
    temp = read_temp();
    xQueueSend(temp_queue, &temp, 0);
    vTaskDelay(1000);
  }
}
void task_fan(void *pvParameters) {
  float temp;
  while (1) {
    xQueueReceive(temp_queue, &temp, portMAX_DELAY);
    if (temp > 30.0) HAL_GPIO_WritePin(FAN_GPIO, FAN_PIN, GPIO_PIN_SET);
    else HAL_GPIO_WritePin(FAN_GPIO, FAN_PIN, GPIO_PIN_RESET);
  }
}

Debugging com RTOS🔗

Use o STM32CubeIDEConfigurando o ambiente de desenvolvimento para STM32Configurando o ambiente de desenvolvimento para STM32Aprenda a configurar o ambiente para desenvolvimento em STM32 usando STM32CubeIDE, debuggers e ferramentas integradas com dicas de troubleshooting práticas. para:

Conclusão e Próximos Passos🔗

A implementação de multitarefa com FreeRTOS no STM32Introdução ao FreeRTOS no STM32Introdução ao FreeRTOS no STM32Descubra como otimizar projetos STM32 usando FreeRTOS com exemplos práticos de tarefas, sincronização, comunicação e gestão de recursos. permite criar sistemas robustos e escaláveis. Para avançar:

Dominar essas técnicas abre portas para aplicações em IoT, automação industrial e dispositivos embarcados de alta performance.

Autor: Marcelo V. Souza - Engenheiro de Sistemas e Entusiasta em IoT e Desenvolvimento de Software, com foco em inovação tecnológica.

Referências🔗

Compartilhar artigo

Artigos Relacionados