- 简述
- uc/OS的任务支持挂起和恢复功能
- 挂起相当于暂停,暂停后从就绪列表中移除
- 恢复即重新将任务插入到就绪列表
- 一个任务挂起多少次就要被恢复多少次才能重新运行
- 例程代码
- 自定义任务的状态
/* ************************************************************************************************************************ * 任务状态 ************************************************************************************************************************ */ #define OS_STATE_OS_STOPPED (OS_STATE)(0u) #define OS_STATE_OS_RUNNING (OS_STATE)(1u) /* ------------------- TASK STATES ------------------ */ #define OS_TASK_STATE_BIT_DLY (OS_STATE)(0x01u) /* /-------- SUSPENDED bit */ /* | */ #define OS_TASK_STATE_BIT_PEND (OS_STATE)(0x02u) /* | /----- PEND bit */ /* | | */ #define OS_TASK_STATE_BIT_SUSPENDED (OS_STATE)(0x04u) /* | | /--- Delayed/Timeout bit */ /* | | | */ /* V V V */ #define OS_TASK_STATE_RDY (OS_STATE)( 0u) /* 0 0 0 Ready */ #define OS_TASK_STATE_DLY (OS_STATE)( 1u) /* 0 0 1 Delayed or Timeout */ #define OS_TASK_STATE_PEND (OS_STATE)( 2u) /* 0 1 0 Pend */ #define OS_TASK_STATE_PEND_TIMEOUT (OS_STATE)( 3u) /* 0 1 1 Pend + Timeout */ #define OS_TASK_STATE_SUSPENDED (OS_STATE)( 4u) /* 1 0 0 Suspended */ #define OS_TASK_STATE_DLY_SUSPENDED (OS_STATE)( 5u) /* 1 0 1 Suspended + Delayed or Timeout */ #define OS_TASK_STATE_PEND_SUSPENDED (OS_STATE)( 6u) /* 1 1 0 Suspended + Pend */ #define OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED (OS_STATE)( 7u) /* 1 1 1 Suspended + Pend + Timeout */ #define OS_TASK_STATE_DEL (OS_STATE)(255u)
- 修改任务控制块TCB
/* ************************************************************************************************************************ * OS_TCB 任务控制块 ************************************************************************************************************************ */ struct os_tcb { CPU_STK *StkPtr; CPU_STK_SIZE StkSize; //任务延时周期个数 OS_TICK TaskDelayTicks; //任务优先级 OS_PRIO Prio; //就绪列表的下一个指针 OS_TCB *NextPtr; //就绪列表的上一个指针 OS_TCB *PrevPtr; //时基列表相关字段 OS_TCB *TickNextPtr; //指向链表中的下一个节点 OS_TCB *TickPrevPtr; //指向链表中的上一个节点 OS_TICK_SPOKE *TickSpokePtr; //每个被插入到链表的TCB都包含一个字段TickSpokePtr,用于回指到链表的根部 //TickCtrMatch的值等于时基计数器OSTickCtr的值加上TickRemain的值,当TickCtrMatch的值等于OSTickCtr值的时候,表示等待到期, //TCB会从链表中删除 OS_TICK TickCtrMatch; OS_TICK TickRemain; //设备任务还需要等待多少个时钟周期,每到来一个时钟周期,该值会递减 //时间片相关字段 OS_TICK TimeQuanta; //表示任务需要多少个时间片,单位为系统时钟周期Tick //表示任务还剩下多少个时间片,每到来一个系统时钟周期,TimeQuanCtr 会减1 //当TimeQuantaCtr == 0,表示时间片用完,任务的TCB会从就绪列表链表的头部移动到尾部 //好让下一个任务共享时间片 OS_TICK TimeQuantaCtr; //任务状态 OS_STATE TaskState; #if OS_CFG_TASK_SUSPEND_EN > 0u //任务挂起函数OSTaskSpuend()计数器 //任务每挂起一次,SuspendCtr递增一次,一个任务挂起多少次,就要恢复多少次才能运行 OS_NESTING_CTR SuspendCtr; #endif };
- 挂起函数OSTaskSuspend()
/********************************************************* * 函数名: void OSTaskSuspend(OS_TCB *p_tcb, OS_ERR *p_err); * 描述 :任务挂起函数 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ #if OS_CFG_TASK_SUSPEND_EN > 0u void OSTaskSuspend(OS_TCB *p_tcb, OS_ERR *p_err) { //保存当前中断状态 CPU_SR_ALLOC(); //进入临界段 OS_CRITICAL_ENTER(); //是否挂起自己 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; //根据任务的状态来决定挂起的动作 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; break; } //任务切换 OSSched(); } #endif
- 恢复函数OSTaskResume()
/********************************************************* * 函数名: void OSTaskResume(OS_TCB *p_tcb, OS_ERR *p_err); * 描述 :任务恢复 * 输入 :无 * 输出 :无 * 返回 :无 * 调用 :内部调用 **********************************************************/ #if OS_CFG_TASK_SUSPEND_EN > 0u void OSTaskResume(OS_TCB *p_tcb, OS_ERR *p_err) { CPU_SR_ALLOC(); *p_err = OS_ERR_NONE; /* 根据任务的状态来决定挂起的动作 */ 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; } /* 任务切换 */ OSSched(); } #endif
- 自定义任务的状态
- 总结
- 实验现象
【20】从0到1教你写uC/OS-III————>任务的挂起和恢复
最新推荐文章于 2022-08-27 18:19:06 发布