UCOS任务切换详解

1 UCOS知识点

(1) UCOS是可剥夺型的多任务内核。当一个高优先级的任务准备就绪,并且此时发生了任务调度,那么高优先级的任务就会获得CPU的使用权。

(2) 任务调度就是终止当前正在运行的任务转而去执行其他的任务。

(3) 每个任务都有自己的任务控制块:OS_TCB类型(结构体类型)。用来维护任务相关的信息,比如任务栈顶地址、栈的容量、任务当前状态等信息。OS_TCB存储于RAM中。

(4) 每个任务都有自己的:OS_STK类型(数组)。栈可以静态分配,也可以使用malloc()函数从堆中动态分配。由于频繁创建和删除任务会导致内存碎片产生,因此一般栈空间不需要被释放掉。栈作用一是保存任务的局部变量;二是当任务挂起时保存CPU寄存器的值(也就是现场)。

(5) 任务可以访问全局变量,但是全局变量会被多个任务共享,且任务是可剥夺型的,因此这样做不安全,UCOS提供了保护机制(信号量,互斥信号量)。

2 UCOS任务切换

(1) 任务处于休眠态(指任务已存在存储器中,但还不受UCOS管理);

(2) 通过OSTaskCreate()函数,任务处于就绪态;任务就绪表保存已经就绪的的任务。

(3) 此时发生了任务调度。任务调度有两种:1.任务级调度器OSSched();2.中断级调度器OSIntExit()

  OSSched():

  (1)扫描就绪任务表中就绪任务中优先级最高的任务;

  (2)获取到优先级最高任务的控制块;

  (3)把当前任务CPU寄存器里的值保存到栈里面,并把CPU堆栈指针寄存器(TSP)的值存放到OS_TCB中;

  (4)把新任务OS_TCB中保存的TSP值载入到CPU堆栈指针寄存器(TSP);

  (5)从新的堆栈中恢复CPU寄存器的值,此时新的任务就运行了

  OSIntExit():

  (1)中断嵌套计数器OSIntNestingCtr减1

  (2)如果OSIntNestingCtr=0,也就是最后一层嵌套的中断(再返回就到任务级了),并且调度器没有上锁

  (3)获取到优先级最高任务的控制块;

  (4)因为在进入中断服务程序前任务的现场已经保存了,因此这里不用再保存;

  (5)把新任务OS_TCB中保存的TSP值载入到CPU堆栈指针寄存器(TSP);

  (6)从新的堆栈中恢复CPU寄存器的值,此时新的任务就运行了

备注:

OSSched()实际是调用了OS_TASK_SW(),OS_TASK_SW()是调用了OSCtxSw(),而OSCtxSw()实质是进入异常中断服务程序OS_CPU_PendSVHandler

3 任务调度点

3.1 会调用OSSched()的情况:

  (1)给另一个任务发送消息或信号量,OS??? Post()

  (2)任务调用延时函数OSTimeDly()或OSTimeDlyHMSM()

  (3)任务在等待一个时间的发生(消息或者信号量)OS??? Pend()

  (4)任务取消等待OS??? PendAbord()

  (5)创建一个更高优先级的任务OSTaskCreate()

  (6)当前任务被删除OSTaskDel()

  (7)任务自身被挂起OSTaskSuspend()

  (8)用户直接调用OSSched()

3.2 会调用OSIntExit()的情况:

  当所有的中断嵌套结束时,在返回任务前要调用OSIntExit()函数

原文地址:https://www.cnblogs.com/Mike2019/p/12548536.html