本篇介绍的是OSStart()函数和OSStatInit()函数和OSTimeTick()函数。

OSStart()多任务开始函数:

/*$PAGE*/
/*
*********************************************************************************************************
*                                          START MULTITASKING
*                                           启动多个任务
* Description: This function is used to start the multitasking process which lets uC/OS-II manages the
*              task that you have created.  Before you can call OSStart(), you MUST have called OSInit()
*              and you MUST have created at least one task.
*               该功能用来开始多任务进程,使UC/OS-II管理你所创建的任务。在调用OSStart()之前必须先调用OSInit()并且必须创建至少一个任务
* Arguments  : none
*
* Returns    : none
*
* Note       : OSStartHighRdy() MUST:
*                 a) Call OSTaskSwHook() then,调用OSStartHighRdy()之后就调用OSTaskSwHook()函数
*                 b) Set OSRunning to OS_TRUE.将OSRunning设置为真,指出多任务已经开始
*                 c) Load the context of the task pointed to by OSTCBHighRdy.加载高优先级就绪任务启动函数中指出的任务的上下文
*                 d_ Execute the task.执行任务
*********************************************************************************************************
*/void  OSStart(void)                               /*启动多个任务*/
{if (OSRunning == OS_FALSE) {               /*此时没有多任务*/OS_SchedNew();                           /* Find highest priority's task priority number 找到最高优先级的任务优先级号  */OSPrioCur = OSPrioHighRdy;                 /*将最高优先级任务的优先级号作为当前要执行任务的优先级号*/OSTCBHighRdy = OSTCBPrioTbl[OSPrioHighRdy]; /* Point to highest priority task ready to run 指向将要运行的最高优先级任务   */OSTCBCur = OSTCBHighRdy;               /*将高优先级任务的TCB作为当前TCB*/OSStartHighRdy();                        /* Execute target specific code to start task执行代码开始任务     */}
}

将上述代码总结为如图所示流程:

OSStatInit()统计任务初始化函数:

/*$PAGE*/
/*
*********************************************************************************************************
*                                        STATISTICS INITIALIZATION
*                                           统计任务初始化
* Description: This function is called by your application to establish CPU usage by first determining
*              how high a 32-bit counter would count to in 1 second if no other tasks were to execute
*              during that time.  CPU usage is then determined by a low priority task which keeps track
*              of this 32-bit counter every second but this time, with other tasks running.  CPU usage is
*              determined by:
*            统计初始化函数OSStatInit()决定在没有其它应用任务运行时,空闲计数器(OSIdleCtr)的计数有多快。这个任务每秒执行一次,以确定所有应用程序中的任务消耗了多少CPU时间。当用户的应用程序代码加入以后,运行空闲任务的CPU时间就少了,OSIdleCtr就不会像原来什么任务都不运行时有那么多计数。要知道,OSIdleCtr的最大计数值是OSStatInit()在初始化时保存在计数器最大值OSIdleCtrMax中的。
*                                             OSIdleCtr
*                 CPU Usage (%) = 100 * (1 - ------------)
*                                            OSIdleCtrMaxCPU使用率(百分比形式)=100*(1-空闲计数值/设定最大空闲计数值)
*
* Arguments  : none
*
* Returns    : none
*********************************************************************************************************
*/#if OS_TASK_STAT_EN > 0u
void  OSStatInit(void)                          /*统计任务初始化*/
{
#if OS_CRITICAL_METHOD == 3u                     /* Allocate storage for CPU status register 中断函数被设定为模式3          */OS_CPU_SR  cpu_sr = 0u;
#endifOSTimeDly(2u);                               /* Synchronize with clock tick调用延迟函数OSTimeDly()将自身延时2个时钟节拍以停止自身的运行,这是为了使OSStatInit()与时钟节拍同步                        */OS_ENTER_CRITICAL();                      /*关闭中断(进入中断)*/OSIdleCtr = 0uL;                            /* Clear idle counter 执行OSStartInit()时,空闲计数器OSIdleCtr被清零*/OS_EXIT_CRITICAL();                            /*打开中断*/OSTimeDly(OS_TICKS_PER_SEC / 10u);           /* Determine MAX. idle counter value for 1/10 second确定最大空闲计数值为1或10s  */OS_ENTER_CRITICAL();                        /*关闭中断*/OSIdleCtrMax = OSIdleCtr;                    /* Store maximum idle counter count in 1/10 second 存储最大空闲计数值   */OSStatRdy = OS_TRUE;                      /*将统计任务就绪标志OSStatRdy设为"真",以此来允许两个时钟节拍以后OSTaskStat()开始计算CPU的利用率*/OS_EXIT_CRITICAL();                          /*打开中断*/
}
#endif

OSTimeTick()时钟节拍函数:

/*$PAGE*/
/*2018/2/3~2/7
*********************************************************************************************************
*                                         PROCESS SYSTEM TICK
*                                           时钟节拍函数
* Description: This function is used to signal to uC/OS-II the occurrence of a 'system tick' (also known
*              as a 'clock tick').  This function should be called by the ticker ISR but, can also be
*              called by a high priority task.
*该功能是用来给uc/os发送时钟信号。该功能称为时钟中断,也叫做高优先级任务
* Arguments  : none
*
* Returns    : none
*********************************************************************************************************
*/void  OSTimeTick(void)                                    /*时钟节拍函数*/
{OS_TCB    *ptcb;                                   /*指向TCB列表的的指针*/
#if OS_TICK_STEP_EN > 0uBOOLEAN    step;                                 /*设置一个布尔型变量*/
#endif
#if OS_CRITICAL_METHOD == 3u                               /* Allocate storage for CPU status register中断函数被设定为模式3     */OS_CPU_SR  cpu_sr = 0u;
#endif#if OS_TIME_TICK_HOOK_EN > 0u                             /*可以生成时钟钩子函数OS_TIME_TICK_HOOK()*/OSTimeTickHook();                                      /* Call user definable hook 调用用户自定义钩子函数                    */
#endif
#if OS_TIME_GET_SET_EN > 0u                                 /*可以生成OS_TIME_GET_SET()函数*/OS_ENTER_CRITICAL();                                   /* Update the 32-bit tick counter  更新32位节拍数,关中断             */OSTime++;                                            /*/累加从开机以来的时间,用的是一个无符号32位变量*/OS_EXIT_CRITICAL();                                     /*开中断*/
#endifif (OSRunning == OS_TRUE) {
#if OS_TICK_STEP_EN > 0uswitch (OSTickStepState) {                     /* Determine whether we need to process a tick步进的状态:决定我们是否需要处理节拍  */case OS_TICK_STEP_DIS:                         /* Yes, stepping is disabled 步进被禁用 */step = OS_TRUE;                                break;case OS_TICK_STEP_WAIT:                        /* No,  waiting for uC/OS-View to set ...步进等待状态:等待uC/OS-View将步进状态设置成进一步*/step = OS_FALSE;                          break;case OS_TICK_STEP_ONCE:                        /* Yes, process tick once and wait for next ...步进一次等待下一步命令 */step = OS_TRUE;                                /*... step command from uC/OS-View步进命令来自于uc/os-view*/OSTickStepState = OS_TICK_STEP_WAIT;       /*将步进状态设置为步进等待状态*/break;default:                                       /* Invalid case, correct situatio无效的情况或者正确的情况下*/step = OS_TRUE;                          OSTickStepState = OS_TICK_STEP_DIS;        /*将步进状态设置为禁止状态*/break;}if (step == OS_FALSE) {                            /* Return if waiting for step command如果正在等待步进命令,返回*/return;}
#endifptcb = OSTCBList;                                  /* Point at first TCB in TCB list 指向TCB列表的第一个*/while (ptcb->OSTCBPrio != OS_TASK_IDLE_PRIO) {     /* Go through all TCBs in TCB list 浏览TCB列表的所有TCB*/OS_ENTER_CRITICAL();                            /*进入中断*/if (ptcb->OSTCBDly != 0u) {                    /* No, Delayed or waiting for event with TO等待任务时的最多节拍数不为0*/ptcb->OSTCBDly--;                          /* Decrement nbr of ticks to end of delay时间延迟项减1*/if (ptcb->OSTCBDly == 0u) {                /* Check for timeout减1后检查是否到时间了。时间延迟项等于0,就转为就绪态(外部条件准备就绪)*/if ((ptcb->OSTCBStat & OS_STAT_PEND_ANY) != OS_STAT_RDY) {    /*(检查内部条件是否准备就绪)如果TCB状态和挂起状态进行位与运算之后不等于准备好的状态,简单来说就是任务没有准备好*/ptcb->OSTCBStat &= (INT8U)~(INT8U)OS_STAT_PEND_ANY;          /* Yes, Clear status flag清除状态标志*/ptcb->OSTCBStatPend = OS_STAT_PEND_TO;                 /* Indicate PEND timeout将TCB挂起状态设置为超时状态*/}else {                                       /*如果是已准备好的状态(内部条件准备就绪)*/ptcb->OSTCBStatPend = OS_STAT_PEND_OK;/*就将TCB挂起状态设置为挂起结束(正常结束)状态*/}if ((ptcb->OSTCBStat & OS_STAT_SUSPEND) == OS_STAT_RDY) {  /* Is task suspended? 查看任务是否为挂起状态*/OSRdyGrp |= ptcb->OSTCBBitY;             /* No,  Make ready如果不是(即已为就绪态),在就绪表中找到具体的任务控制块*/OSRdyTbl[ptcb->OSTCBY] |= ptcb->OSTCBBitX;}}}ptcb = ptcb->OSTCBNext;                        /* Point at next TCB in TCB list指向TCB列表的下一个 */OS_EXIT_CRITICAL();                              /*退出中断(开中断)*/}}
}

同时介绍一下相关的时间管理方面的内容:http://blog.csdn.net/adam_embedded/article/details/46323491

1.1 时钟节拍

UCOSii通过时钟节拍OSTimeTick()来定期进行任务调度,一般来说这个频率是10-100HZ,频率越高,系统的开销也就越大。

1.2 任务延时函数

OSTimeDly()

任务可以调用OSTimeDly()来对自身延时一段时间。延时时,任务被挂起。任务被延时的时间必须是时钟节拍的倍数。与延时有关的变量在Tcb结构体中。

Tcb.OSTCBDly表示任务自己延时挂起的时间。

这样,当任务调用OSTimeDly()来进行延时时,该函数会修改修改OSTCBDly的值,把要延时的次数写入该变量,最后进行任务调度即可。

每次时钟节拍发生的时候,OSTCBDly的值都会被减去一,当该值为0的时候,内核就会把它放入就绪队列。

NOTE: 当调用OSTimeDly(1)只延时一个时钟节拍的时候,由于任务可能运行在一个时钟节拍的中后期,此时经过不到半个时钟节拍的时间,OSTCBDly的值就会被修改。因此,如果用户的应用程序至少得延时一个节拍,必须要调用 OSTimeDly(2),指定延时两个节拍。(即指定延时1,延时可能不足1,但是指定延时为2,至少可以保证延时一个节拍)。

来看一下OSTimeDly()的结构和原型:

结构:

void OSTimeDly(OS_TICK dly,//指定延时的长度,单位为时间节拍OS_OPT opt,//延时模式OS_ERR *p_err//错误信息
)
  • 如果延时时间dly>0,则会发生任务调度;0表示不延时
  • OSTimeDly()函数延时模式有四种:OS_OPT_TIME_DLY;OS_OPT_TIME_TIMEOUT;OS_OPT_TIME_PERIODIC;OS_OPT_TIME_MATCH;
函数原型:
void OSTimeDly (INT16U ticks)
{if (ticks > 0) {OS_ENTER_CRITICAL();if ((OSRdyTbl[OSTCBCur->OSTCBY] &= ~OSTCBCur->OSTCBBitX) == 0) {OSRdyGrp &= ~OSTCBCur->OSTCBBitY;}   OSTCBCur->OSTCBDly = ticks;OS_EXIT_CRITICAL();OSSched();}
}

可以看到该函数将延时次数传递给了OSTCBDly。

OSTimeDly()有一些缺点:一是只能延时65535次时钟节拍,二是不能换算成时间。

1.3 结束任务延时函数

OSTimeDlyResume()函数可以被用来强制某一任务结束延时,它的主要作用是支持任务之间的通讯和同步。

OSTimeDlyResume()要做的就是将OSTCBDly清0,然后进行任务调度。

1.4 系统时间

每次发生时钟节拍时,UCOS都会将一个32位的计数器加1。

OSTimeGet()和 OSTimeSet()用来获取或者设置这个计数器的值。

OS_CORE.C(8)相关推荐

  1. OS_CORE.C(11)

    OS_SchedNew(void)找到将要运行的最高优先级任务函数 和任务调度函数OS_Sched(void): /* **************************************** ...

  2. OS_CORE.C(10)

    今天看os_core.c文件中的各种初始化函数. OS_EventWaitListInit(OS_EVENT *pevent)初始化事件控制块的等待列表: /*$PAGE*/ /*2018/2/8 * ...

  3. OS_CORE.C(总结)

    在内核的功能模块中,重点函数为: static  void  OS_InitEventList(void);/*初始化事件列表*/ static  void  OS_InitMisc(void);/* ...

  4. OS_CORE.C(1)

    第一个函数(获得信号量.互斥量.邮箱或者队列名字的函数)的流程图和分析图如下所示: /*$PAGE*/ /* ********************************************* ...

  5. OS_CORE.C(9)

    本篇介绍以下几个函数: OSVersion()获得版本号函数. OS_Dummy()虚拟函数. OS_EventTaskRdy (OS_EVENT *pevent, void *msg, INT8U ...

  6. OS_CORE.C(6)

    先介绍一下优先级反转的相关知识: 优先级翻转是当一个高优先级任务通过信号量机制访问共享资源时,该信号量已被一低优先级任务占有,因此造成高优先级任务被许多具有较低优先级任务阻塞,实时性难以得到保证. 例 ...

  7. OS_CORE.C(5)

    /*$PAGE*/ /* *************************************************************************************** ...

  8. OS_CORE.C(3)

    OSTCBCur->OSTCBStat |= events_stat | /* Resource not available, ...无法获得资源的话就将其挂起 */OS_STAT_MULTI; ...

  9. OS_CORE.C(7)

    本篇介绍的是调度器的上锁和解锁: 调度器上锁函数OSSchedlock()的功能是用于禁止任务调度,使任务保持对CPU的控制权. 调度器开锁函数OSSchedUnlock()的功能是解除对任务调度的禁 ...

最新文章

  1. 关于图片上传的个人摘要
  2. 《当程序员的那些狗日日子》(十五)首次接单
  3. sqlserver 安装_安装sqlserver
  4. python数组合并、输入三行数据,如何在python中合并两个或三个3D数组?
  5. 190729知识笔记
  6. poj2955 Brackets (区间dp)
  7. Python进阶(六)文件操作
  8. JS学习总结(13)——DOM
  9. as5300g2 nas软件功能_浪潮AS5300G2 5500G2存储2U12
  10. c语言 队列方法的编写
  11. 《基于机器视觉的高压输电线路覆冰厚度检测》论文笔记
  12. python修改pdf元信息 metadata
  13. 程序员30+后的困惑焦虑,出路在哪里?
  14. Trie——51nod1526 分配笔名
  15. css3 3d特效汇总
  16. 弹跳机器人 桌游_「桌游推荐」我的机器人哪有这么厉害
  17. 写网页设计与制作的博雅互动的作业
  18. 小尺寸android 手机推荐,目前最值得买的4款小屏手机, 懂行的人才会买, 小屏爱好者福音!...
  19. CTF Web入门 命令执行 笔记
  20. Android 30. 广播-Broadcast(一)

热门文章

  1. oracle 对象管理 01_用户及权限
  2. C语言:画一个爱心 送女票
  3. QTP整合QC自动化测试--目录结构搭建
  4. 小巧密码破解工具IE PassView使用指南
  5. 链路层的封装方式与IP选路 (二)
  6. So easy!Nginx+SpringBoot 实现负载均衡
  7. 不小心执行了 rm -f,先别急着跑路
  8. Stack:peek、pop、push、search
  9. Java 洛谷 P2141 珠心算测验
  10. 2013年计算机专业对口模拟试题二,计算机对口升学模拟试题全解.doc