FreeRTOS源码理解(四)——任务调度器

本文系列深入解析FreeRTOS源码,涵盖任务调度器的开启、中断管理、任务创建、时间管理、队列与信号量等关键组件,帮助理解操作系统内核工作原理。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FreeRTOS源码理解(一)——FreeRTOS思路梳理

FreeRTOS源码理解(二)——中断和列表项

FreeRTOS源码理解(三)——任务

FreeRTOS源码理解(四)——任务调度器

FreeRTOS源码理解(五)——任务切换

FreeRTOS源码理解(六)——时间管理

FreeRTOS源码理解(七)——队列

FreeRTOS源码理解(八)——信号量

FreeRTOS源码理解(九)——事件组和任务通知

FreeRTOS源码理解(十)——软件定时器和空闲任务

FreeRTOS源码理解(十一)——内存管理

FreeRTOS源码理解(十二)——汇总

任务调度器

任务调度器的开启 vTaskStartScheduler

  1. 创建空闲任务和软件定时器
  2. 关中断 portDISABLE_INTERRUPTS();
  3. 允许运行任务调度器 xSchedulerRunning = pdTRUE;
  4. 开启任务调度器,初始化相关硬件 xPortStartScheduler()

开启任务调度器,初始化 xPortStartScheduler

  1. 设置pendsv和滴答定时器优先级为最低优先级
  2. 设置滴答定时器的周期
  3. 初始化临界区嵌套计时器
  4. 开始第一个任务 prvStartFirstTask();

开启第一个任务 prvStartFirstTask

  1. 获取MSP的初始值,复位MSP
  2. 使能中断
  3. 数据和指令同步(保证数据和指令的写入和执行,而非在缓冲区)
  4. 触发SVC中断

SVC中断服务函数

中断服务函数:SVC_Handler()

  1. 取当前任务的TCB块,获取栈顶指针赋值给r0
  2. 寄存器出栈
  3. 进程栈PSP指针初始化为任务堆栈
  4. 指令同步
  5. 开启中断

空闲任务

在vTaskStartScheduler函数中会创建一个空闲任务,这个任务优先级最低,功能有:

  1. 判断系统是否有任务删除
  2. 运行用户设置的空闲任务钩子函数
  3. 低功耗模式的开启与处理

调度器的挂起和恢复 vTaskSuspendAll xTaskResumeAll

vTaskSuspendAll:任务挂起所有主要是使得滴答定时器不在更新系统时钟节拍数(xTickCount),系统就会认为时间仍未达到唤醒其他任务的时间,这样就不会进行任务切换了;挂起时候用uxPendedTicks来记录时间节拍;同时将任务调度器挂起,即将更改标志位

xTaskResumeAll:相反,恢复xTickCount计数时钟节拍数;恢复任务调度器,即将更改标志位

文档汇总

文档汇总

### GD32F303 FreeRTOS 任务调度不工作的解决方案 当遇到GD32F303上FreeRTOS任务调度无法正常工作的情况时,可能的原因涉及多个方面。以下是详细的排查和解决方法: #### 1. 初始化配置检查 确保FreeRTOS的初始化配置正确无误。这包括但不限于堆栈大小、任务优先级设置以及系统滴答定时(SysTick)的配置。 对于GD32F303而言,正确的初始化过程至关重要[^1]。如果这些参数被错误设定,则可能导致任务创建失败或调度异常。 #### 2. 中断优先级调整 中断优先级不当可能会干扰RTOS内核运行机制,进而影响任务切换效率甚至阻止其发生。具体来说,在Cortex-M系列MCU中,所有用于RTOS服务函数调用的服务请求应该具有较低的抢占优先级;而外设产生的IRQ则需保持较高水平以便及时响应外部事件[^2]。 #### 3. 堆栈溢出检测 另一个常见问题是由于分配给各线程/协程的空间不足而导致崩溃现象——即所谓的“Stack Overflow”。可以通过增加默认堆栈尺寸来尝试解决问题,也可以利用调试工具监视实际占用情况并据此作出相应修改。 #### 4. 调度算法验证 确认所使用的版本是否已知存在缺陷,并查阅官方发布的补丁说明文档获取修复建议。此外,还可以对比其他成功案例中的源码片段找出差异之处加以优化改进。 ```c // 示例:定义两个不同优先级的任务 void vTask1(void *pvParameters) { while (true) { // 执行一些操作... vTaskDelay(pdMS_TO_TICKS(100)); } } void vTask2(void *pvParameters) { while (true) { // 执行另一些操作... vTaskDelay(pdMS_TO_TICKS(500)); } } ``` 上述代码展示了如何创建两个具有不同延迟时间的任务实例。请注意适当调整`vTaskPrioritySet()`等API调用来满足特定应用的需求。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值