FreeRTOS 核心功能:内核对象、调度策略与内存方案
核心功能:内核对象、调度策略与内存方案
任务与调度。创建任务用 xTaskCreate(动态分配栈)或 xTaskCreateStatic(静态栈,需要 configSUPPORT_STATIC_ALLOCATION)。调度默认是抢占式的:只要有一个更高优先级任务就绪,当前任务立刻被打断。同优先级任务之间默认按时间片轮转(configUSE_TIME_SLICING),把 configUSE_PREEMPTION 置 0 则变成协作式,任务必须主动让出。优先级数值 0 留给空闲任务,用户任务从 1 起,上限由 configMAX_PRIORITIES 决定。
优先级反转与优先级继承。这是新手最容易踩的坑:低优先级任务持有互斥资源,中优先级任务就绪后不断抢占低优先级任务,结果等这把锁的高优先级任务被无限期推迟。用二值信号量当互斥锁就会这样;改用 mutex(configUSE_MUTEXES 置 1,用 xSemaphoreCreateMutex 创建)则启用优先级继承:持锁任务会被临时提升到等待者的优先级,尽快跑完并释放。注意 mutex 不能在中断里 Give 或 Take,中断里只能用信号量。
内核对象一览:
| 对象 | 典型用途 | 注意点 |
|---|---|---|
| Queue 队列 | 任务间传数据,按值拷贝 | 拷贝的是整块数据,大结构体建议传指针 |
| Binary Semaphore | 事件通知、中断与任务同步 | 不带优先级继承,不要当锁用 |
| Counting Semaphore | 资源计数、事件累计 | 需要 configUSE_COUNTING_SEMAPHORES |
| Mutex / Recursive Mutex | 互斥保护共享资源 | 带优先级继承;只能在任务上下文使用 |
| Event Group | 多事件「与/或」等待,一个任务等多方就绪 | 位操作,比堆多个信号量省内存 |
| Stream Buffer / Message Buffer | 单生产者单消费者的字节流 | 适合串口收发缓冲;不是任意多对多 |
| Task Notification | 轻量的任务间通知,可替代只通知一个任务的信号量 | 更快更省 RAM,但每个任务只有一组通知值 |
| Software Timer | 定时回调 | 回调运行在定时器守护任务上下文,不能阻塞 |
五种堆方案的差异。选错会在项目后期付出代价:
| 方案 | 能否释放 | 碎片与合并 | 适用场景 |
|---|---|---|---|
| heap_1 | 不能释放 | 只有分配,没有碎片问题 | 安全关键系统:任务在启动时一次性创建完,之后不再动态分配 |
| heap_2 | 能释放 | 不合并相邻空闲块,容易碎片化 | 官方已不推荐新项目使用 |
| heap_3 | 能释放 | 交给标准库的 malloc 与 free | 自己已有一份线程安全的堆,或需要与已有内存管理统一 |
| heap_4 | 能释放 | 首次适配并合并相邻空闲块 | 最常用,通用场景默认选它 |
| heap_5 | 能释放 | 同 heap_4,且支持多块不连续区域 | 片内 SRAM 与外部 SDRAM 拼成一个堆 |
关键 config 宏。
| 宏 | 作用 | 备注 |
|---|---|---|
| configTICK_RATE_HZ | tick 频率 | 越高延时粒度越细,切换开销也越大 |
| configMAX_PRIORITIES | 优先级档数 | 影响就绪表占用的内存 |
| configMINIMAL_STACK_SIZE | 空闲任务栈大小 | 单位是字,不是字节 |
| configTOTAL_HEAP_SIZE | FreeRTOS 堆总大小 | 只对 heap_1、heap_2、heap_4、heap_5 有效 |
| configMAX_SYSCALL_INTERRUPT_PRIORITY | 允许调用 FromISR API 的中断优先级下限 | Cortex-M 上数值越大优先级越低,必须与 NVIC 优先级分组一起配 |
| configUSE_PREEMPTION | 抢占式调度开关 | 置 0 变协作式 |
| configUSE_TIME_SLICING | 同优先级任务是否轮转 | 置 0 可以减少切换 |
| configUSE_MUTEXES | 启用 mutex 与优先级继承 | 需要互斥就别关 |
| configUSE_TICKLESS_IDLE | 低功耗 tickless 模式 | 需要低功耗定时器与 port 支持配合 |
| configCHECK_FOR_STACK_OVERFLOW | 栈溢出检测等级 0 / 1 / 2 | 开发阶段建议 2,量产可保留 1 |
| configASSERT | 参数与状态断言 | 开发阶段一定要开 |
| configGENERATE_RUN_TIME_STATS | 统计各任务 CPU 占用 | 需要一个高频计时源 |

