什么是 RTOS?

RTOS(Real-Time Operating System)实时操作系统是一种能够保证在确定时间内完成任务调度的操作系统。

RTOS vs 通用 OS

特性RTOS通用 OS(Windows/Linux)
实时性确定性响应非确定性
任务调度优先级驱动时间片轮转
内存占用KB 级别MB/GB 级别
应用场景嵌入式、工业控制桌面、服务器

硬实时 vs 软实时

  • 硬实时:必须在规定时间内完成(如汽车安全气囊)
  • 软实时:尽量在规定时间内完成(如视频播放)

FreeRTOS 基础

核心概念

概念说明
任务(Task)独立的执行线程
调度器(Scheduler)管理任务执行顺序
优先级(Priority)决定任务执行顺序
队列(Queue)任务间通信机制
信号量(Semaphore)资源同步机制
互斥量(Mutex)保护共享资源

任务管理

创建任务

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

// 任务函数
void vTaskFunction(void *pvParameters) {
    char *pcTaskName = (char *)pvParameters;
    
    for (;;) {
        printf("%s is running\n", pcTaskName);
        vTaskDelay(pdMS_TO_TICKS(1000)); // 延时 1 秒
    }
}

// 创建任务
void vStartTasks(void) {
    xTaskCreate(
        vTaskFunction,           // 任务函数
        "Task1",                 // 任务名称
        configMINIMAL_STACK_SIZE,// 栈大小
        (void *)"Task1",         // 参数
        1,                       // 优先级
        NULL                     // 任务句柄
    );
}

任务优先级

// 优先级数字越大,优先级越高
#define TASK_PRIORITY_HIGH    3
#define TASK_PRIORITY_NORMAL  2
#define TASK_PRIORITY_LOW     1

xTaskCreate(vTask1, "Task1", 128, NULL, TASK_PRIORITY_HIGH, NULL);
xTaskCreate(vTask2, "Task2", 128, NULL, TASK_PRIORITY_LOW, NULL);

删除任务

// 删除自己
vTaskDelete(NULL);

// 删除其他任务
vTaskDelete(xTaskHandle);

延时与超时

阻塞延时

// 延时 500ms
vTaskDelay(pdMS_TO_TICKS(500));

// 相对延时(从当前时刻开始)
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));

精确延时

TickType_t xLastWakeTime = xTaskGetTickCount();

void vTaskFunction(void *pvParameters) {
    for (;;) {
        // 执行任务
        
        // 精确延时 100ms
        vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(100));
    }
}

任务间通信

队列(Queue)

#include "queue.h"

// 创建队列
QueueHandle_t xQueue = xQueueCreate(10, sizeof(int));

// 发送数据(阻塞等待)
int data = 42;
xQueueSend(xQueue, &data, portMAX_DELAY);

// 接收数据(阻塞等待)
int receivedData;
xQueueReceive(xQueue, &receivedData, portMAX_DELAY);

队列示例:生产者 - 消费者

QueueHandle_t xQueue;

void vProducerTask(void *pvParameters) {
    int data = 0;
    for (;;) {
        xQueueSend(xQueue, &data, portMAX_DELAY);
        data++;
        vTaskDelay(pdMS_TO_TICKS(100));
    }
}

void vConsumerTask(void *pvParameters) {
    int receivedData;
    for (;;) {
        xQueueReceive(xQueue, &receivedData, portMAX_DELAY);
        printf("Received: %d\n", receivedData);
    }
}

void vStartSystem(void) {
    xQueue = xQueueCreate(10, sizeof(int));
    
    xTaskCreate(vProducerTask, "Producer", 128, NULL, 1, NULL);
    xTaskCreate(vConsumerTask, "Consumer", 128, NULL, 1, NULL);
    
    vTaskStartScheduler();
}

同步与互斥

二值信号量

#include "semphr.h"

SemaphoreHandle_t xBinarySemaphore;

void vInterruptHandler(void) {
    // 中断中释放信号量
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    xSemaphoreGiveFromISR(xBinarySemaphore, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

void vTaskFunction(void *pvParameters) {
    for (;;) {
        // 等待信号量
        if (xSemaphoreTake(xBinarySemaphore, portMAX_DELAY) == pdTRUE) {
            // 处理事件
        }
    }
}

void vStartSystem(void) {
    xBinarySemaphore = xSemaphoreCreateBinary();
    xTaskCreate(vTaskFunction, "Task", 128, NULL, 1, NULL);
    vTaskStartScheduler();
}

互斥量(Mutex)

SemaphoreHandle_t xMutex;

void vTask1(void *pvParameters) {
    for (;;) {
        // 获取互斥量
        if (xSemaphoreTake(xMutex, portMAX_DELAY) == pdTRUE) {
            // 访问共享资源
            printf("Task1 accessing shared resource\n");
            vTaskDelay(pdMS_TO_TICKS(100));
            xSemaphoreGive(xMutex);
        }
        vTaskDelay(pdMS_TO_TICKS(200));
    }
}

内存管理

堆管理方案

方案特点适用场景
heap_1只分配,不释放简单系统
heap_2分配 + 释放,不合并固定大小块
heap_3使用 malloc/free通用场景
heap_4分配 + 释放,合并空闲块推荐
heap_5支持多个内存区域复杂系统

配置示例

// FreeRTOSConfig.h
#define configTOTAL_HEAP_SIZE    ((size_t)(10 * 1024))
#define configUSE_MALLOC_FAILED_HOOK 1

void vApplicationMallocFailedHook(void) {
    // 内存分配失败处理
}

实际项目:多传感器数据采集

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

typedef struct {
    float temperature;
    float humidity;
    uint32_t timestamp;
} SensorData_t;

QueueHandle_t xSensorQueue;

// 温度采集任务
void vTempTask(void *pvParameters) {
    SensorData_t data;
    for (;;) {
        data.temperature = readTemperature();
        data.timestamp = xTaskGetTickCount();
        xQueueSend(xSensorQueue, &data, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 湿度采集任务
void vHumidityTask(void *pvParameters) {
    SensorData_t data;
    for (;;) {
        data.humidity = readHumidity();
        data.timestamp = xTaskGetTickCount();
        xQueueSend(xSensorQueue, &data, portMAX_DELAY);
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// 数据处理任务
void vProcessTask(void *pvParameters) {
    SensorData_t data;
    for (;;) {
        xQueueReceive(xSensorQueue, &data, portMAX_DELAY);
        printf("Temp: %.2f, Hum: %.2f, Time: %lu\n",
               data.temperature, data.humidity, data.timestamp);
    }
}

void vStartSystem(void) {
    xSensorQueue = xQueueCreate(10, sizeof(SensorData_t));
    
    xTaskCreate(vTempTask, "Temp", 256, NULL, 1, NULL);
    xTaskCreate(vHumidityTask, "Humidity", 256, NULL, 1, NULL);
    xTaskCreate(vProcessTask, "Process", 512, NULL, 2, NULL);
    
    vTaskStartScheduler();
}

调试技巧

常见问题

问题可能原因解决方法
系统不启动栈太小增加 configMINIMAL_STACK_SIZE
任务不执行优先级太低提高优先级
内存不足堆太小增加 configTOTAL_HEAP_SIZE
死锁互斥量使用不当检查获取顺序

性能监控

// 获取空闲任务计数
uint32_t ulIdleCount = uxTaskGetNumberOfTasks();

// 获取系统运行时间
TickType_t xUptime = xTaskGetTickCount();

// 获取任务列表
TaskStatus_t xTaskStatus[10];
UBaseType_t uxTasks = uxTaskGetNumberOfTasks();
vTaskGetList(xTaskStatus, uxTasks);

结语

FreeRTOS 是嵌入式 RTOS 的事实标准。通过本教程,你掌握了任务管理、通信和同步机制。动手做一个多任务项目吧!


参考资料:FreeRTOS 官方文档、Mastering the FreeRTOS Real Time Kernel