ucos2 任务

uC/OS-II 的任务:

从任务的存储结构来看,uC/OS-II 的任务由三个部分构成:

  1. 任务程序代码,任务的执行部分
  2. 任务堆栈,用来保存任务工作环境
  3. 任务控制块,用来保存任务属性

每一个任务都作为一个节点,组成一个双向的任务链表。

用户任务:

从程序代码上看,用户任务似乎就是一个C语言函数,但是这个函数不是一般的C语言函数,它是一个任务(线程)。因此,它不是被主函数或其他函数调用的,主函数mian()只是负责创建和启动它们,而由操作系统负责来调度它们。

系统任务:

uC/OS-II 预定义了两个为应用程序服务的系统任务:

  1. 空闲任务(OSTaskIdle
  2. 统计任务(OSTaskStat

其中空闲任务是每个应用程序必须使用的。OSTaskIdle由系统自动创建,在系统初始化时,

  • OSInit --> OS_InitTaskIdle --> OSTaskIdle

如果用户应用程序要使用统计任务,则必须把定义在OS_CFG.H中的OS_TASK_STAT_EN设置为1,并且必须在创建统计任务之前调用函数OSStatInit( ) 对统计任务进行初始化。

任务优先级:

优先级数目通过OS_CFG.H中的OS_LOWEST_PRIO配置。

固定地,系统总是把最低优先级别OS_LOWEST_PRIO自动赋给空闲任务。如果应用程序中还使用了统计任务,则系统会把OS_LOWEST_PRIO - 1 自动赋给统计任务。

由于每个任务都具有唯一的优先级别,因此uC/OS-II 通常也用任务的优先级别来作为这个任务的标识。

任务堆栈:

堆栈的增长方向随系统所使用的处理器不同而不同,为提高应用程序的可移植性,可利用OS_CFG.H 中的 OS_STK_GROWTH 作为选择开关。

把CPU启动任务时所需的初始数据事先存放在任务的堆栈中,当任务获得CPU使用权时,就可以把堆栈中的初始数据复制到CPU的各寄存器中,使任务顺利地启动并运行。

任务堆栈的初始化工作是由系统通过在OSTaskCreate ( )中调用OSTaskStkInit ( )来完成的。

任务控制块:

任务控制块用来记录一些与任务有关的属性,负责把任务代码和任务堆栈进行关联,而使任务控制块/任务代码/任务堆栈成为一个整体,并且系统要通过这个任务控制块来感知和管理一个任务。

uC/OS-II用两条双向链表来管理任务控制块:

  1. 空闲链表(OSTCBFreeList):在OSInit ( ) --> OS_InitTCBList ( ) 时建立
  2. 任务块链表(OSTCBList) :在OSTaskCreate ( ) --> OS_TCBInit ( ) 时建立

两个数组,一个指针:

  1. OS_TCB OSTCBTbl[ ] : 每个元素就是一个任务控制块,用于构建OSTCBFreeList
  2. OS_TCB *OSTCBPrioTbl[ ] : 以优先级为顺序存放指向任务控制块的指针,加快访问速度
  3. OS_TCB *OSTCBCur : 指向当前运行任务的任务控制块

uC/OS-II允许用函数OSTaskDel ( )删除一个任务,实质上就是把该任务的任务控制块从OSTCBList中删掉,并把它归还给OSTCBFreeList

任务就绪表:

OSRdyTbl[0] ~ OSRdyTbl[7] 中的每一位对应优先级0~63

OSRdyGrp 中的每一位对应OSRdyTbl[0] ~ OSRdyTbl[7]中的一组

64个优先级需要用6位二进制数标识,高三位(D5D4D3)指明OSRdyTbl[0~7] 中的某一组y,而低三位(D2D1D0)指明OSRdyTbl[y] 中的某一位x

两个用于加快运算速度的数组:

  1. OSMapTbl[ ] : 用于加快获取某个特定位,OS_TCB中的OSTCBBitX/OSTCBBitY也是出于此目的
  2. OSUnMapTbl[ ] : 用于加快获取xyOS_TCB中的OSTCBX/OSTCBY也是出于此目的

获取最高优先级的就绪任务:

  1. y = OSUnMapTbl[ OSRdyGrp];
  2. x = OSUnMapTbl[ OSRdyTbl[ y ] ];
  3. prio = (y << 3) + x;
  • 这里的OSUnMapTbl[ ] 不太好理解,我看了很久才想明白的,其实它是这样构成的:

0000000000111111,每一种情况对应OSUnMapTbl[ ] 中的一个元素,自己算一遍就知道了。

任务的调度:

任务调度器的主要工作有两项:

  • 在任务就绪表中查找具有最高优先级的就绪任务
  • 实现任务的切换

uC/OS-II有两种调度器:

  1. 任务级调度器(OSSched): uC/OS-II 允许应用程序调用OSSchedLock( )(OSLockNesting + 1) 和 OSSchedUnlock ( ) (OSLockNesting - 1)给调度器上锁和解锁。在确认未被上锁(OSLockNesting == 0)并且不是中断服务程序调用调度器(OSIntNesting == 0)的情况下,OSSched获取最高级别的任务控制块,再根据OSTCBHIghRdyOSTCBCur在宏OS_TASK_SW ( )中实施任务切换。
  2. 中断级调度器(OSIntExt

任务切换宏OS_TASK_SW ( ) :

任务切换的工作是靠OSCtxSw ( ) 完成的。

任务的切换其实就是断点数据的切换,断点数据的切换也就是CPU堆栈指针的切换。堆栈指针SP是保存在控制块成员(OS_TCB)的OSTCBStkPtr中的。

OSCtxSw ( ) 要依次完成如下7项任务:

  1. 被中止任务的断点指针PC保存到任务堆栈
  2. CPU通用寄存器的内容保存到任务堆栈
  3. 被中止任务的任务堆栈指针SP保存到该任务的任务控制块OSTCBStkPtr
  4. 获得待运行任务任务控制块
  5. 使CPU通过任务控制块获得待运行任务的任务堆栈指针SP
  6. 把待运行任务堆栈中通用寄存器的内容恢复到CPU的通用寄存器
  7. 使CPU获得待运行任务的断点指针PC

由于任务切换时需要对CPU的寄存器进行操作,因此在一般情况下,中断服务程序OSCtxSw ( ) 都要用汇编语言来编写。具体的实现与处理器有关,需要根据情况编写。

任务的创建:

uC/OS-II有两个用来创建任务的函数:OSTaskCreate ( ) OSTaskCreateExt ( ) OSTaskCreateExt ( )OSTaskCreate ( ) 的扩展,并提供了一些附加功能。

OSTaskCreate ( ) 首先进行优先级判断,随后调用OSTaskStkInit ( )OSTCBInit ( ) 进行初始化。初始化成功后,把任务计数器加1,如果 uC/OS-II 处于运行状态(OSRunning == 1),则调用OSSched ( ) 进行任务调度。

  • uC/OS-II 有一个规定:在调用启动任务函数OSStart ( ) 之前,必须已经创建了至少一个任务。 uC/OS-II 不允许在中断服务程序中创建任务。

任务的挂起和恢复:

  • 挂起任务(OSTaskSuspend):删除任务就绪表中被挂起任务的就绪标志,并在任务控制块成员OSTCBStat中做好挂起记录
  • 恢复任务(OSTaskResume) :清除任务控制块成员OSTCBStat中的挂起记录并使任务就绪。

任务优先级的修改:OSTaskChangePrio ( )

任务的删除:

所谓删除一个任务,就是把该任务置于睡眠状态。具体做法是,把被删除任务的OSTCBOSTCBList中删除,并归还给OSTCBFreeList,然后在OSRdyTbl中把相应的就绪任务位置0

在任务中,可以掉用OSTaskDel ( ) 来删除任务自身或者除了空闲任务之外的其他任务。

如果要删除一个占用资源的任务时,提出删除任务请求的任务通过调用OSTaskDelReq ( ) 提出请求,把被删除任务OSTCB中的OSTCBDelReq置为OS_TASK_DEL_REQ被删除任务可以在适当的时间检测自己的OSTCB中的OSTCBDelReq,如果被置为OS_TASK_DEL_REQ,则释放资源并且删除自身提出请求的任务可以通过OSTaskDelReq ( ) 返回值是否为OS_TASK_NOT_EXIST来确定被删除任务是否已经被删除。

查询任务的信息:OSTaskQuery ( )

uC/OS-II 的初始化:

函数OSInit ( ) 将对 uC/OS-II 的所有全局变量数据结构进行初始化:

任务:

  • OSTaskIdle : 赋予最低优先级并永远处于就绪状态
  • OSStat : 如果OS_TASK_STAT_EN = 1,则以优先级OS_LOWEST_PRIO - 1创建统计任务。

数据结构:

  • 包括空任务控制块链表在内的5个空数据缓冲区
  • OSTCBPrioTbl[ OS_LOWEST_PRIO + 1]

全局变量:

变量变量的说明
OSPrioCur0INT8U,正在运行的任务的优先级
OSPrioHighRdy0INT8U,具有最高优先级别的就绪任务的优先级
OSTCBCurNULLOS_TCB *,指向正在运行任务的OSTCB的指针
OSTCBHighRdyNULLOS_TCB *,指向最高优先级就绪任务OSTCB的指针
OSTime0LINT32U,系统当前时间(节拍数)
OSIntNesting0INT8U,中断嵌套的层数(0~255)
OSLockNesting0INT8U,调用了OSSchedLock的嵌套层数
OSCtxSwCtr0INT32U,上下文切换的次数
OSTaskCtr2INT8U,已经建立了的任务数
OSRunningFALSEBOOLEAN,uC/OS-II核是否正在运行的标志
OSCPUUsage0INT8S,CPU的利用率(%)
OSIdleCtrMax0LINT32U,每秒空闲任务计数的最大值
OSIdleCtrRun0LINT32U,空闲任务的计数器每秒的计数值
OSIdleCtr0LINT32U,空闲任务计数器
OSStatRdyFALSEBOOLEAN,统计任务是否就绪的标志
OSIntExity0INT8U,用于OSInitExt()

uC/OS-II 的启动:

uC/OS-II 进行任务的管理是从调用启动函数OSStart ( ) 开始的,前提是在调用该函数之前至少创建了一个任务。

OSStartHighRdy ( ) 在多任务系统启动函数OSStart ( ) 中调用。实现的功能是,设置系统运行标志OSRunning = TRUE,将就绪表中最高优先级任务的栈指针加载到SP中,并强制中断返回。这样就绪的最高优先级任务就如同从中断里返回到运行态一样,使得整个系统得以运转

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值