任务调度器基本概念
在uCOS-III系统 中提供的任务调度器是基于优先级的全抢占式调度:在系统中除了中断处理函数、调度器上锁部分的代码和禁止中断的代码是不可抢占的之外,系统的其他部分都是可以抢占的。系统理论上可以支持无数个优先级(0 ~N),优先级数值越大的任务优先级越低,(OS_CFG_PRIO_MAX - 1u)为最低优先级,分配给空闲任务使用,一般不建议用户来使用这个优先级。一般系统默认的最大可用优先级数目为 32。在一些资源比较紧张的系统中,用户可以根据实际情况选择只支持 8 个或自定义个数优先级的系统配置。
可理解为任务调度器有两种:任务级调度器、中断级调度器以及时间片轮转调度器。任务级调度器就是根据任务的优先级来使用cpu,然后进行任务切换。中断调度器就是指有中断的任务强行打断正在执行的任务转而去执行中断服务函数里面的动作。还有一种任务调度器叫:时间片轮转调度,这个是用于同优先级下的讴歌任务的时候。可以设置每个任务执行的时间片,时间片一到就切换到另一个任务。这个调度器只在同优先级下有多个任务的时候使用。
uCOS的任务状态
1、就绪(OS_TASK_STATE_RDY)
该任务在就绪列表中,就绪的任务已经具备执行的能力,只等待调度器进行调度,新创建的任务会初始化为就绪态。
2、延时(OS_TASK_STATE_DLY)
该任务处于延时调度状态。
3、等待(OS_TASK_STATE_PEND)
任务调用 OSQPend()、OSSemPend()这类等待函数,系统就会设置一个超时时间让该任务处于等待状态,如果超时时间设置为 0,任务的状态,无限期等下去,直到事件发生。如果超时时间为 N(N>0),在N 个时间内任务等待的事件或信号都没发生,就退出等待状态转为就绪状态。
4、运行(Running)
该状态表明任务正在执行,此时它占用处理器,UCOS 调度器选择运行的永远是处于最高优先级的就绪态任务,当任务被运行的一刻,它的任务状态就变成了运行态,其实运行态的任务也是处于就绪列表中的。
5、挂起(OS_TASK_STATE_SUSPENDED)
任务通过调用 OSTaskSuspend()函数
能够挂起自己或其他任务,调用OSTaskResume()是使被挂起的任务回复运行的唯一的方法,对于同一个任务调用几次 OSTaskSuspend()函数就需要调用OSTaskResume()函数使得任务恢复。挂起一任务意味着该任务再被恢复运行以前不能够取得 CPU 的使用权,类似强行暂停一个任务。
6、延时+挂起(OS_TASK_STATE_DLY_SUSPENDED)
任务先产生一个延时,延时没结束的时候被其他任务挂起,挂起的效果叠加,当且仅当延时结束并且挂起被恢复了,该任务才能够再次运行。
7、等待+挂起(OS_TASK_STATE_PEND_SUSPENDED)
任务先等待一个事件或信号的发生(无限期等待),还没等待到就被其他任务挂起,挂起的效果叠加,当且仅当任务等待到事件或信号并且挂起被恢复了,该任务才能够再次运行。
8、超时等待+挂起(OS_TASK_STATE_PEND_TIMEOUT_SUSPENDED)
任务在指定时间内等待事件或信号的产生,但是任务已经被其他任务挂起。
9、删除(OS_TASK_STATE_DEL)
任务被删除后的状态,任务被删除后将不再运行,除非重新创建任务。
常用任务函数讲解
OS_TaskSuspend() | 任务挂起函数 |
---|---|
OSTaskResume() | 任务恢复函数 |
OSTaskDel() | 删除任务函数 |
OSTimeDly() | 任务延时函数 |
OSTimeDlyHMSM() | 与OSTimeDly()任务延时函数 |
OSTaskCreate() | 创建任务函数 |
1、创建任务函数 OSTaskCreate()
OSTaskCreate()在任务创建一节已经讲过了,在这里不在赘述。文章链接任务创建
2、删除任务函数 OSTaskDel()
OSTaskDel()用于删除一个任务。当一个任务删除另外一个任务时,形参为要删除任务创建时返回的任务句柄,如果是删除自身,则形参为 NULL。要想使用该函数必须在os_cfg.h 中把 OS_CFG_TASK_DEL_EN 宏定义配置为 1,删除的任务将从所有就绪,阻塞,挂起和事件列表中删除。
void OSTaskDel (OS_TCB *p_tcb, //目标任务控制块指针,NULL是删除本身
OS_ERR *p_err) //返回错误类型
3、任务挂起函数 OS_TaskSuspend()
挂起指定任务。任务可以通过调用 vTaskSuspend()函数都可以将处于任何状态的任务挂起,被挂起的任务得不到 CPU 的使用权,也不会参与调度,它相对于调度器而言是不可见的,除非它从挂起态中解除。想要使用任务挂起函数的就必须将宏定义OS_CFG_TASK_SUSPEND_EN 使能。
/* *p_tcb 任务控制块指针,如果传递进来的任务控制块指针是 NULL 或者是 0, 则表明要挂起的任务是任务自身*/
void OS_TaskSuspend (OS_TCB *p_tcb,
OS_ERR *p_err) //返回错误类型
4、任务恢复函数 OSTaskResume()
任务恢复就是让挂起的任务重新进入就绪状态,恢复的任务会保留挂起前的状态信息,在恢复的时候根据挂起时的状态继续运行。如果被恢复任务在所有就绪态任务中,处于最高优先级列表的第一位,那么系统将进行任务上下文的切换。 使用任务恢复函数需要使能宏定义 OS_CFG_TASK_SUSPEND_EN
void OSTaskResume (OS_TCB *p_tcb, //任务控制块指针,该指针不允许指向任务自身
OS_ERR *p_err) //返回错误类型
5、任务延时函数
(1)、OSTimeDly()
OSTimeDly() 函数常用于停止当前任务进行的运行,延时一段时间后再运行。任务的延时在实际中运用特别多,因为需要暂停一个任务,让任务放弃 CPU,延时结束后再继续运行该任务,如果任务中没有阻塞的话,比该任务优先级低的任务则无法得到CPU 的使用权,就无法运行。
void OSTimeDly (OS_TICK dly, //延时的时钟节拍数
OS_OPT opt, //选项
OS_ERR *p_err) //返回错误类型
选项 opt 包含:
选项opt | dly 功能属性 |
---|---|
OS_OPT_TIME_DLY | dly 为相对时间,就是从现在起延时多长时 间 ,到 时 钟 节 拍 总 计 数 OSTickCtr = OSTickCtr 当前 + dly 时延时结束 |
OS_OPT_TIME_TIMEOUT | 与 OS_OPT_TIME_DLY 的作用情况一样 |
OS_OPT_TIME_MATCH | dly 为绝对时间,从系统开始运行(调用 OSStart()) 时到节拍总计数 OSTickCtr = dly 时延时结束 |
OS_OPT_TIME_PERIODIC | 周 期 性 延 时 , 跟OS_OPT_TIME_DLY 的作用差不多,如果是长时间延时,该选项更精准一些 |
(2)、OSTimeDlyHMSM()
OSTimeDlyHMSM() 函数与 OSTimeDly() 函数的功能类似,也是用于停止当前任务的运行,延时一段时间后再运行,但是 OSTimeDlyHMSM()函数会更加直观,延时多少个小时、分钟、秒、毫秒。但是,用户若要使用OSTimeDlyHMSM()函数,必须将宏OS_CFG_TIME_DLY_HMSM_EN 设为 1,该宏定义位于 os_cfg.h 中。
void OSTimeDlyHMSM (CPU_INT16U hours, //延时小时数
CPU_INT16U minutes, //分钟数
CPU_INT16U seconds, //秒数
CPU_INT32U milli, //毫秒数
OS_OPT opt, //选项
OS_ERR *p_err) //返回错误类型
选项 opt 包含:
选项opt | dly 功能属性 |
---|---|
OS_OPT_TIME_DLY | dly 为相对时间,就是从现在起延时多长时 间 ,到 时 钟 节 拍 总 计 数 OSTickCtr = OSTickCtr 当前 + dly 时延时结束 |
OS_OPT_TIME_TIMEOUT | 与 OS_OPT_TIME_DLY 的作用情况一样 |
OS_OPT_TIME_MATCH | dly 为绝对时间,从系统开始运行(调用 OSStart()) 时到节拍总计数 OSTickCtr = dly 时延时结束 |
OS_OPT_TIME_PERIODIC | 周 期 性 延 时 , 跟OS_OPT_TIME_DLY 的作用差不多,如果是长时间延时,该选项更精准一些 |
OS_OPT_TIME_HMSM_STRICT | 延时时间取值比较严格:小时数 hours: (0-99) ;分钟数 minutes: (0-59);秒数 seconds: (0-59);毫秒数 milliseconds: (0-999) |
OS_OPT_TIME_HMSM_NON_STRICT | 延时时间取值比较宽松:小时数 hours: (0-999);分钟数 minutes: (0-9999);秒数 seconds: (0-65535) ;毫秒数 milliseconds: (0-4294967295) |