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

/*
 * -----------------------------------------------------------
 * 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 */
	}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值