简单聊一下FreeRTOS
FreeRTOS 是一个轻量级的实时操作系统(RTOS),特别适合嵌入式开发,比如用在 ESP32、STM32 这种小芯片上。
啥是 FreeRTOS?
想象你在开饭店,厨房只有一个厨师(单线程),忙不过来咋办?雇几个厨师(多线程),但得有人管着,不然乱套。FreeRTOS 就像个“厨房经理”,帮你调度多个任务(线程),让它们在小小的芯片上高效跑起来,还能保证关键任务优先干。它特别适合需要“实时”响应的场景,比如传感器一有数据就得马上处理。
简单说:FreeRTOS 是一个小而美的任务调度系统,帮你在嵌入式设备上跑多任务。
用 FreeRTOS 开发时,主要得搞懂这几块:任务管理、同步工具、队列通信、时间管理和内存管理
1. 任务管理:让多个活儿一起跑
啥是任务? 任务就是你想让芯片干的活儿,比如点灯、读传感器、发数据。FreeRTOS 能同时跑多个任务,还能决定谁先干。
例子:点灯和读温度
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
void blink_task(void *pvParameters) {
while (1) {
printf("灯闪一下\n");
vTaskDelay(1000 / portTICK_PERIOD_MS); // 等1秒
}
}
void temp_task(void *pvParameters) {
while (1) {
printf("读温度\n");
vTaskDelay(2000 / portTICK_PERIOD_MS); // 等2秒
}
}
int main() {
xTaskCreate(blink_task, "Blink", 2048, NULL, 1, NULL); // 任务1:点灯
xTaskCreate(temp_task, "Temp", 2048, NULL, 1, NULL); // 任务2:读温度
vTaskStartScheduler(); // 开跑
return 0;
}
xTaskCreate(函数, 名字, 栈大小, 参数, 优先级, 句柄):创建任务。 vTaskDelay(毫秒 / portTICKPERIODMS):让任务睡一会儿,别一直占着 CPU。 输出可能是:
灯闪一下
读温度
(等1秒)
灯闪一下
(等1秒)
灯闪一下
读温度
要掌握啥?
创建任务:xTaskCreate。
任务优先级:数字越大越优先(比如 2 比 1 先跑)。
任务休眠:vTaskDelay 让出 CPU,别卡死。
2. 同步工具:别抢着干活
啥是同步? 多个任务可能抢资源,比如都想写串口。FreeRTOS 提供信号量和互斥锁,管住谁先谁后。
例子:用信号量控制串口
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
SemaphoreHandle_t serial_lock;
void task1(void *pvParameters) {
while (1) {
if (xSemaphoreTake(serial_lock, portMAX_DELAY) == pdTRUE) {
printf("任务1: 用串口\n");
vTaskDelay(500 / portTICK_PERIOD_MS);
xSemaphoreGive(serial_lock); // 释放
}
}
}
void task2(void *pvParameters) {
while (1) {
if (xSemaphoreTake(serial_lock, portMAX_DELAY) == pdTRUE) {
printf("任务2: 用串口\n");
vTaskDelay(500 / portTICK_PERIOD_MS);
xSemaphoreGive(serial_lock);
}
}
}
int main() {
serial_lock = xSemaphoreCreateMutex(); // 创建互斥锁
xTaskCreate(task1, "T1", 2048, NULL, 1, NULL);
xTaskCreate(task2, "T2", 2048, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}
xSemaphoreCreateMutex():创建互斥锁。
xSemaphoreTake(锁, 等待时间):拿锁,没拿到就等。
xSemaphoreGive(锁):还锁。
输出可能是:
任务1: 用串口
(等0.5秒)
任务2: 用串口
(等0.5秒)
任务1: 用串口
要掌握啥? 互斥锁:xSemaphoreCreateMutex、Take、Give,防抢资源。 二进制信号量:xSemaphoreCreateBinary,适合“通知”场景。 等待时间:portMAX_DELAY(一直等)或具体 ticks。
3. 队列通信:任务间传东西
啥是队列? 任务之间得传数据,比如传感器任务把温度传给显示任务。队列就像个“传送带”。
例子:传温度数据
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
QueueHandle_t temp_queue;
void sensor_task(void *pvParameters) {
int temp = 25;
while (1) {
xQueueSend(temp_queue, &temp, portMAX_DELAY); // 发数据
temp++;
vTaskDelay(1000 / portTICK_PERIOD_MS);
}
}
void display_task(void *pvParameters) {
int received_temp;
while (1) {
if (xQueueReceive(temp_queue, &received_temp, portMAX_DELAY) == pdTRUE) {
printf("显示温度: %d\n", received_temp);
}
}
}
int main() {
temp_queue = xQueueCreate(5, sizeof(int)); // 队列能存5个int
xTaskCreate(sensor_task, "Sensor", 2048, NULL, 1, NULL);
xTaskCreate(display_task, "Display", 2048, NULL, 1, NULL);
vTaskStartScheduler();
return 0;
}
xQueueCreate(长度, 数据大小):创建队列。
xQueueSend(队列, 数据指针, 等待时间):发数据。
xQueueReceive(队列, 接收指针, 等待时间):收数据。
输出:
显示温度: 25
(等1秒)
显示温度: 26
要掌握啥?
创建队列:xQueueCreate。
发送和接收:xQueueSend 和 xQueueReceive。
队列满/空处理:用返回值判断。
- 时间管理:定时干活 啥是时间管理? 有些活儿得定时跑,比如每秒检查一次状态。FreeRTOS 有软件定时器。
例子:定时打印
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/timers.h"
void timer_callback(TimerHandle_t xTimer) {
printf("定时器喊: 到点了!\n");
}
int main() {
TimerHandle_t timer = xTimerCreate("MyTimer", 1000 / portTICK_PERIOD_MS, pdTRUE, NULL, timer_callback);
xTimerStart(timer, 0); // 启动定时器
vTaskStartScheduler();
return 0;
}
xTimerCreate(名字, 周期, 是否重复, 参数, 回调):创建定时器。 xTimerStart(定时器, 等待时间):开跑。
输出:
定时器喊: 到点了!
(等1秒)
定时器喊: 到点了!
要掌握啥?
创建定时器:xTimerCreate。
启动/停止:xTimerStart、xTimerStop。
单次 vs 重复:pdFALSE(一次)或 pdTRUE(循环)。
5. 内存管理:别乱用空间
啥是内存管理?
嵌入式设备内存小,FreeRTOS 默认用动态内存分配(pvPortMalloc),但得小心用。
例子:任务栈大小
xTaskCreate(my_task, "Task", 2048, NULL, 1, NULL); // 栈2048字节
栈太小(比如 512),任务可能崩溃。 栈太大,浪费内存。
要掌握啥?
栈大小:调 xTaskCreate 的第3个参数,够用就行。
动态分配:pvPortMalloc 和 vPortFree,别漏内存。
配置:了解 FreeRTOSConfig.h 里的 configTOTALHEAPSIZE。
总结:程序员的核心技能 任务管理:会创建任务、调优先级、用 vTaskDelay。 同步工具:用信号量、互斥锁防冲突。 队列通信:任务间传数据靠队列。 时间管理:定时器搞定周期任务。 内存管理:栈和堆别用崩。
文档信息
版权声明:可自由转载(请注明转载出处)-非商用-非衍生
发表时间:2025年7月1日 11:00