uCOS-Ⅲ学习笔记: 任务挂起&恢复

一、简介

任务的挂起:即将任务从就绪列表中暂时移除,不再参与运行,恢复即把任务从新插入到就绪列表,继续运行

二、设置挂起恢复有关函数以及变量

挂起恢复有关变量(TCB中)

  • 任务TCB添加有关变量储存任务状态以及记录任务挂起的次数(挂起多少次就要恢复多少次才能继续插入就绪列表)
  • OS_STATE TaskState(记入任务状态)
  • OS_STATE u8类型重定义类型
  • SuspendCtr(挂起次数计数器)

编写调度函数

任务挂起函数

	OSTaskSuspend
	(
	    OS_TCB *tcb 
	    OS_ERR *err
	)//(任务挂起函数格式,以及其传递进去函数形式)
  1. 创建临界段调用参数
CPU_SR_ALLOC();
//展开(头文件中的定义)
/* 定义一个局部变量,用于保存CPU中断状态 */
#define  CPU_SR_ALLOC()             CPU_SR  cpu_sr = (CPU_SR)0
#else
#define  CPU_SR_ALLOC()
#endif
  1. 是否开启屏蔽
  • 根据宏定义判断一些任务的可执行性
  • ISR程序中不可调用挂起,否则报错
  • 中断处理函数不能挂起,否则报错
  • 空闲任务不能挂起,否则报错
#if 0 /* 屏蔽开始 */
#ifdef OS_SAFETY_CRITICAL
/* 安全检查,OS_SAFETY_CRITICAL_EXCEPTION()函数需要用户自行编写 */
    if (p_err == (OS_ERR *)0) {
    
    
        OS_SAFETY_CRITICAL_EXCEPTION();
        return;
    }
#endif

#if OS_CFG_CALLED_FROM_ISR_CHK_EN > 0u
/* 不能在ISR程序中调用该函数 */
    if (OSIntNestingCtr > (OS_NESTING_CTR)0) {
    
                 
       *p_err = OS_ERR_TASK_SUSPEND_ISR;
        return;
    }
#endif

/* 不能挂起空闲任务 */
    if (p_tcb == &OSIdleTaskTCB) {
    
                             
        *p_err = OS_ERR_TASK_SUSPEND_IDLE;
        return;
    }

#if OS_CFG_ISR_POST_DEFERRED_EN > 0u
/* 不能挂起中断处理任务 */
    if (p_tcb == &OSIntQTaskTCB) {
    
                              
        *p_err = OS_ERR_TASK_SUSPEND_INT_HANDLER;
        return;
    }
#endif
  1. 进入临界段
CPU_CRITICAL_ENTER();
  1. 判断传入TCB==0?
  • 若等于0,则令TCB=OSTCBCurPtr
  • 不为0,判断若为OSTCBCurPtr ,则根据一个调度器宏定义变量判断,若调度器锁住,退出临界段,并报错
	/* 是否挂起自己 */
    if (p_tcb == (OS_TCB *)0) 
	{
    
                                 
        p_tcb = OSTCBCurPtr;
    }
    if (p_tcb == OSTCBCurPtr) 
	{
    
    
        /* 如果调度器锁住则不能挂起自己 */
		if (OSSchedLockNestingCtr > (OS_NESTING_CTR)0) 
		{
    
    
            CPU_CRITICAL_EXIT();
            *p_err = OS_ERR_SCHED_LOCKED;
            return;
        }
  }
    *p_err = OS_ERR_NONE;
  1. 判断传入TCB的状态 switch判断
  • 非挂起状态进行挂起操作(状态切换为当前状态+挂起),挂起数目1,退出临界段和判断
  • 已经挂起的任务执行default,挂起数目+1,退出临界段和判断
/* 根据任务的状态来决定挂起的动作 */
    switch (p_tcb->TaskState) 
	{
    
    
        case OS_TASK_STATE_RDY:
             OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
             p_tcb->TaskState  =  OS_TASK_STATE_SUSPENDED;
             p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
             OS_RdyListRemove(p_tcb);
             OS_CRITICAL_EXIT_NO_SCHED();
             break;

        case OS_TASK_STATE_DLY:
             p_tcb->TaskState  = OS_TASK_STATE_DLY_SUSPENDED;
             p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
             CPU_CRITICAL_EXIT();
             break;

        case OS_TASK_STATE_PEND:
             p_tcb->TaskState  = OS_TASK_STATE_PEND_SUSPENDED;
             p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
             CPU_CRITICAL_EXIT();
             break;

        case OS_TASK_STATE_PEND_TIMEOUT:
             p_tcb->TaskState  = OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED;
             p_tcb->SuspendCtr = (OS_NESTING_CTR)1;
             CPU_CRITICAL_EXIT();
             break;

        case OS_TASK_STATE_SUSPENDED:
        case OS_TASK_STATE_DLY_SUSPENDED:
        case OS_TASK_STATE_PEND_SUSPENDED:
        case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
             p_tcb->SuspendCtr++;
             CPU_CRITICAL_EXIT();
             break;

        default:
             CPU_CRITICAL_EXIT();
             *p_err = OS_ERR_STATE_INVALID;
             return;
    }
  1. 任务切换(任务状态改变后都要进行任务切换)
    /* 任务切换 */
	OSSched();

任务挂起恢复函数

	OSTaskResume
	{
    
    
	   OS_TCB *p_tcb
	   OS_TCB *p_err
	}
	//(任务恢复函数,用于恢复被挂起的任务,无法恢复自己,函数形式如上)
  1. 创建临界段调用参数
    (同挂起函数)
  2. 是否开启屏蔽
    - 根据宏定义判断一些任务的可执行性
    - ISR程序中不可调用挂起,否则报错
    - 不能挂起当前任务自己
    (同上,因为没有空闲任务挂起,所以少一个)
  3. 判断任务状态,执行对应的恢复动作(switch判断)任务挂起数目递减;同时判断若挂起数量等于0,则将任务恢复到挂起之前状态(就绪、延迟、等待、等待+超时),再退出临界段
	/* 根据任务的状态来决定恢复的动作 */
    switch (p_tcb->TaskState) 
	{
    
    
        case OS_TASK_STATE_RDY:
        case OS_TASK_STATE_DLY:
        case OS_TASK_STATE_PEND:
        case OS_TASK_STATE_PEND_TIMEOUT:
             CPU_CRITICAL_EXIT();
             *p_err = OS_ERR_TASK_NOT_SUSPENDED;
             break;

        case OS_TASK_STATE_SUSPENDED:
             OS_CRITICAL_ENTER_CPU_CRITICAL_EXIT();
             p_tcb->SuspendCtr--;
             if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
    
    
                 p_tcb->TaskState = OS_TASK_STATE_RDY;
                 OS_TaskRdy(p_tcb);
             }
             OS_CRITICAL_EXIT_NO_SCHED();
             break;

        case OS_TASK_STATE_DLY_SUSPENDED:
             p_tcb->SuspendCtr--;
             if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
    
    
                 p_tcb->TaskState = OS_TASK_STATE_DLY;
             }
             CPU_CRITICAL_EXIT();
             break;

        case OS_TASK_STATE_PEND_SUSPENDED:
             p_tcb->SuspendCtr--;
             if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
    
    
                 p_tcb->TaskState = OS_TASK_STATE_PEND;
             }
             CPU_CRITICAL_EXIT();
             break;

        case OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED:
             p_tcb->SuspendCtr--;
             if (p_tcb->SuspendCtr == (OS_NESTING_CTR)0) {
    
    
                 p_tcb->TaskState = OS_TASK_STATE_PEND_TIMEOUT;
             }
             CPU_CRITICAL_EXIT();
             break;

        default:
             CPU_CRITICAL_EXIT();
             *p_err = OS_ERR_STATE_INVALID;
             return;
    }
  1. 任务切换

三、调用流程

  1. 初始化
    - 任务TCB、创建变量;
*/
struct os_tcb
{
    
    
//任务状态标志
OS_STATE             TaskState;
#if OS_CFG_TASK_SUSPEND_EN > 0u
/* 任务挂起函数OSTaskSuspend()计数器 */
    OS_NESTING_CTR       SuspendCtr;
#endif

};
  1. 调用
    - 在任务中直接根据需求使用
//挂起
	OSTaskSuspend(&Task1TCB,&err);	
//恢复
	OSTaskResume(&Task1TCB,&err);

猜你喜欢

转载自blog.csdn.net/qq_45396672/article/details/109960631