FreeRtos -验证xTaskResumeAll是否能够唤醒已被vTaskSuspend的任务

验证xTaskResumeAll是否能够唤醒已被vTaskSuspend的任务

先说结论,xTaskResumeAll 无法唤醒已被vTaskSuspend的任务。

其实从xTaskResumeAll 的源码及vTaskResume的源码就可以看出来,两个函数的功能相似确截然不同;

xTaskResumeAll 主要是释放计数器,以及将等待的任务转移到就绪列表,并不涉及到挂起的任务

BaseType_t xTaskResumeAll( void )
{
TCB_t *pxTCB = NULL;
BaseType_t xAlreadyYielded = pdFALSE;

	//屏蔽中断.
	taskENTER_CRITICAL();
	{
		// 将计数减一
		--uxSchedulerSuspended;
		// 如果等于0,则允许调度
		if( uxSchedulerSuspended == ( UBaseType_t ) pdFALSE )
		{
			//线程数量大于0,才可能进行调度
			if( uxCurrentNumberOfTasks > ( UBaseType_t ) 0U )
			{
				/* pending 中的线程数量(停止线程调度时候,积攒下来的线程数) > 0		 */
				while( listLIST_IS_EMPTY( &xPendingReadyList ) == pdFALSE )
				{
					/*将所有在xPendingReadyList中的任务移到对应的就绪链表中 */
					pxTCB = ( TCB_t * ) listGET_OWNER_OF_HEAD_ENTRY( ( &xPendingReadyList ) );
					( void ) uxListRemove( &( pxTCB->xEventListItem ) );
					( void ) uxListRemove( &( pxTCB->xStateListItem ) );
					prvAddTaskToReadyList( pxTCB );

					/* 如果pending中的线程任务优先级大于当前线程的优先级.需要做调度线程 */
					if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
					{
						xYieldPending = pdTRUE;
					}
				}

				if( pxTCB != NULL )
				{
					/* 获取下次需要唤醒线程的那一刻的时间.如果没有那就 portMAX_DELAY
					如果有的话,把时间保存在xNextTaskUnblockTime中*/
					prvResetNextTaskUnblockTime();
				}

				/* 如果在禁止调度期间,有时钟节拍中断发生,则我们把发生的次数记录在uxPendedTicks中,称为丢失的时钟节拍数;
				我们在这里模拟uxMissedTicks次时钟节拍中断,也就是说调用uxPendedTicks次时钟节拍isr: vTaskIncrementTick()。
				这样保证了所有任务的延时量不会出现偏差,它们将在正确的时间被唤醒*/ */
				{
					UBaseType_t uxPendedCounts = uxPendedTicks; /* Non-volatile copy. */

					if( uxPendedCounts > ( UBaseType_t ) 0U )
					{
						do
						{
							/*xTaskIncrementTick:详细的可看下面
							1,重新增加xTickCount.
							2,线程中是否存在等待调度的信息.
							*/
							if( xTaskIncrementTick() != pdFALSE )
							{
								//存在需要调度的线程
								xYieldPending = pdTRUE;
							}
							--uxPendedCounts;
						} while( uxPendedCounts > ( UBaseType_t ) 0U );

						uxPendedTicks = 0;
					}
				}
 				//如果存在需要调度的线程
				if( xYieldPending != pdFALSE )
				{
					#if( configUSE_PREEMPTION != 0 )
					{
						xAlreadyYielded = pdTRUE;
					}
					#endif
					taskYIELD_IF_USING_PREEMPTION();
				}
			}
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}
	//放开中断
	taskEXIT_CRITICAL();

	return xAlreadyYielded;
}

vTaskResume 任务很明显对挂起列表的任务做了处理

void vTaskResume( TaskHandle_t xTaskToResume )
	{
	/*把句柄赋值给任务控制块指针*/
	TCB_t * const pxTCB = ( TCB_t * ) xTaskToResume;
 
		/* It does not make sense to resume the calling task. */
		configASSERT( xTaskToResume );
 
		/* The parameter cannot be NULL as it is impossible to resume the
		currently executing task. */
		/*带进来的任务块不能是正在运行任务,不能等于NULL,*/
		if( ( pxTCB != NULL ) && ( pxTCB != pxCurrentTCB ) )
		{
			/*进入临界区*/
			taskENTER_CRITICAL();
			{	/*判断这个任务是在挂起列表中*/
				if( prvTaskIsTaskSuspended( pxTCB ) != pdFALSE )
				{	
					traceTASK_RESUME( pxTCB );
 
					/* As we are in a critical section we can access the ready
					lists even if the scheduler is suspended. */
					/*移除状态列表,不管在什么列表都会被移除,这里将原本挂起的任务添加到就绪列表中*/
					( void ) uxListRemove(  &( pxTCB->xStateListItem ) );
					/*添加到就绪列表中*/
					prvAddTaskToReadyList( pxTCB );
 
					/* We may have just resumed a higher priority task. */
					/*优先级高于当前运行任务优先级*/
					if( pxTCB->uxPriority >= pxCurrentTCB->uxPriority )
					{
						/* This yield may not cause the task just resumed to run,
						but will leave the lists in the correct state for the
						next yield. */
						/*任务切换*/
						taskYIELD_IF_USING_PREEMPTION();
					}
					else
					{
						mtCOVERAGE_TEST_MARKER();
					}
				}
				else
				{
					mtCOVERAGE_TEST_MARKER();
				}
			}
			/*退出临界区*/
			taskEXIT_CRITICAL();
		}
		else
		{
			mtCOVERAGE_TEST_MARKER();
		}
	}

看完了两个函数的源码,我们对两个函数的区别有了一定了解。下面实际测试一下。
可以分为以下步骤:
1 创建一个任务,并挂起它
2 在其他任务中调用xTaskResumeAll
3 查询挂起的任务状态。

1 创建一个任务,并挂起它

    xTaskCreate(motion_alg_repeat_task, "motion_alg_repeat", 4096, 0, 2, &motion_alg_repeat);//
	vTaskSuspend(motion_alg_repeat);

2 、3

  //测试xTaskResumeAll是否能够唤醒被suspend的任务
  // cur == eSuspend;说明xTaskResumeAll不能唤醒被vTaskSuspend的任务
  vTaskSuspendAll();
  xTaskResumeAll();
  extern TaskHandle_t 	motion_alg_repeat;
  eTaskState cur = eTaskGetState(motion_alg_repeat);

调试运行,发现cur == eSuspend;说明当前任务被挂起。
xTaskResumeAll不能唤醒被vTaskSuspend的任务

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值