通过分析任务切换,我们知道任务切换的两种方法:系统节拍器中断、调用portYIELD产生PendSV中断。

在系统节拍器中断中,如果调度器被挂起,仅仅将调度器挂起时间加一(在解除挂起后需要补偿这些节拍),并不会检查是否有任务需要切换。

/* 系统节拍加一 */
BaseType_t xTaskIncrementTick(void)
{BaseType_t xSwitchRequired = pdFALSE;/* 调度器没有被挂起 */if(uxSchedulerSuspended == (UBaseType_t)pdFALSE){......}/* 调度器被挂起 */else{/* 挂起时间加一 */++uxPendedTicks;}/* 前面有程序因为各种原因,要求延迟到现在切换 */if(xYieldPending != pdFALSE){/* 请求切换任务,最终进入PendSV异常,是否切换上下文还是在于PendSV */xSwitchRequired = pdTRUE;}return xSwitchRequired;
}

在PendSV中断中,如果调度器被挂起,则不进行上下文切换,通过xYieldPending将任务切换延迟到下一个节拍。

/* 任务切换上下文 */
void vTaskSwitchContext(void)
{/* 调度器被挂起 */if(uxSchedulerSuspended != (UBaseType_t)pdFALSE){/* 等到下一次节拍的时候再切换上下文 */xYieldPending = pdTRUE;}/* 调度器没有挂起 */else{......}
}

也就是说,只要将调度器挂起,就肯定不会进行任务切换。

挂起调度器非常简单,只要让uxSchedulerSuspended不等于pdFALSE(0)即可。调度器可以多次挂起,但是对应的也要进行多次解除挂起。

/* 挂起调度器 */
void vTaskSuspendAll(void)
{/* 挂起层数加一 */++uxSchedulerSuspended;
}

当完全解除调度器挂起时,需要进行如下工作:

检查在调度器挂起期间是否有任务进入就绪态,有则要将其从挂起期间就绪任务列表中移除,重新挂接到就绪任务列表

更新下一个需要解除阻塞的任务,的解除时间

要对之前调度器挂起期间产生的节拍进行补偿

对于延迟切换任务到下一个节拍的请求,在这里提供一次切换机会

/* 解除调度器挂起 */
BaseType_t xTaskResumeAll( void )
{TCB_t *pxTCB = NULL;BaseType_t xAlreadyYielded = pdFALSE;configASSERT(uxSchedulerSuspended);/* 进入临界区 */taskENTER_CRITICAL();{/* 调度器挂起层数减一 */--uxSchedulerSuspended;/* 调度器挂起完全解除 */if(uxSchedulerSuspended == (UBaseType_t)pdFALSE){/* 系统当前任务数大于0 */if(uxCurrentNumberOfTasks > (UBaseType_t)0U){/* 挂起时进入就绪的任务列表不为空 */while(listLIST_IS_EMPTY(&xPendingReadyList) == pdFALSE){/* 从挂起时进入就绪的任务列表中取出一个任务 */pxTCB = listGET_OWNER_OF_HEAD_ENTRY((&xPendingReadyList));/* 将任务从事件列表中移除 */(void)uxListRemove(&(pxTCB->xEventListItem));/* 将任务从状态列表中移除 */(void)uxListRemove(&(pxTCB->xStateListItem));/* 将任务加入就绪任务列表 */prvAddTaskToReadyList(pxTCB);/* 如果任务优先级高于当前任务优先级,则请求在下一个节拍时切换 */if(pxTCB->uxPriority >= pxCurrentTCB->uxPriority){xYieldPending = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}}/* 有任务在挂起期间就绪 */if(pxTCB != NULL){/* 更新下一个要解除阻塞的时间 */prvResetNextTaskUnblockTime();}{/* 调度器挂起时间 */UBaseType_t uxPendedCounts = uxPendedTicks;/* 调度器挂起时间大于1个节拍 */if(uxPendedCounts > (UBaseType_t)0U){/* 将所有节拍重新补上 */do{/* 节拍数加一,如果需要切换任务,则请求在下一个节拍时切换 */if(xTaskIncrementTick() != pdFALSE){xYieldPending = pdTRUE;}else{mtCOVERAGE_TEST_MARKER();}--uxPendedCounts;}while(uxPendedCounts > (UBaseType_t)0U);uxPendedTicks = 0;}else{mtCOVERAGE_TEST_MARKER();}}/* 原来请求在下一个节拍时切换的任务,在这里直接请求切换 */if(xYieldPending != pdFALSE){#if (configUSE_PREEMPTION != 0){/* 已经切换过任务 */xAlreadyYielded = pdTRUE;}#endiftaskYIELD_IF_USING_PREEMPTION();}else{mtCOVERAGE_TEST_MARKER();}}}else{mtCOVERAGE_TEST_MARKER();}}/* 退出临界区 */taskEXIT_CRITICAL();/* 返回是否已经切换过任务 */return xAlreadyYielded;
}

FreeRTOS调度器挂起与解除相关推荐

  1. 【STM32】FreeRTOS 调度器开启和任务相关函数详解

    文章目录 调度器开启过程分析 调度器开启过程分析 前面的所有例程中我们都是在 main()函数中先创建一个开始任务 start_task,后面紧接着调 用函数 vTaskStartScheduler( ...

  2. FreeRTOS调度器启动

    在真正启动调度器之前,先创建空闲任务,初始化一些变量.真正启动调度器的函数是xPortStartScheduler /* 启动调度器 */ void vTaskStartScheduler( void ...

  3. FreeRTOS个人笔记-挂起/解挂任务

    根据个人的学习方向,学习FreeRTOS.由于野火小哥把FreeRTOS讲得比较含蓄,打算在本专栏尽量细化一点.作为个人笔记,仅供参考或查阅. 配套资料:FreeRTOS内核实现与应用开发实战指南.野 ...

  4. FreeRTOS任务挂起与解除

    任务挂起的主要工作包括: 将任务从状态列表中移除并挂接到挂起列表中 更新任务唤醒时间 如果挂起当前任务,需要请求切换 /* 挂起任务 */ void vTaskSuspend(TaskHandle_t ...

  5. FreeRTOS学习记录 05--任务调度器开启和切换

    文章目录 0 前言 1 任务调度器的开启 1.1 如何启动第一个任务的 2 任务的切换 2.1 PendSV 异常 2.2 两个事件引起PendSV 异常 2.3 PendSV 的中断服务函数 在这里 ...

  6. 任务延时、任务挂起、解除任务挂起、任务优先级获取和设置

    FreeRTOS任务控制API函数主要实现任务延时.任务挂起.解除任务挂起.任务优先级获取和设置等功能. 1.相对延时 1.1函数描述 void vTaskDelay( portTickTypexTi ...

  7. [转]Golang中goroutine的调度器详解

    Go调度器原理浅析 来源:https://www.douban.com/note/300631999/ goroutine是golang的一大特色,或者可以说是最大的特色吧(据我了解),这篇文章主要翻 ...

  8. go语言学习笔记(四):调度器基础-爬上那座山

    目录 调度器概述 调度器初始化 第一个goroutine,main goroutine的创建 第一个goroutine,main goroutine的调度 非main goroutine的创建.退出以 ...

  9. 编写LitmusRT调度器插件

    目录 背景 打桩 编译安装 引入TRACE模块来输出debug信息 为P-EDF定义每个CPU的状态 激活插件 模块测试 添加调度逻辑 帮助函数 demo_job_completion() demo_ ...

最新文章

  1. 台式计算机机箱都一样吗,别以为组装台式机很简单,机箱选择大有学问
  2. oracle查看登录时间黑屏,oracle 11g默认用户名、密码解锁 以及安装后重启黑屏问题.doc...
  3. win2000/2003 Discuz生存环境搭建及基础优化 攻略
  4. 我的学习之路_第十四章_反射
  5. windows2k服务和进程详解
  6. ehd边缘直方图描述子 matlab,一种新的图像空间特征提取方法
  7. java编解码技术,netty nio
  8. 处理MathType的兼容问题(下)
  9. word for mac 输入拼音时出现方框
  10. java 修改Chrome浏览器的默认下载路径
  11. android端的声音检测程序(检测声音分贝大小)
  12. oc引导windows蓝屏_使用Opencore引导ubuntu以及Linux的步骤
  13. NVIDIA INSTANT NGP
  14. 内网访问高德地图nginx代理
  15. python workflow_Python 编写一个有道翻译的 workflow 教程
  16. AWB(Attention WaveBlock)
  17. 【生活感想】期末考试
  18. CSS3笔记(菜鸟教程)
  19. word如何添加页码
  20. 【问题解决】HOST_JUJU_LOCK_PERMISSION 。。

热门文章

  1. Qt工作笔记-右键删除视图中的Item【坐标映射】
  2. C/C++信息隐写术(二)之字符串藏入BMP文件
  3. dhcp服务器显示2个ip,下列关于Windows 2003系统DHCP服务器的描述中,错误的是( )。A.DHCP服务器负责多个网段IP地址分配_考题宝...
  4. django.db.utils.OperationalError: (1040, ‘Too many connections‘)
  5. unity打包android 乱码,Unity3d发布IOS9应用时出现中文乱码的解决方法
  6. openfire php注册,openfire php 初始配置
  7. python读取plt文件吗_用Python读取文件并绘制CDF
  8. 前端基础-html-表格的标题和表头单元格标签
  9. (计算机组成原理)第六章总线-第二节:总线仲裁(链式查询,计数器查询、独立请求)
  10. shell获取命令行结果指定列(指定列结果)