uCOSIII任务管理

  • 任务简介:

    • 任务即由系统管理的程序实体,由三部分组成:

      • 任务堆栈:本质是一个数组,不同的任务在创建前可以自己定义相关数组的大小;
      • 任务控制块:本质上是一个结构体,用于保存任务当前的各种状态信息,其成员只可用uCOSIII相关函数访问,用户不可直接访问;
      • 任务函数:即表达任务功能的地方,通过系统调用来切换,分为运行至完成型(完成后自我删除)和无限循环型(while(1));
    • 任务还有一些其他属性,如优先级等等,这些在以后使用中会注意到;
  • 任务状态:

    • 用户角度:

      • 休眠态:任务已经在CPU的flash中了,但未注册而不受UCOSIII管理;
      • 就绪态:系统为任务分配了任务控制块,并且满足运行的条件,任务已经在就绪队列中;
      • 运行态:任务获得CPU的使用权,正在运行;
      • 等待态:任务需要等待等待某个事件或外设,进入等待队列中,此时系统就会把CPU使用权转交给别的任务;
      • 中断服务态:当发送中断,当前正在运行的任务会被挂起,CPU转而去执行中断服务函数,此时任务即中断服务态;

  • 操作系统角度:

    • 有八种状态,且每种状态在操作系统中都有相关宏定义表示,而OS_TCB中也记录了任务当前属于哪种状态:
    • 从图中可以看出进入每种状态的条件(调用什么函数);

  • 任务基本属性:

    • 任务栈:

      • 根据实际任务为相应任务分配合理大小的堆栈(--------具体方式应查一下);
      • uCOSIII中建议用静态分配栈,动态会生成很多碎片;
      • 注意堆栈溢出情况,采取堆栈溢出检测:
        • MMU或MPU检测:配置硬件;
        • 具有堆栈溢出检测功能CPU:CPU堆栈指针SP高于/低于某个预定值产生异常;
          • 这个预定值(stk_limit,堆栈限位)在创建任务时会作为OSTaskCreate()参数传给OS_TCB;
          • 此种堆栈限位值可以很接近堆栈底,任务运行时常存在一个寄存器(堆栈溢出检测寄存器)中;
          • 上下文切换时先让此寄存器指向NULL;再改变SP的值;之后再改变此寄存器值为新任务stk_limit;
        • 基于软件堆栈溢出检测:任务切换函数中添加相关代码,模拟硬件实现方式;
          • 没有硬件可靠,且stk_limit值离堆栈底应远一点;
        • 系统中的OSTaskStkChk()函数可以用于计算任务堆栈使用量;
    • 优先级:
      • uCOSIII优先级个数可为无穷大,默认的是64,由os_cfg.h中的OS_CFG_PRIO_MAX决定,值越小代表优先级越高;
      • 最高优先级任务(0优先级)为中断服务管理任务(OS_IntQTask()),最低优先级为系统的空闲任务;
      • 用户可以为用户任务设置优先级,但设置原则建议为:单调执行率调度法(执行频率高的任务优先级高):
      • 高优先级可以抢占低优先级,同优先级间采用轮转时间片调度;
  • 任务相关操作:

    • 任务创建:主要调用OSTaskCreate()函数,由于其参数表较为复杂,此处列出:
  • 系统任务:

    • 空闲任务(OS_IdleTask(),os_core.c):

      • 是UCOSIII创建的第一个任务,亦是必须创建的任务,此任务在OSInit()内由系统创建;
      • 任务优先级为OS_CFG_PRIO_MAX-1,其他任务不允许使用此优先级;
      • 其他任务未就绪时,系统运行空闲任务;
      • 空闲任务内有两个计数器:
        • OSIdleTaskCtr:表示空闲任务活跃度;
        • OSStatTaskCtr:由统计任务控制,统计程序运行CPU利用情况;
      • 该任务有个OSIdleTaskHook()的函数,允许用户做一些额外操作,但这些操作不可使空闲任务进入等待态;
    • 时钟节拍任务/时基任务(OS_TickTask(),os_tick.c):
      • 用于处理时钟节拍,是必须创建的任务;
      • 任务优先级在os_cfg_app.h文件中OS_CFG_TICK_TASK_PRIO设置,其优先级应纸币用户系统中最重要的任务优先级低一点(通常设置为1或2);
      • 该任务等待时钟节拍(定时器)发送的信号,进入就绪态,启动任务;
      • 在此任务内,系统会遍历所有等待延时或指定时间内等待某内核对象的任务(即时钟节拍列表---时钟节拍轮)---关于此表在中文书79页,很有意思,此处不详述;
      • 更新时钟节拍列表大部分在临界区代码完成的;
    • 统计任务(OS_StatTask(),os_stat.c):
      • 可选任务,通过os_cfg.h中的OS_CFG_STAT_TASK_EN控制;
      • 任务优先级为os_cfg_app.h文件中OS_CFG_STST_TASK_PRIO设置;
      • 用于统计总CPU使用率,各任务CPU使用率,各任务堆栈使用量,CPU利用率从0~10000表示从0.00%~100.00%,具体计算方法不细述;
      • 使用此任务,main函数在调用OSStart()前只可创建一个用户任务,此任务中应先调用OSStatTaskCPUUsageInit()函数,然后才可创建其他任务;
      • 系统会把每个任务运行统计结果存入每个任务OS_TCB中;
    • 定时任务(OS_TmrTask(),os_tmr.c):
      • 是可选任务,由os_cfg.h中的OS_CFG_TMR_EN控制是否使用此任务;
      • 任务优先级为os_cfg_app.h文件中OS_CFG_TMR_TASK_PRIO设置,常设为中等优先级;
      • 和时钟节拍任务使用相同的中断源,但会对时钟节拍进行分频,多少个节拍后产生一个相关信号量;
    • 中断服务管理任务(OS_IntQTask()、os_int.c):
      • 是可选任务,由os_cfg.h中的OS_CFG_ISR_POST_DEFERRED_EN控制;
      • 当通过调度器解/上锁管理临界区时,ISR调用Post函数不会直接操纵等待表等,而是先放入一缓冲队列;
      • 中断结束之后进行任务切换,此时该任务会把相关消息、信号传递给对应任务;
      • 这种方式(延迟发布)降低了关中断时间;
  • 任务就绪表:

    • 就绪优先级位映射表(OSPrioTbl[]):

      • 某一优先级有对应任务就绪,该表对应位会被置1;
      • 此表中优先级从左到右从上到下逐渐降低,这样在某些CPU中查找最高优先级速度会较快;
      • 该表相关配置和操作函数在os_prio.h/.c文件内;

  • 就绪任务列表(OSRdyList[]):

    • 是一个包含OS_CFG_PRIO_MAX项的结构体数组,每一项对应存储这个优先级任务的队列;
    • 操作就绪任务列表的函数在os_core.c文件内,包括创建新任务时会入就绪队列;
    • 初始化时该数组中相关元素相关元素都会被初始化;
  • 任务调度:

    • 调度方式:

      • 是抢占式的,分为直接发布和延迟发布两种模式,最终结果一样:

        • 直接发布:

          • 中断服务函数中,直接向某个任务发布信号量或消息等;
          • 中断结束后直接进入更高优先级的任务,而不先返回原来任务;
        • 延迟发布:
          • 中断中将要发布的信息先放入相关缓冲队列中;
          • 退出中断后会进入最高优先级的中断服务管理任务(OS_IntQTask());
          • 该函数内根据消息队列发布相关操作,这有利于减少关中断事件;
    • 调度点:
      • 任务向另一任务发送信号量或消息:

        • 一个任务调用OS_XXX_Post()函数时,该函数结束后即发生任务调度;
        • 当OS_OPT_POST_NO_SCHED使能时则不发生任务调度;
      • 当前任务调用STimeDly()或OSTimeDlyHMSM():
        • 该任务会被放入等待延时列表(时钟节拍轮)中,启动调度器;
      • 任务执行到需要等待一个事件发生时:
        • 通常是调用了OS_XXX_Pend()函数,当前任务被放入等待事件列表中;
        • 若指定了等待的时间,还会入等待超时队列中;
      • 任务取消等待一个事件:
        • 任务调用OS_XXX_PendAbort()取消对一事件的等待,此时会从相关等待队列删除,系统重新调度;
      • 创建任务,删除当前任务:此时亦会启动调度器;
      • 删除内核对象:
        • 系统通知等待该内核任务,这些任务转入就绪态。重新调度;
      • 有任务优先级被改变时;
      • 任务自我挂起或者解挂:
        • 分别调用OSTaskSuspend()和OSTaskResume()函数;
      • 退出所有嵌套中断时:
        • 此时系统会检查这些中断是否使某些优先级任务进入就绪态;
        • 这时候任务调度通过OSIntExit()函数实现;
      • 任务放弃当前时间片(礼让);
        • 即调用OSSchedRoundRobinYield()函数;
      • 用户手动调度:
        • 即显式的调用OSSched()函数,这主要用于使能OS_OPT_POST_NO_SCHED时,调用OS_XXX_Post()函数不会产生调度时;
        • 这样可以一次发布多个信息后进行一次任务调度,而非每次发布后执行;
    • 轮转时间片:
      • 多个同优先级任务时,系统使用此方式管理,用户可使能或禁止;
      • 允许一个任务主动放弃CPU,即“礼让”,
      • 用户可在运行时改变默认时间片长度(QSTaskTimeQuantaSet()函数);
      • 可以为每个任务制定不同长度的时间片;
    • 几个调度函数:
      • OSSched()函数:

        • 该函数是任务级调度器,不可在ISR_Func内被调用;
        • 进入此函数时中断应关闭的,退出时中断应重新开始;
        • 扫描就绪任务表,一旦要调度,则调用任务级上下文切换函数;
      • OSIntExit()函数:
        • 此函数通常会在ISR_Func结束时被调用来调度任务;
        • 当任务调度器未上锁,且是最后一层嵌套的中断中,该函数执行调度;
        • 查询任务就绪表,调用中断级上下文切换函数;
      • OS_SshedRoundRobin()函数:
        • 用于进行同优先级下的时间片轮转调度;
        • 直接发布时由OSTimeTick()函数调用,延迟发布时由OS_IntQTask()函数调用;
  • 上下文切换:

    • 概述:

      • 主要作用是将当前任务现场保存到任务堆栈中;
      • 不同CPU寄存器数不同,故这部分代码移植时应根据实际CPU修改,具体在os_cpu.h、os_cpu_c.c、os_cpu_a.asm文件中;
      • 寄存器中的PC和状态寄存器(SR)先入栈,这是硬件自动完成的,其他由软件入栈,任务堆栈指针不入栈,而直接存入OS_TCB中;
      • 具体的两个切换函数都是在os_cpu_a.asm中用汇编写的;
    • 任务级OSCtxSw()函数:
      • 先将当前任务相关寄存器存入任务堆栈,入栈顺序一般和中断时一样;
      • 将当前堆栈指针值存入当前任务OS_TCB中;
      • 将新任务OS_TCB中的任务堆栈指针值载入堆栈指针寄存器中;
      • 从新任务堆栈中依次弹栈,恢复现场;
    • 中断级OSIntCtxSw()函数:
      • 与任务级不同,中断级在切换前默认发生中断时CPU寄存器已被存入相关堆栈内;
      • 所以其只完成任务级的后两步;
  • 任务挂起表:

    • 功能概述:

      • 当前任务等待某一内核对象或者消息时,用来记录的地方;
      • 其本质是一个个链表,每个内核对象或者消息对应一个链表,表中高优先级任务放在前面;
      • 链表的表头中记录等待对象的结构体被称为OS_PEND_OBJ,有以下元素:
        • Type:表明该表中元素等待的内核对象的类型,四个字节的ANSII码表示;
        • NamePtr:指向该种内核对象的一个确切实体的名字;
      • 任务挂起表内元素不是OS_TCB,而是OS_PEND_DATA结构体,位于任务自己的堆栈内;
      • 该结构体内指针可以指向自己的OS_TCB,而OS_TCB亦可指向自己的OS_PEND_DATA;

时间: 2024-10-08 10:29:43

uCOSIII任务管理的相关文章

UCOS-III API函数

附录:UCOS-III API函数 任务管理 就绪列表 挂起队列 时间管理 信号量 消息队列 内存管理

ucos-III前言

前言 自从 2009年 uC/OS-III实时操作系统面世以来,uC/OS-III的性能和稳定性已经日趋完善.uC/OS-III对前面版本取精弃粕,推陈出新,功能和性能比起 uC/OS-II已经上了很大一步台阶.uC/OS-III 正在逐渐取代 uC/OS-II,学习 uC/OS-III 已经成为许多嵌入式工程师迫在眉睫的一件事. 下面是 uC/OS 系统各个版本的对比. uC/OS-III 的源码已经跟前面版本的源码相差很大,很多方面都做了更加规范的修改,很多处理问题的机制也有很大的突破. 因

ucos-III基础教程汇总

目录: 1.ucos-III前言

Linux进程控制和计划任务管理

程序是保存在外部存储介质(如硬盘)中的可执行机器代码和数据的静态集合,而进程是在CPU及内存中处于动态执行状态的计算机程序.在Linux中,每个程序启动后可以创建一个或多个进程. ps命令   查看静态的进程统计信息 ps         只显示当前用户会话中打开的进程 ps  aux    以简单列表的形式显示出进程信息 ps  -elf   以长格式显示系统中的进程信息,包括更丰富的内容 top命令   查看进程动态信息 在当前终端已交互式的界面显示进程排名,及时跟踪CPU.内存等系统资源占

【Xilinx-ZYNQ ucos-iii的移植与开发】-00-开始

前一段时间,调试了一块ZYNQ的板子,上面用到了ucos-iii操作系统,最终在该板子上实现了操作系统的运行,并实现了一些外设模块的功能,主要包括PWM,I2C,GPIO,两级中断. 等有空了总结一下. 包括操作系统的移植(不算是移植,因为官方已经做好了-_-,就介绍一下怎么安装到Xilinx SDK当中去,和一些必要的参数配置), 基于ZYNQ ucos-iii的平台编写了一些AXI4外设模块的驱动程序,到时候也介绍一下,最重要的是AXI4 Interrupt Controller这个模块的功

Eclipse插件Mylyn管理上下文任务管理

原文地址:http://www.ibm.com/developerworks/cn/java/j-mylyn1/ Mylyn 2.0,第 1 部分: 集成的任务管理 使用集成的 Eclipse 问题跟踪功能简化工作 现在,在 2.0 版中,Mylyn(以前称为 Mylar)通过将任务无缝集成到 Eclipse 中并在工作时自动管理任务上下文,提高了效率.Mylyn 项目主管 Mik Kersten 更新了他撰写的分两部分的 Mylyn 使用指南,以便包括根据 Mylyn 1.0 的大量用户反馈而

stm32f407 官方ucos-iii 不支持FPU 导致haltfault错误的处理办法

由于官方提供的μCOS-III移植工程中对于浮点寄存器的入栈和出栈处理是错误的,所以网上就流传了 各种修正版本.但是这些修正的代码只能在 MDK4.7 以下版本中可以正常的运行,MDK4.7 及其以上的版 本无法正常运行.下面针对高版本的MDK进行修正处理 处理方法如下: 为了解决 FPU 的问题,有两个函数需要修改:一个是 CPU_STK  *OSTaskStkInit(),另一个是 PendSV 中断. 最后需要在工程选项中开启FPU的支持 修改函数CPU_STK  *OSTaskStkIn

μCos-ii学习笔记2_任务管理

二.任务管理 任务管理是ucos-ii操作系统的核心内容.这一章大致就以下流程来介绍和总结任务管理的相关知识. 要实现复杂任务管理,必然要定义众多数据来描述任务状态,为了精简,建立了许多不同的数据结构,所以第一步就是了解这些数据结构和构成.为了避免枯燥,我们同时要认识到每一种结构具体起到什么作用,感受其中的精妙之处,这样理解起来就更容易了. 建立完必要的数据结构,程序在OS_TCBInit()中对TCB进行初始化,在OSInit()中对操作系统的其他重要数据结构进行初始化. 操作系统在启动和运行

uCOS-iii 中定义的一些常量

uCOS-iii 中定义的一些常量 uCOS-iii 中有许多宏定义的量,这些量不需要全部记住是什么意思,因为在阅读代码的时候可以选中变量或宏定义然后右键查看定义,就可以知道它代表的什么意思.但是如果知道什么样的变量是大概是什么含义,这样会在阅读代码的时候很流畅.这是我第一天阅读代码的时候遇到的一些宏定义: 第一种是yes和no类型的:常用的TRUE,YES,ENABLE,ACTIVE,VALID,ON,SET,OK都是1的意思,反之则是0: #define DEF_FALSE 0u #defi