什么是 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