☰
FreeRTOS入坑指南
2026/10/10 1:15:09 网站建设 项目流程

开发环境准备:

一般平台都有自己的开发环境。 例如nxp 有mcu xpresso 开发工具。 这里我们推荐linux 上的freertos模拟器。 感谢GitHub - crazyskady/FreeRTOS_study: Study for FreeRTOShttps://github.com/crazyskady/FreeRTOS_study贡献的代码, 我们把代码拉到本地 , 增加一个tmp 目录, 就可以顺利编译通过。

下面就可以开启 freertos 之旅了。

1.任务管理

FreeRTOS 最核心的就是任务(Task),任务就是独立可调度的函数,每个任务拥有独立栈空间、独立上下文,由内核抢占式调度。 任务状态:就绪 (Ready)、运行 (Running)、阻塞 (Blocked)、挂起 (Suspended)。

核心 API

  • xTaskCreate():动态创建任务
  • vTaskDelay():相对延时,任务进入阻塞(推荐)
  • vTaskDelayUntil():绝对周期延时,适合固定周期任务
  • vTaskSuspend()/vTaskResume():任务挂起 / 恢复
  • uxTaskGetStackHighWaterMark():查看任务栈剩余空间,排查栈溢出
  • vTaskDelete():删除任务

2.队列管理

#include <stdio.h> #include <stdlib.h> #include "main.h" #include "FreeRTOS.h" #include "task.h" #include "queue.h" typedef struct { int ID; portCHAR Data[ 20 ]; } Message, *pMessage; //xQueueHandle MsgQueue; xQueueHandle MsgQueue; void TaskA( void *pvParameters ); void TaskB( void *pvParameters ); static void vSenderTask(void *pvParameters){ printf("创建发送TASK \n"); Message message; message.ID=1; strcpy(message.Data, "hello"); portBASE_TYPE xStatus; for (; ;) { // vTaskDelay( 2000/portTICK_RATE_MS ); xStatus = xQueueSend( MsgQueue, (void *)&message, 0 ); if(xStatus != pdPASS ){ printf("could not send to the queue \r\n"); }else{ printf("send ID =%d , DATA =%s\r\n", message.ID, message.Data ); } taskYIELD(); message.ID++; } } static void vReceiverTask(void *pvParamters){ printf("创建接收TASK \n"); Message message; portBASE_TYPE xStatus; const portTickType xTicksToWait = 100/portTICK_RATE_MS; for (; ;) { if (uxQueueMessagesWaiting(MsgQueue) != 0) { printf("queue should have been empty ! \r\n"); } xStatus = xQueueReceive(MsgQueue, &message, xTicksToWait); if (xStatus == pdPASS) { printf("received ID = %d, DATA= %s \r\n", message.ID, message.Data); } else { printf("could not receive from the queue \r\n"); } } } int main(void ){ MsgQueue = xQueueCreate( 5 , sizeof( Message ) ); if(MsgQueue != NULL ){ printf("创建两个TASK \n"); xTaskCreate( vSenderTask, "Sender1", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1 ,NULL); xTaskCreate( vReceiverTask, "Receiver", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1 ,NULL); vTaskStartScheduler(); printf("start task \r\n"); return 0; }else{ printf("Error \n"); } return 0; } void vMainQueueSendPassed( void ) { return; } /* This is a stub function for FreeRTOS_Kernel */ void vApplicationIdleHook( void ) { return; }

替换 main.c, 既是一个简单的队列管理模型。

3.中断管理

嵌入式场景大量使用中断(CAN 接收、定时器、IO 外部中断)。

⚠️ 关键规则:普通 FreeRTOS API 不能在中断服务函数 ISR 中调用!中断里只能调用后缀为FromISR的 API:xQueueSendFromISR、xSemaphoreGiveFromISR。 中断中业务逻辑尽量简短:仅接收硬件数据、丢队列 / 释放信号量,复杂业务放到任务中处理。

常用 API

  • xQueueSendFromISR():中断向队列发送消息
  • xSemaphoreGiveFromISR():中断释放信号量,唤醒等待任务
  • portYIELD_FROM_ISR():中断退出时,判断是否需要任务切换

4.资源管理

多任务并发,全局变量、硬件外设属于共享资源,会出现竞态冲突。FreeRTOS 提供信号量、互斥锁保护资源。

  • 互斥锁 Mutex(xSemaphoreCreateMutex):用于保护共享资源,自带优先级继承,防止优先级反转。适合多任务访问全局变量。
  • 二值信号量 Binary Semaphore:多用于中断唤醒任务(事件通知)。
  • 计数信号量 Counting Semaphore:资源计数,例如多个硬件缓冲区。

❗ 互斥锁不能在中断中使用,仅任务内使用。

5.内存管理

FreeRTOS 提供pvPortMalloc/vPortFree,有 5 种 heap 方案,常用 heap1/heap2/heap4。

  • heap1:只分配不释放,适合简单静态设备;
  • heap2:链表,支持 malloc/free,内存碎片问题;
  • heap4:最佳实践,支持合并空闲块,减少碎片,项目推荐。

不建议直接使用标准库malloc,容易和 RTOS 冲突,优先使用 RTOS 自带内存接口。

6.文件管理

FreeRTOS 内核本身不带文件系统,一般搭配FatFS(最常用轻量文件系统),实现读写 SD 卡 / Flash 文件。 架构:FreeRTOS 任务负责调度,FatFS 负责文件 IO;多任务读写文件需要加互斥锁保护,防止文件操作冲突。

Linux 模拟器环境下,可以直接映射主机文件模拟 SD 卡。

7.网络编程

目录是参考linux等平台,和项目开发过程中用到的知识点,总结列举出的。 逐步把代码模型补充完整。

FreeRTOS 本身无 TCP/IP 协议栈,搭配lwIP(light weight IP),嵌入式标准轻量网络协议栈。 典型架构:

  1. lwIP 有两种模式:RAW API(无任务,回调)、NETCONN API(线程安全,搭配 FreeRTOS 任务)
  2. 网卡中断唤醒 lwIP,数据包投递到任务处理;车载以太网常用这套组合。

参考:

在Linux下实现FreeRTOS的简单模拟器_crazyskady的博客-CSDN博客_freertos linux模拟器

《freeRTOS操作系统中文版手册.pdf》

欢迎阅读韦东山百问网freeRTOS教程! — 韦东山百问网freeRTOS教程 文档

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询