嵌入式面试八股文之FreeRTOS
嵌入式面试八股文之FreeRTOS
为巽1.1 任务 Task
1 | xTaskCreate(task_func, "task", 4096, NULL, 5, &handle); |
动态创建(xTaskCreate):从堆分配TCB和栈,简答灵活。
静态创建(xTaskCreateStaytic):用预分配的数组-不依赖堆、确定性好。资源受限的安全关键场景用静态创建。
1.1.1优先级
在FreeRTOS中,数字越大优先级越高。
1.1.2怎么设置优先级?
1、实时性要求高的任务优先级高
2、耗时但不紧急的任务优先级低
3、高优先级任务不能长时间占用CPU
1.2 队列 Queue
队列是FreeRTO任务间传递数据的安全通道:
发送方put数据->队列缓冲->接收方get数据。
支持阻塞等待(满时等空位/空时等数据)。
1.2.1场景:
- UART接收任务把数据发送给协议解析任务
- 传感器任务把采集结果发送给显示任务
- 中断把事件发送给事件处理任务
1.2.2队列和共享全局变量:
队列更适合任务间传递数据:
1、数据边界清晰
2、可以阻塞等待
3、减少共享变量竞争
4、容易维护
5、自带同步
全局变量:适合简单状态,但是需要考虑同步
1.3 互斥量 Mutex
互斥锁保护共享资源一次只被一个任务访问。互斥锁有优先级继承(防止优先级反转)、持有者概念(只有获取者能释放)。保护共享资源用互斥锁。
1.4 二值信号量
二值信号量只有0和1两个状态-Give设为1(有事件)、Take设为0(处理事件)。典型用途:中断Give->任务Take(中断通知任务)。简单高效,最常用的同步机制。
信号量常用于任务间同步或资源计数。
1.5 计数信号量
计数信号量计数值可以大于1。Give加1、Take减1(为0则阻塞)。
用于:
1、管理多个资源(例如3个UART通道)
2、事件计数(不丢失多次Give)
信号量同于任务间同步或资源计数。
1.6 任务通知 Task Notification
任务通知时FreeRTOS最轻量的同步机制—每个任务内置一个32位通知值和一个通知状态(不需要额外创建内核对象 )。比信号量/队列都快45%(无需创建对象、无需动态内存)。限制:只能点对点通知(不能一对多),
1.7 看门狗
看门狗是一个硬件定时器,作用是检测程序卡死/跑飞,自动复位系统:
工作原理:任务必须定期“喂狗”(重置计数器),如果超时没喂,说明程序出问题 -> 看门狗复位芯片。
独立看门狗 IWDG:
- 独立时钟源(LSI),主时钟挂了也能复位
- 只能防程序跑飞/卡死
窗口看门狗 WWDG:
- 喂狗必须在时间窗口内(太快太慢都复位)
- 能检测程序“跑得太快”(时序异常)
1.7.1 FreeRTOS中的应用
用空闲任务钩子(Idle Hook)+ 计数方式实现任务级监控:
- 每个被监控任务运行时设置一个“活着”标志
- 空闲任务检查所有标志,全部正常才喂狗
- 清零标志,等待下一轮
好处:任何一个任务卡死,空闲任务检测到标志不全 -> 不喂狗 -> 系统复位。
1.7.2 注意
1、喂狗周期要合理:太短容易误复位,太长失去保护意义
2、不要在中断里随意喂狗(会掩盖任务卡死)
3、调试器断点会暂停喂狗,可配置调试时暂停看门狗
1.8 临界区 Critical Section
临界区是一段不允许被打断的代码,用于保护极短的共享资源访问:
1 | taskENTER_CRITICAL(); // 进入临界区(关闭中断/调到最高优先级) |
1.8.1 实现方式
FreeRTOS根据配置不同,进入临界区可能:
- 关中断(禁用可屏蔽中断)
- 或屏蔽到
configMAX_SYSCALL_INTERRUPT_PRIORITY以下的中断
1.8.2 使用原则
1、时间要极短(微秒级):关中断期间无法响应中断,影响实时性
2、临界区内不能调用可能阻塞的API(如 xQueueSend 带阻塞时间)
3、支持嵌套:进出次数配对即可
1.8.3 中断中的临界区
1 | UBaseType_t saved = taskENTER_CRITICAL_FROM_ISR(); |
1.8.4 临界区 vs 互斥量 vs 挂起调度器
| 机制 | 适用场景 | 是否关中断 | 开销 |
|---|---|---|---|
| 临界区 | 任务与中断共享数据(短) | 是 | 小 |
| 互斥量 Mutex | 任务之间共享资源(可长) | 否,有优先级继承 | 中 |
| 挂起调度器 vTaskSuspendAll | 任务之间,不想关中断 | 否 | 小 |
选择建议:
- 和中断共享数据 -> 临界区
- 任务间共享长资源 -> 互斥量
- 任务间共享但不想关中断 -> 挂起调度器



