freertos中空闲任务函数prvIdleTask()详解

2023-11-16

/*
 * -----------------------------------------------------------
 * The Idle task.  空闲任务函数
 * ----------------------------------------------------------
 *
 * The portTASK_FUNCTION() macro is used to allow port/compiler specific
 * language extensions.  The equivalent prototype for this function is:
 *
 * void prvIdleTask( void *pvParameters );
 * 就是下面的static portTASK_FUNCTION( prvIdleTask, pvParameters )
 */
static portTASK_FUNCTION( prvIdleTask, pvParameters )
{
	/* Stop warnings. */
	( void ) pvParameters;  //防止报错

	/** THIS IS THE RTOS IDLE TASK - WHICH IS CREATED AUTOMATICALLY WHEN THE
	SCHEDULER IS STARTED. **/

	for( ;; )
	{
		/* See if any tasks have deleted themselves - if so then the idle task
		is responsible for freeing the deleted task's TCB and stack. */
		
		//下面的这个函数用来检查是不是有任务要杀死自己,如果有就释放这些任务的TCB和任务堆栈内存
		prvCheckTasksWaitingTermination();  //有任务使用vTaskDelete()删除自身,就将这任务添加到xTasksWaitingTermination列表中
		                                    //函数prvCheckTasksWaitingTermination()检查列表是否为空,不为空的话就将列表中的任务TCB和堆栈内存删除

		#if ( configUSE_PREEMPTION == 0 )
		{
			/* If we are not using preemption we keep forcing a task switch to
			see if any other task has become available.  If we are using
			preemption we don't need to do this as any task becoming available
			will automatically get the processor anyway. */
			
			//如果没有使用抢占式内核的话就强制进行一次任务切换查看是否有其他
			//任务有效,如果有使用抢占式内核的话就不需要这一步,因为只要有任
			//何任务有效(就绪)之后都会自动的抢夺 CPU 使用权
			taskYIELD();
		}
		#endif /* configUSE_PREEMPTION */

		#if ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) )
		{
			/* When using preemption tasks of equal priority will be
			timesliced.  If a task that is sharing the idle priority is ready
			to run then the idle task should yield before the end of the
			timeslice.

			A critical region is not required here as we are just reading from
			the list, and an occasional incorrect value will not matter.  If
			the ready list at the idle priority contains more than one task
			then a task other than the idle task is ready to execute. */
			
			//如果使用抢占式内核并且使能时间片调度的话,当有任务和空闲任务共享
			//一个优先级的时候,并且此任务处于就绪态的话空闲任务就应该放弃本时
			//间片,将本时间片剩余的时间让给这个就绪任务。如果在空闲任务优先级
			//下的就绪列表中有多个用户任务的话就执行这些任务。
			if( listCURRENT_LIST_LENGTH( &( pxReadyTasksLists[ tskIDLE_PRIORITY ] ) ) > ( UBaseType_t ) 1 )
			{ //检查跟空闲任务一样优先级的任务列表中是不是空的,如果不是空的就进行任务调度
				taskYIELD();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		#endif /* ( ( configUSE_PREEMPTION == 1 ) && ( configIDLE_SHOULD_YIELD == 1 ) ) */

		#if ( configUSE_IDLE_HOOK == 1 )
		{
			extern void vApplicationIdleHook( void );

			/* Call the user defined function from within the idle task.  This
			allows the application designer to add background functionality
			without the overhead of a separate task.
			NOTE: vApplicationIdleHook() MUST NOT, UNDER ANY CIRCUMSTANCES,
			CALL A FUNCTION THAT MIGHT BLOCK. */
			
			//在调度器启动以后会自动创建一个空闲任务
			//如果定义了宏configUSE_IDLE_HOOK就在创建任务的时候调用一次钩子函数
			//执行用户定义的空闲任务钩子函数,注意!钩子函数里面不能使用任何
			//可以引起阻塞空闲任务的 API 函数。
			vApplicationIdleHook();
		}
		#endif /* configUSE_IDLE_HOOK */

		/* This conditional compilation should use inequality to 0, not equality
		to 1.  This is to ensure portSUPPRESS_TICKS_AND_SLEEP() is called when
		user defined low power mode	implementations require
		configUSE_TICKLESS_IDLE to be set to a value other than 1. */
		
		#if ( configUSE_TICKLESS_IDLE != 0 ) //如果使能了Tickless模式就执行相关代码
		{                                    //下面的代码是跟低功耗模式相关的代码
			TickType_t xExpectedIdleTime;

			/* It is not desirable to suspend then resume the scheduler on
			each iteration of the idle task.  Therefore, a preliminary
			test of the expected idle time is performed without the
			scheduler suspended.  The result here is not necessarily
			valid. */
			xExpectedIdleTime = prvGetExpectedIdleTime();  //将进入低功耗模式的时长保存在xExpectedIdleTime中

			if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP ) //进入低功耗的时长必须大于宏configEXPECTED_IDLE_TIME_BEFORE_SLEEP
			{
				vTaskSuspendAll();
				{
					/* Now the scheduler is suspended, the expected idle
					time can be sampled again, and this time its value can
					be used. */
					configASSERT( xNextTaskUnblockTime >= xTickCount );
					xExpectedIdleTime = prvGetExpectedIdleTime();    //再获取一次进入低功耗的时间

					if( xExpectedIdleTime >= configEXPECTED_IDLE_TIME_BEFORE_SLEEP )
					{
						traceLOW_POWER_IDLE_BEGIN();
						portSUPPRESS_TICKS_AND_SLEEP( xExpectedIdleTime );  //调用portSUPPRESS_TICKS_AND_SLEEP()进入低功耗模式
						traceLOW_POWER_IDLE_END();
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
				}
				( void ) xTaskResumeAll();
			}
			else
			{
				mtCOVERAGE_TEST_MARKER();
			}
		}
		#endif /* configUSE_TICKLESS_IDLE */
	}
}

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

freertos中空闲任务函数prvIdleTask()详解 的相关文章

随机推荐

  • SSD预测错误调试:RuntimeError: index_select(): functions with out=... arguments don‘t support automatic dif

    一 错误 运行SSD pytorch版本时 运行test py时 遇到这种错误 RuntimeError index select functions with out arguments don t support automatic d
  • Kafka面试必问几个概念 与 使用场景

    介绍下我写的这个kafka项目 里面做了详细的配置注释已经代码的demo 可供大家学习 项目 地址 springboot kafka集群项目实战 kafka集群批量消费数据去重和一致性 kafka的几个重要概念 接下来围绕下面几个概念来进行
  • 运放中接电容的作用

    运放概述 案例讲解 运算分析 一 基本概念 反向放大器 优点 两个输入端电位始终近似为零 同相端接地 反相端虚地 只有差模信号 抗干扰能力强 缺点 输入阻抗很小 等于信号到输入端的串联电阻的阻值 同相放大器 优点 输入阻抗和运放的输入阻抗相
  • 《JavaScript高级程序设计(第四版)》红宝书学习笔记(2)(第四章:变量、作用域与内存)

    个人对第四版红宝书的学习笔记 不适合小白阅读 这是part2 持续更新 其他章节笔记看我主页 记 的表示是ES6新增的知识点 记 表示包含新知识点 第四章 变量 作用域与内存 4 1 原始值与引用值 ECMAScript变量可以包含两种不同
  • C获取linux系统环境变量方法(Environment Variables)

    主要有三种方法 都很简单 1 一个单纯c语言获取的方式 span style font family none font size 14px include span
  • Java系列8—对象创建的内存分配和构造方法

    对象的创建 类和对象的区别 面向对象 java语言的核心机制 最重要的内容 java语言的特色 面向过程和面向对象的区别 面向过程 主要关注点是 实现的具体过程 因果关系 面向对象 主要关注对象 独立体 能完成哪些功能 优点 耦合度低 扩展
  • 态势感知(SIP)

    SIP态势感知 一 SIP态势感知概述 1 业界标准 数据来源 gt 智能分析 gt 安全可视 gt 协同响应 通过日志采集探针和流量传感器分别进行不同系统日志和流量日志的采集和处理任务 通过对海量数据进行多维度快速 自动化的关联分析发现本
  • 跨框架解决方案-Mitosis【问题与局限】

    不要定义与状态属性同名的变量 async方法不能定义在state内 函数不能通过引用直接传递给JSX回调函数 可以在回调函数中定义一个匿名函数 不能将 params 分配给 state 不能将函数输出分配给 state state不能被解构
  • dart 相关资源收集

    百丈高楼平地起 要想写好flutter 必先学号dart 资源 给 Android 开发者的 Dart 教程 学好 Dart 才能玩转 Flutter
  • ms-repeat 数据渲染后触发事件

    ms repeat 数据渲染后触发 data repeat rendered 例子 div class timebox h3 el year 年 el month 月 h3 ul li li ul div
  • MVC设计思想

    1 MVC思想的说明 经典MVC模式中 M是指业务模型 V是指用户界面 C则是控制器 使用MVC的目的是将M和V的实现代码分离 从而使同一个程序可以使用不同的表现形式 其中 View的定义比较清晰 就是用户界面 M model 业务模型 V
  • 24个笔画顺序表_语文老师整理:560个小学常用汉字笔画笔顺表!小学阶段多练习...

    今天给大家分享的是资深语文老师整理的学习资料 560个小学常用汉字笔画笔顺表 家里有小学生的家长 建议帮孩子存好 小学阶段多练习 不仅对语文学习的提高有帮助 还能培养孩子的语文素养 在小学语文的学习中 汉字是最基础的知识点 孩子在学习语文的
  • Codeforces Round #561 (Div. 2)ABC

    三个题 各位大佬别喷我 我很菜 A Silent Classroom There are n students in the first grade of Nlogonia high school The principal wishes
  • 【03】上下文

    基于智能 合约的安全企业对消费者供应链系统在农产品供应链中使用区块链和智能 合约进行追溯链上 链下 智能 合约的可扩展和隐私保护设计TinyEVM 低功耗物联网设备上的链下 智能 合约区块链技术中的智能 合约和用例概述Blockumulus
  • Java的8种基本数据类型

    博主前些天发现了一个巨牛的人工智能学习网站 通俗易懂 风趣幽默 忍不住也分享一下给大家 点击跳转到网站 前言 Java数据类型分为两大类 基本数据类型 引用类型 如图所示 下面讲解的是Java的八种基本数据类型 一 按照数据类型来分 1 整
  • 西门子变频器SINAMICS S120电源模块分享

    西门子变频器SINAMICS S120系列 在工业领域中能胜任各种要求严格的驱动控制任务 为用户提供简单有效的驱动控制过程 西门子变频器SINAMICS S120系列可以配置电源模块 来为西门子变频器驱动控制系统提供稳定的电源保障 本文下面
  • 设计模式-模板方法

    文章目录 前言 模板方法模式简介 Java代码示例 模板方法使用场景 模板方法使用场景 前言 当我们需要在一个算法的框架中定义算法的骨架 并将一些步骤的具体实现留给子类来完成时 模板方法模式是一种非常有用的设计模式 这篇博客将介绍模板方法模
  • install.packages(“hgu133a.db“)报错——解决办法

    问题描述 install packages hgu133a db WARNING Rtools is required to build R packages but is not currently installed Please do
  • Sqli-Labs Less1-16关详细讲解

    Sqli Labs Less1 16关详细讲解 一 首先介绍一下这个重要的数据库 information schema数据库 二 Sqli Labs靶场 Get传输方式 Less 1 Union Select注入 闭合符 Less 5 报错
  • freertos中空闲任务函数prvIdleTask()详解

    The Idle task 空闲任务函数 The portTASK FUNCTION macro is used to allow port compiler specific language extensions The equival